T-Sql Dynamic Query String Limit - sql

I am getting a weird exception saying "
"
Msg 203, Level 16, State 2, Line 53
The name 'SELECT
ISNULL(ESP.ID,-1) AS 'PayScaleID',
ISNULL(E.Prefix,'') + ISNULL(E.SerialNo,0) AS 'Token number',
ISNULL(E.FirstName,'')+' '+ ISNULL(E.MiddleName,'')+' '+ISNULL(E.LastName,'') AS 'Employee name',
ISNULL(E.CostCentreCode,'') AS 'Cost centre code',
ESP.TotalPresentDays AS 'Present days',
ESP.TotalWeeklyOffDays AS 'Week offs',
ESP.TotalPaidHolidays AS 'Paid holiDays',
ESP.TotalAbsentDays AS 'Absent days',
ESP.ArrearDays AS 'Arrear days',
ESP.OTHours AS 'OTHours',
ESP.TotalPaidAmount AS 'Total Amount',
MAD.Name AS 'Allowance' ,
X.Amount
INTO #temp
FROM
(
SELECT
-1 AS 'BillingI' is not a valid identifier."
I am executing the following query.
"
{
DECLARE #sql AS VARCHAR(8000)
SET #sql = 'SELECT
ISNULL(ESP.ID,-1) AS ''PayScaleID'',
ISNULL(E.Prefix,'''') + ISNULL(E.SerialNo,0) AS ''Token number'',
ISNULL(E.FirstName,'''')+'' ''+ ISNULL(E.MiddleName,'''')+'' ''+ISNULL(E.LastName,'''') AS ''Employee name'',
ISNULL(E.CostCentreCode,'''') AS ''Cost centre code'',
ESP.TotalPresentDays AS ''Present days'',
ESP.TotalWeeklyOffDays AS ''Week offs'',
ESP.TotalPaidHolidays AS ''Paid holiDays'',
ESP.TotalAbsentDays AS ''Absent days'',
ESP.ArrearDays AS ''Arrear days'',
ESP.OTHours AS ''OTHours'',
ESP.TotalPaidAmount AS ''Total Amount'',
MAD.Name AS ''Allowance'' ,
X.Amount
INTO #temp
FROM
(
SELECT
-1 AS ''BillingID'',
ESP.ID AS ''EmployeeSalaryPaidID'',
MAd.ID AS ''AllowanceID'',
ESPD.PaidAmount AS ''Amount''
FROM Employee_SalaryPaid ESP
INNER JOIN Employee_SalaryPaidDetails ESPD ON ESPD.EmployeeSalaryPaidID = ESP.ID
INNER JOIN Employee E ON E.ID = ESP.EmployeeID
INNER JOIN Master_AllowanceDeduction MAD ON MAD.ID = ESPD.AllowanceDeductionID
WHERE ESP.YearAndMonth =201104
UNION ALL
SELECT
CBR.ID AS ''BillingID'',
CBRD.EmployeeSalaryPaidID,
CBRD.AllowanceDeductionID AS ''AllowanceID'',
CBRD.Amount AS ''Amount''
FROM Company_BillRaised CBR
INNER JOIN Company_BillRaisedDetails CBRD ON CBRD.BillRaisedID = CBR.ID
WHERE CBR.MonthYear =201104
)X
INNER JOIN Master_AllowanceDeduction MAD ON MAD.ID = X.AllowanceID
INNER JOIN Employee_SalaryPaid ESP ON ESP.ID =X.EmployeeSalaryPaidID
INNER JOIN Employee E ON E.ID= ESP.EmployeeID
INNER JOIN dbo.vw_CompanyEmployeeIDs CE ON CE.EmployeeID = E.ID
WHERE CE.BranchID =73
DROP TABLE #temp'
EXEC #sql
}
I cannot understand what exactly the problem is? Do we have some limits of characters while executing Dynamic Sql like I am doing. I tried printing what I am getting in #Sql, I can get the results what I am looking for. But when I go like this using EXEC #Sql it gives me the error.
Any suggestions?

Try
Declaring #sql as nvarchar(max)
then
exec sp_executesql #sql
instead of
exec #sql
Executing dynamic sql with just exec is very limited. See this link http://www.sommarskog.se/dynamic_sql.html.

Try changing your last line to EXEC (#sql).
Execute a character string
{ EXEC | EXECUTE }
( { #string_variable | [ N ]'tsql_string' } [ + ...n ] )
[ AS { LOGIN | USER } = ' name ' ]
[;]
Source:
EXECUTE (Transact-SQL)

You can use:
Execute or exec: EXEC (#sql)
The system stored procedure sp_execute. Benefits: can use additional parameters in the syntax and validate the data types before execution: execute sp_execute #sql

Related

The identifier that starts with (query) Maximum length is 128

Problem: I am using a sp on sql server where I took parameter which modify the query and then run the full query in the server. While I am passing that parameter to sp then it says: "The identifier that starts with 'WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-001' is too long. Maximum length is 128."
THE QUERY:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[get_SupComProducts] #whereClause NVARCHAR(max)
AS
BEGIN
DECLARE #query NVARCHAR(max)
, #status VARCHAR(25);
SET #status = 'IN'
SET #query = 'SELECT DISTINCT
p.ProductId,
p.CompanyId,
p.ProductName,
p.ProductGrossWeight,
p.ProductNetWeight,
p.ProductUnit,
p.CategoryId,
p.BrandId,
p.ProductBarcode,
p.MinShelfLife,
p.ProductMargin,
p.IsWeighted,
p.PVAT,
p.ProductMargin,
p.AFSProduct,
ISNULL(sp.ProductBarcode, 0) AS Barcode,
ISNULL(sp.CostPrice, 0) AS CostPrice,
ISNULL(sp.TradePrice, 0) AS TradePrice,
ISNULL(sp.MRP, 0) AS MRP,
ISNULL(sp.SellingPrice, 0) AS SellingPrice,
ISNULL(sp.VAT, 0) AS VAT,
ISNULL((
SELECT SUM(ProductQty) AS ProductQty
FROM StockDetails
WHERE ProductId = p.ProductId AND [Status]= ''' + #status + '''' +
'),0) AS CurrentStock
FROM Supplier d
JOIN Product p
ON p.CompanyId = d.CompanyId
LEFT JOIN StockDetails sd
ON sd.ProductId = p.ProductId
LEFT JOIN SupplierProduct sp
ON sp.ProductId = p.ProductId ' + #whereClause
EXEC (#query)
END
GO
Please if there are any resolve you guys know already, it will be much appreciable. Thanks in advance.
SP EXEC:
EXEC [dbo].[get_SupComProducts] #whereClause="WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-00123'"
If I remove any of the AND query then it works, but the full query says the error.
Msg 103, Level 15, State 4, Line 1
The identifier that starts with 'WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-001' is too long. Maximum length is 128.
While there might be issues with your procedure, this particular one comes from the way you call it. Double quotes in SQL, by default, designate object names, and in MS SQL Server, maximum length for any object name is 128 characters. That's where you are getting this error, I suspect.
So, in your sp call, you need to replace your double quotes with single ones, and appropriately escape all single quotes inside it. Something like this:
EXEC [dbo].[get_SupComProducts] #whereClause = '
WHERE
d.LastModified<1676270281779 AND (
p.ProductName LIKE ''%2004%''
OR p.ProductBarcode LIKE ''%2004%''
) AND d.SupplierId=''SUP-00123''
';

Concatenate query string in procedure having case statement with parameter

I need to append below select query set with another set query based on condition
DECLARE #queryString VARCHAR(1000);
-- Insert statements for procedure here
Set #queryString ='SELECT
CASE
WHEN d.sno IS NOT NULL THEN 'y'
ELSE NULL
END
amendment_type,
u.user_login_id [User],
role_name [Role],
u.user_name [Name],
a.companyname +':<br>('+b.branch+')' [Agent/Branch],
u.last_login_pc+'('+u.ip_address+')<br> Login Time: '+cast(u.last_login AS varchar(50)) [Last Login],
u.lock_status [Lock/Unlock],
CASE
WHEN u.lock_status='y' THEN 'Locked - '+ u.lock_by
WHEN datediff(d,u.last_login,getdate())>u.lock_days
AND isnull(u.lock_days,0)>0 THEN 'Locked - Day Exceed'
WHEN u.active_session IS NULL
AND isnull(u.lock_status,'n')='n' THEN 'Not Login'
ELSE 'Active'
END
[Status],
u.*,
a.agentcan,
b.branch,
b.branchcodechar,
NULL branchcan
FROM agentsub u
JOIN agentbranchdetail b
ON u.agent_branch_code=b.agent_branch_code
JOIN agentdetail a
ON b.agentcode=a.agentcode
LEFT OUTER JOIN application_role_agent_user r
ON u.user_login_id=r.user_id
LEFT OUTER JOIN application_role p
ON r.role_id=p.role_id
LEFT OUTER JOIN agentsub_amendment d
ON d.agent_user_id=u.agent_user_id
WHERE 1=1'
IF (#loginId !=null)
BEGIN
SET #queryString =#queryString + 'and u.user_login_id like ('+ #loginId +')'
END
SET #queryString =#queryString +'order by u.user_login_id,a.companyname,b.branch'
EXEC #queryString
First... Your query as it stands (via notepad++) is 1,731 characters, so it wont fit into a varchar(1000)
Second... You need to address some escaping issues with your query; e.g.
WHEN d.sno IS NOT NULL THEN 'y'
should probably be
WHEN d.sno IS NOT NULL THEN ''y''
Third... google/investigate sp_executesql and parameters
Finally... as #Panagiotis Kanavos says, Don't concatenate anything (see Third...); you need to look up "sql injection"
#uberbloke is correct regarding query length.
EXEC sp_executesql with multiple parameters link give you solution for dynamic query to pass parameter values.
Please check below updated query code.
DECLARE #queryString NVARCHAR(MAX);
-- Insert statements for procedure here
Set #queryString =
'SELECT
CASE
WHEN d.sno IS NOT NULL THEN ''y''
ELSE NULL
END
amendment_type,
u.user_login_id [User],
role_name [Role],
u.user_name [Name],
a.companyname + '':<br>('' + b.branch) [Agent/Branch],
u.last_login_pc + ''('' + u.ip_address + '')<br> Login Time: '' + cast(u.last_login AS varchar(50)) + '' [Last Login],
u.lock_status [Lock/Unlock],
CASE
WHEN u.lock_status = ''y'' THEN ''Locked - '' + u.lock_by
WHEN datediff(d,u.last_login,getdate()) > u.lock_days AND (u.lock_days,0) > 0 THEN ''Locked - Day Exceed''
WHEN u.active_session IS NULL AND isnull(u.lock_status,''n'') = ''n'' THEN ''Not Login''
ELSE ''Active''
END [Status],
u.*,
a.agentcan,
b.branch,
b.branchcodechar,
NULL branchcan
FROM agentsub u
JOIN agentbranchdetail b ON u.agent_branch_code = b.agent_branch_code
JOIN agentdetail a ON b.agentcode = a.agentcode
LEFT OUTER JOIN application_role_agent_user r ON u.user_login_id = r.user_id
LEFT OUTER JOIN application_role p ON r.role_id = p.role_id
LEFT OUTER JOIN agentsub_amendment d ON d.agent_user_id = u.agent_user_id
WHERE 1 = 1 '
IF (#loginId !=null)
BEGIN
SET #queryString = #queryString + 'and u.user_login_id like ('+ #loginId + ')'
END
SET #queryString = #queryString + ' order by u.user_login_id,a.companyname,b.branch'
EXEC sp_executesql #queryString
I am getting below error:

While executing my stored procedure, I'm getting this error while my input is multiple values [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
This is my SP.
I'm getting this error - "Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
enter code here
ALTER PROCEDURE GetToDoDetails
#ClientID VARCHAR(MAX) = NULL
AS
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE(#ClientID,',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) "CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
EXEC (#Sql)
GO
If I write
EXEC GetToDoDetails '1566'
, I'm getting this result(refer image)
Now if I write
EXEC GetToDoDetails '1566,1697'
It is showing the error which I told about.
After Adding TOP 1 in my subquery as
(Select TOP 1 count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID + ''')
I'm getting the count for first record only for different clientIDs(1566 & 1697).(refer image)
After the 45th record for ClientID=1566(total row count is 45 for 1566),
I want the count to change for ClientID=1697(which is 63).
I don't know how to approach this. I'm a newbie. Please help.
There's some guess work in there, however, SQL Injection is not your friend. That needs to go, NOW. I've therefore used a Table Type Parameter instead.
In regards to the error, that was due to the statement:
(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) "CountRow"
This'll return multiple rows if you had more than one value in #ClientID. Also, the quote operator in SQL Server for an object is a bracket ([]), not double quotes (").
Anyway, this is a guess, but this should get you on the right path (I hope):
CREATE TYPE ClientList AS TABLE (ClientID int); --Datatype is GUESSED
GO
CREATE PROCEDURE GetToDoDetails #Client ClientList READONLY
AS
SELECT C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName + ',' + CL.FirstName) AS [Client Name],
COUNT(C.ClientID) OVER (PARTITION BY C.ClientID) AS [CountRow] --Total guess here
--If this is meant to just be a count of EVERY row, remove the PARTITION BY clause (so just OVER())
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
WHERE EXISTS (SELECT 1 FROM #Client e WHERE C.ClientID = e.ClientID) --Changed from IN to EXISTS
ORDER BY C.ClientID ASC;
GO
It is not ideal to have a subquery in select statement for count, In your query you are getting multiple values as client id has multiple values, I would prefer to bring it down in join statement. Print #sql should work to check if statement is valid. This will do the trick for you
DECLARE #ClientID VARCHAR(MAX) = NULL
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE('1566,1697,2467',',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
"CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) CO
on C.ClientID = CO.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
PRINT (#Sql)
Your SP:
ALTER PROCEDURE GetToDoDetails
#ClientID VARCHAR(MAX) = NULL
AS
BEGIN
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE(#ClientID,',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
"CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) CO
on C.ClientID = CO.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
PRINT (#Sql)
EXEC (#Sql)
END

Getting Conversion failed error in stored procedure

I don't know anything about procedure, but I have to create one so I tried one. But now I am getting error - please help.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Get_List_Docter_Detail_A]
#special varchar(MAX),
#city varchar(MAX),
#offset int,
#pageSet int,
#area varchar(MAX)
AS
Begin
declare #sql nvarchar(MAX);
set #sql = 'SELECT'+
'(SELECT Stuff('+
'(SELECT N"," + sp.specialization FROM DSpecialization_Master dsp'+
'LEFT JOIN Specialization_Master sp on sp.id = dsp.specialization'+
'WHERE dsp.profileid = pm.id and (dsp.specialization = (select id from Specialization_master where specialization='+#special+'))'+
'FOR XML PATH(""),TYPE)'+
'.value("text()[1]","nvarchar(max)"),1,1,N"")) as drspec,'+
'pm.id as profileid,'+
'pm.loginid as loginid,'+
'dam.clinicname,'+
'dam.area,'+
'dam.address,'+
'dam.pincode,'+
'dam.id as addressid,'+
'dam.feecharge as feecharge,'+
'pm.fname,'+
'pm.lname,'+
'pm.email,'+
'pm.mobile,'+
'pm.phone,'+
'pm.gender,'+
'pm.dob,'+
'pm.totexp,'+
'pm.imagepath,'+
'pm.languages,'+
'pm.statement,'+
'pm.createdby,'+
'convert(nvarchar, pm.createdon, 103) as createddate,'+
'convert(nvarchar, pm.createdon, 108) as createdtime,'+
'pm.hsbit,'+
'overall_count = COUNT(*) OVER(),'+
'(SELECT Stuff('+
'(SELECT N"," + education FROM DEducation_Master WHERE profileid = pm.id'+
'FOR XML PATH(""),TYPE)'+
'.value("text()[1]","nvarchar(max)"),1,1,N"")) as dredu'+
'FROM Profile_Master pm '+
'LEFT JOIN DAddress_Master dam on dam.profileid = pm.id '+
'WHERE '+
'dam.city='+#city;
if #area!=''
set #sql+=' and dam.area in('+#area+') and';
set #sql+=' pm.id IN (SELECT profileid FROM DSpecialization_Master WHERE specialization = (select id from Specialization_master where specialization='+#special+')) ORDER BY dam.city OFFSET '+#offset+' ROWS FETCH NEXT '+#pageSet+' ROWS ONLY';
EXECUTE sp_executesql #sql
END
I am getting this error.
Msg 245, Level 16, State 1, Procedure Get_List_Docter_Detail_A, Line 61
Conversion failed when converting the nvarchar value 'SELECT(SELECT Stuff((SELECT N"," + sp.specialization FROM DSpecialization_Master dspLEFT JOIN Specialization_Master sp on sp.id = dsp.specializationWHERE dsp.profileid = pm.id and (dsp.specialization = (select id from Specialization_master where specialization=Dentist))FOR XML PATH(""),TYPE).value("text()[1]","nvarchar(max)"),1,1,N"")) as drspec,pm.id as profileid,pm.loginid as loginid,dam.clinicname,dam.area,dam.address,dam.pincode,dam.id as addressid,dam.feecharge as feecharge,pm.fname,pm.lname,pm.email,pm.mobile,pm.phone,pm.gender,pm.dob,pm.totexp,pm.imagepath,pm.languages,pm.statement,pm.createdby,convert(nvarchar, pm.createdon, 103) as createddate,convert(nvarchar, pm.createdon, 108) as createdtime,pm.hsbit,overall_count = COUNT(*) OVER(),(SELECT Stuff((SELECT N"," + education FROM DEducation_Master WHERE profileid = pm.idFOR XML PATH(""),TYPE).value("text()[1]","nvarchar(max)"),1,1,N"")) as dreduFROM Profile_Master pm LEFT JOIN DAddress_Master dam on dam.profileid = pm.id WHERE dam.city=surat and dam.area in(Adajan) and' to data type int.
What am I doing wrong? Please correct me.
Try to replace double quotas with double single quotas
Replace this line
'(SELECT N"," + sp.specialization
With
'(SELECT N'','' + sp.specialization

Cannot specify an index or locking hint for a remote data source SQL Server 2005

I have this query which involves a table from another server:
select count(serialno), max(convert(varchar(10),Crtd_DateTime,101))
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
inner join [server_2].fdb.dbo.sns_in_out sio
on tsb.serialno = sio.lotsernbr and invtMult='-1' and RefNbr like 'I%'
where tmb.WO=34612
but this query is taking forever, and I cannot specify an index or locking hint for a remote data source, so I looked into the web and I found out that I can use this:
SELECT * FROM OpenQuery(server, 'Select * from sometable with (nolock)')
Which works fine, but as you can see I have a link between tsb.serialno and sio.lotsernbr, and when I place all that inside the '' like the following:
select serialno,
(SELECT *
FROM OpenQuery([server_2], 'select convert(varchar(10), Crtd_DateTime, 101)
from fdb.dbo.sns_in_out sio (nolock)
where (tsb.serialno = sio.lotsernbr
and invtMult=''-1'' and RefNbr like ''I%'')')) as crtDate
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
where tmb.WO=34612
I get this error:
[OLE/DB provider returned message: Deferred prepare could not be
completed.]
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "tsb.serialno" could not be bound.
Any idea of how to accomplish this?
If you want to run queries with (NOLOCK) on a remote server, create a stored procedure or view on the remote server and apply the locking hint there.
If you have no access to the remote server, you could pull the data first by executing something like this through a linked server (I'll assume your linked server is called server_2):
CREATE TABLE #loc (lotsernbr INT, dt DATETIME);
INSERT #loc
EXEC [server_2].fdb..sp_executesql 'SELECT lotsernbr, Crt_DateTime
FROM dbo.sns_in_out WITH (NOLOCK)
WHERE invtMult=''-1'' AND RefNbr LIKE ''I%'';';
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- much better than nolock on every table
SELECT tsb.serialno, crtDate = CONVERT(CHAR(10), loc.dt, 101)
FROM tblSBox AS tsb
INNER JOIN #loc AS loc
ON tsb.serialno = loc.lotsernbr
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612;
Now you can join against the local #temp table. The difference may be negligible but it may be significant. If this brings across a lot of rows and you only need a few, you may want to do it slightly differently: build your IN list dynamically and pass it to the other server, e.g.
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + ',' + CONVERT(VARCHAR(12), serialno)
FROM tblSBox AS tsb
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612
GROUP BY serialno; -- to avoid dupes
SET #sql = N'SELECT serialno = lotsernbr, crtDate = CONVERT(CHAR(10), Crt_Datetime, 101)
FROM fdb.dbo.sns_in_out WITH (NOLOCK)
WHERE lotsernbr IN (' + STUFF(#sql, 1, 1, N'') + ');'
-- now you don't need the join, since you are only outputting
-- the two columns:
EXEC [server_2].fdb..sp_executesql #sql;