J'ai un code qui est:
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)
La longueur du script est d'environ 10 000 caractères. Depuis, j'utilise print statement qui ne peut contenir qu'un maximum de 8 000 caractères. J'utilise donc deux instructions print.
Le problème, c’est quand j’ai un script de 18 000 caractères, puis j’utilisais 3 instructions d’impression.
Donc, est-il possible de définir le nombre d'instructions d'impression en fonction de la longueur du script?
Vous pouvez créer une boucle WHILE
en fonction du nombre de fois la longueur de votre script divisée par 8000.
PAR EXEMPLE:
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
Je sais que c'est une vieille question, mais ce que j'ai fait n'est pas mentionné ici.
Pour moi, ce qui suit a fonctionné.
DECLARE @info NVARCHAR(MAX)
--SET @info to something big
PRINT CAST(@info AS NTEXT)
La solution de contournement suivante n'utilise pas l'instruction PRINT
. Cela fonctionne bien en combinaison avec SQL Server Management Studio.
SELECT CAST('<root><![CDATA[' + @MyLongString + ']]></root>' AS XML)
Vous pouvez cliquer sur le code XML renvoyé pour le développer dans le visualiseur XML intégré.
Il existe une limite assez généreuse du côté client sur la taille affichée. Allez à Tools/Options/Query Results/SQL Server/Results to Grid/XML data
pour l’ajuster si nécessaire.
Voici comment cela devrait être fait:
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*/
Je suis tombé sur cette question et je voulais quelque chose de plus simple ... Essayez ceci:
SELECT [processing-instruction(x)]=@Script FOR XML PATH(''),TYPE
Ce processus imprime correctement le paramètre VARCHAR(MAX)
en considérant le wrapping:
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
Je cherchais à utiliser l'instruction print pour déboguer un SQL dynamique, comme je l'imagine, la plupart d'entre vous utilisez print pour des raisons similaires.
J'ai essayé quelques-unes des solutions répertoriées et découvert que la solution de Kelsey fonctionnait avec des modifications mineures (@sql is my @script) n.b. LONGUEUR n'est pas une fonction valide:
--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)
Comme indiqué, ce code ajoute une nouvelle ligne à la sortie, mais pour le débogage, ce n'est pas un problème pour moi.
La solution de Ben B est parfaite et la plus élégante, bien que pour le débogage il y ait beaucoup de lignes de code, j'ai donc choisi d'utiliser ma légère modification de celle de Kelsey. Cela pourrait valoir la peine de créer un système comme une procédure stockée dans msdb pour le code de Ben B qui pourrait être réutilisé et appelé sur une ligne?
Le code d'Alfoks ne fonctionne malheureusement pas car cela aurait été plus facile.
crée la procédure dbo.PrintMax @text nvarchar (max) as begin déclarer @ i int, @newline nchar (2), @print varchar (max); set @newline = nchar (13) + nchar (10); sélectionnez @ i = charindex (@newline, @text); tandis que (@i> 0) commencer sélectionnez @print = sous-chaîne (@ text, 0, @ i); tandis que (len (@print)> 8000) commencer sous-chaîne d'impression (@ print, 0,8000); sélectionnez @print = sous-chaîne (@ print, 8000, len (@print)); fin print @print; sélectionnez @text = sous-chaîne (@ text, @ i + 2, len (@text)); sélectionnez @ i = charindex (@newline, @text); fin print @text; end
Vous pouvez utiliser ceci
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
Utilise les sauts de ligne et les espaces comme bon point de rupture:
declare @sqlAll as nvarchar(max)
set @sqlAll = '-- Insert all your sql here'
print '@sqlAll - truncated over 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 ' '
Si le code source ne pose pas de problème de remplacement de LF par CRLF, aucun débogage n’est requis en suivant les codes simples générés.
--http://stackoverflow.com/questions/7850477/how-to-print-varcharmax-using-print-statement
--Bill Bai
SET @SQL=replace(@SQL,char(10),char(13)+char(10))
SET @SQL=replace(@SQL,char(13)+char(13)+char(10),char(13)+char(10) )
DECLARE @Position int
WHILE Len(@SQL)>0
BEGIN
SET @Position=charindex(char(10),@SQL)
PRINT left(@SQL,@Position-2)
SET @SQL=substring(@SQL,@Position+1,len(@SQL))
end;
Ou simplement:
PRINT SUBSTRING(@SQL_InsertQuery, 1, 8000)
PRINT SUBSTRING(@SQL_InsertQuery, 8001, 16000)
Cela devrait fonctionner correctement, il ne s'agit que d'une amélioration des réponses précédentes.
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
Voici une autre version. Celui-ci extrait chaque sous-chaîne à imprimer à partir de la chaîne principale au lieu de réduire de 4000 la chaîne principale sur chaque boucle (ce qui pourrait créer beaucoup de très longues chaînes sous le capot - pas certain).
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