问题
I have this dynamic SQL in a stored procedure:
Declare @template nvarchar(max)
Declare @publishdetails nvarchar(max)
set @publishdetails= ',B.[PublishedBy]=suser_name(),
B.[PublishedDate]=GETDATE() '
set @template='if NOT EXISTS(select * from ' +@DestinationDB+ '.[CLs] where id='+ str(@slid)+')
insert into ' +@DestinationDB+ '.CLs (id,slid,slversion) VALUES ( '+ str(@id)+','+ str(@slid)+','+str(@slversion)+')
update B set
B.[Clientid]=A.clientid,
--.........
B.[CreatedDate] = A.CreatedDate,
B.[ModifiedDate] = A.ModifiedDate,
B.[CreatedBy] = A.CreatedBy,
B.[ModifiedBy] = A.ModifiedBy '+@publishdetails+ --Added publishdetails
'FROM ' + @SourceDB + '.[CLs] as A, '+ @DestinationDB+ '.[CLs] as B
where A.slversion = '+ str(@slversion)+' and A.id='+str(@slid) + 'B.slversion = '+ str(@slversion)+' and B.id='+str(@slid)
print 'template is: ' + @template
exec sp_Executesql @template
When exec sp_Executesql @template
is executing, it fails. Because @template
is > 4000 chars and is truncated. How can I split it in chunks and execute it the correct way?
回答1:
You don't need to split the text into parts. You do need to make sure that truncation doesn't occur whilst you're concatenating strings:
If the result of the concatenation of strings exceeds the limit of 8,000 bytes, the result is truncated. However, if at least one of the strings concatenated is a large value type, truncation does not occur.
So, make sure that the first concatenation is working with a large value type (and thus produces a large value type as its result) and every subsequent concatenation should be saved from truncation:
set @template=CONVERT(nvarchar(max),'if NOT EXISTS(select * from ' ) + @DestinationDB + ...
(In this way, you don't have to insert conversions everywhere)
This generates an error:
declare @t nvarchar(max)
set @t = 'select LEN(''' + REPLICATE('A',3000) + REPLICATE('B',3000) + REPLICATE('C',3000) + ''')'
exec sp_executesql @t
And this produces the result 9000:
declare @t nvarchar(max)
set @t = CONVERT(nvarchar(max),'select LEN(''') + REPLICATE('A',3000) + REPLICATE('B',3000) + REPLICATE('C',3000) + ''')'
exec sp_executesql @t
回答2:
I suggest to use this approach:
Declare @template nvarchar(max) = N''
set @template = @template +N'.... -- Or SELECT instead of SET
Update#1
I run this simple query on my test DB:
DECLARE @query nvarchar(max) = N'',
@i int = 1
WHILE 1000 > @i
BEGIN
SET @query = @query + N'SELECT @@version;'
SET @i = @i+1
END
SELECT LEN (@query)
EXEC sp_executesql @query
I got batch with length of 16983 characters. And execution goes well - no truncation. I guess the problem is inside @SourceDB + '.[CLs]
and @DestinationDB+ '.[CLs]
tables. Somewhere there you got data truncation.
Try to PRINT
your query and run it manually.
来源:https://stackoverflow.com/questions/47629908/sql-server-2012-dynamic-sql-limitation-4000-chars-split