SQL Server 2012: dynamic SQL limitation ( > 4000 chars) (split)

帅比萌擦擦* 提交于 2019-12-24 23:20:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!