如何使用打印语句打印VARCHAR(MAX)?

我有一个代码是:

DECLARE @Script VARCHAR(MAX) SELECT @Script = definition FROM manged.sys.all_sql_modules sq where sq.object_id = (SELECT object_id from managed.sys.objects Where type = 'P' and Name = 'usp_gen_data') Declare @Pos int SELECT @pos=CHARINDEX(CHAR(13)+CHAR(10),@script,7500) PRINT SUBSTRING(@Script,1,@Pos) PRINT SUBSTRING(@script,@pos,8000) 

脚本的长度大约是10,000个字符,因为我使用的print语句只能容纳最多8000个字符。所以我使用了两个打印语句。

问题是当我有一个脚本,这是说18000字符,然后我用3打印语句。

那么有没有一种方法可以根据脚本的长度来设置打印语句的数量?

您可以根据您的脚本长度除以8000来计算WHILE循环。

例如:

 DECLARE @Counter INT SET @Counter = 0 DECLARE @TotalPrints INT SET @TotalPrints = (LEN(@script) / 8000) + 1 WHILE @Counter < @TotalPrints BEGIN -- Do your printing... SET @Counter = @Counter + 1 END 

我知道这是一个古老的问题,但是我在这里没有提到。

对我来说,以下工作。

 DECLARE @info NVARCHAR(MAX) --SET @info to something big PRINT CAST(@info AS NTEXT) 

以下解决方法不使用PRINT语句。 它与SQL Server Management Studio结合使用效果很好。

 SELECT CAST('<root><![CDATA[' + @MyLongString + ']]></root>' AS XML) 

您可以单击返回的XML以在内置的XML查看器中将其展开。

显示的尺寸有一个非常慷慨的客户端限制。 转到Tools/Options/Query Results/SQL Server/Results to Grid/XML data来调整它,如果需要的话。

这是应该如何做的:

 DECLARE @String NVARCHAR(MAX); DECLARE @CurrentEnd BIGINT; /* track the length of the next substring */ DECLARE @offset tinyint; /*tracks the amount of offset needed */ set @string = replace( replace(@string, char(13) + char(10), char(10)) , char(13), char(10)) WHILE LEN(@String) > 1 BEGIN IF CHARINDEX(CHAR(10), @String) between 1 AND 4000 BEGIN SET @CurrentEnd = CHARINDEX(char(10), @String) -1 set @offset = 2 END ELSE BEGIN SET @CurrentEnd = 4000 set @offset = 1 END PRINT SUBSTRING(@String, 1, @CurrentEnd) set @string = SUBSTRING(@String, @CurrentEnd+@offset, LEN(@String)) END /*End While loop*/ 

取自http://ask.sqlservercentral.com/questions/3102/any-way-around-the-print-limit-of-nvarcharmax-in-s.html

我正在寻找使用打印语句来debugging一些dynamic的SQL,因为我想大多数人正在使用打印出于类似的原因。

我尝试了一些列出的解决scheme,发现Kelsey的解决scheme使用微小的tweeks(@sql是我的@script)nb LENGTH不是一个有效的函数:

 --http://stackoverflow.com/questions/7850477/how-to-print-varcharmax-using-print-statement --Kelsey DECLARE @Counter INT SET @Counter = 0 DECLARE @TotalPrints INT SET @TotalPrints = (LEN(@sql) / 4000) + 1 WHILE @Counter < @TotalPrints BEGIN PRINT SUBSTRING(@sql, @Counter * 4000, 4000) SET @Counter = @Counter + 1 END PRINT LEN(@sql) 

这段代码的作用是在输出中添加一行,但为了debugging,这对我来说不是问题。

本B的解决scheme是完美的,是最elegent,虽然debugging是很多代码行,所以我select使用我对Kelsey的轻微修改。 BenB的代码可以在msdb中创build一个像msdb存储过程这样的系统,这个代码可以在一行中重用和调用。

Alfoks的代码不能工作,因为这样做会更容易。

遇到这个问题,并想要更简单的东西…尝试以下操作:

 SELECT [processing-instruction(x)]=@Script FOR XML PATH(''),TYPE 

这个过程正确地输出VARCHAR(MAX)参数考虑包装:

 CREATE PROCEDURE [dbo].[Print] @sql varchar(max) AS BEGIN declare @n int, @i int = 0, @s int = 0, -- substring start posotion @l int; -- substring length set @n = ceiling(len(@sql) / 8000.0); while @i < @n begin set @l = 8000 - charindex(char(13), reverse(substring(@sql, @s, 8000))); print substring(@sql, @s, @l); set @i = @i + 1; set @s = @s + @l + 2; -- accumulation + CR/LF end return 0 END 
创build过程dbo.PrintMax @text nvarchar(max)
如
开始
     declare @i int,@newline nchar(2),@print varchar(max); 
     set @newline = nchar(13)+ nchar(10);
    select@i = charindex(@newline,@text);
    而(@i> 0)
    开始
        select@print = substring(@ text,0,@ i);
         while(len(@print)> 8000)
        开始
            打印子string(@ print,0,8000);
            select@print = substring(@ print,8000,len(@print));
        结束
        打印@print;
        select@text = substring(@ text,@ i + 2,len(@text));
        select@i = charindex(@newline,@text);
    结束
     print @text;
结束

你可以使用这个

 declare @i int = 1 while Exists(Select(Substring(@Script,@i,4000))) and (@i < LEN(@Script)) begin print Substring(@Script,@i,4000) set @i = @i+4000 end 

使用换行符和空格作为一个好的折点:

将@sqlAll声明为nvarchar(max)set @sqlAll =' – 在这里插入所有的sql

'print'@sqlAll – 截断超过4000'print @sqlAll print''print''print''

  print '@sqlAll - split into chunks' declare @i int = 1, @nextspace int = 0, @newline nchar(2) set @newline = nchar(13) + nchar(10) while Exists(Select(Substring(@sqlAll,@i,3000))) and (@i < LEN(@sqlAll)) begin while Substring(@sqlAll,@i+3000+@nextspace,1) <> ' ' and Substring(@sqlAll,@i+3000+@nextspace,1) <> @newline BEGIN set @nextspace = @nextspace + 1 end print Substring(@sqlAll,@i,3000+@nextspace) set @i = @i+3000+@nextspace set @nextspace = 0 end print ' ' print ' ' print ' ' 

这是另一个版本。 这个提取每个子string从主string打印而不是在每个循环中减less4000个主string(这可能会在引擎盖下创build很多非常长的string – 不确定)。

 CREATE PROCEDURE [Internal].[LongPrint] @msg nvarchar(max) AS BEGIN -- SET NOCOUNT ON reduces network overhead SET NOCOUNT ON; DECLARE @MsgLen int; DECLARE @CurrLineStartIdx int = 1; DECLARE @CurrLineEndIdx int; DECLARE @CurrLineLen int; DECLARE @SkipCount int; -- Normalise line end characters. SET @msg = REPLACE(@msg, char(13) + char(10), char(10)); SET @msg = REPLACE(@msg, char(13), char(10)); -- Store length of the normalised string. SET @MsgLen = LEN(@msg); -- Special case: Empty string. IF @MsgLen = 0 BEGIN PRINT ''; RETURN; END -- Find the end of next substring to print. SET @CurrLineEndIdx = CHARINDEX(CHAR(10), @msg); IF @CurrLineEndIdx BETWEEN 1 AND 4000 BEGIN SET @CurrLineEndIdx = @CurrLineEndIdx - 1 SET @SkipCount = 2; END ELSE BEGIN SET @CurrLineEndIdx = 4000; SET @SkipCount = 1; END -- Loop: Print current substring, identify next substring (a do-while pattern is preferable but TSQL doesn't have one). WHILE @CurrLineStartIdx < @MsgLen BEGIN -- Print substring. PRINT SUBSTRING(@msg, @CurrLineStartIdx, (@CurrLineEndIdx - @CurrLineStartIdx)+1); -- Move to start of next substring. SET @CurrLineStartIdx = @CurrLineEndIdx + @SkipCount; -- Find the end of next substring to print. SET @CurrLineEndIdx = CHARINDEX(CHAR(10), @msg, @CurrLineStartIdx); SET @CurrLineLen = @CurrLineEndIdx - @CurrLineStartIdx; -- Find bounds of next substring to print. IF @CurrLineLen BETWEEN 1 AND 4000 BEGIN SET @CurrLineEndIdx = @CurrLineEndIdx - 1 SET @SkipCount = 2; END ELSE BEGIN SET @CurrLineEndIdx = @CurrLineStartIdx + 4000; SET @SkipCount = 1; END END END 

这应该正常工作,这只是以前的答案的改进。

 DECLARE @Counter INT DECLARE @Counter1 INT SET @Counter = 0 SET @Counter1 = 0 DECLARE @TotalPrints INT SET @TotalPrints = (LEN(@QUERY) / 4000) + 1 print @TotalPrints WHILE @Counter < @TotalPrints BEGIN -- Do your printing... print(substring(@query,@COUNTER1,@COUNTER1+4000)) set @COUNTER1 = @Counter1+4000 SET @Counter = @Counter + 1 END