Jeg forstår, at der er et max. 4000 indstillet for NVARCHAR(MAX)
Din forståelse er forkert. nvarchar(max) kan gemme op til (og nogle gange mere) 2 GB data (1 milliard dobbeltbyte-tegn).
Fra nchar og nvarchar i Books online er grammatikken
nvarchar [ ( n | max ) ]
| karakter betyder, at disse er alternativer. dvs. du angiver enten n eller det bogstavelige max .
Hvis du vælger at angive en specifik n så skal dette være mellem 1 og 4.000, men ved at bruge max definerer det som en datatype for et stort objekt (erstatning for ntext som er forældet).
Faktisk i SQL Server 2008 ser det ud til, at for en variabel grænsen på 2 GB kan overskrides på ubestemt tid, hvis der er tilstrækkelig plads i tempdb (Vis her)
Med hensyn til de andre dele af dit spørgsmål
Trunkering ved sammenkædning afhænger af datatype.
varchar(n) + varchar(n)afkortes med 8.000 tegn.nvarchar(n) + nvarchar(n)afkortes med 4.000 tegn.varchar(n) + nvarchar(n)vil afkortes med 4.000 tegn.nvarcharhar højere forrang, så resultatet ernvarchar(4,000)[n]varchar(max)+[n]varchar(max)afkortes ikke (for <2 GB).varchar(max)+varchar(n)afkortes ikke (for <2 GB), og resultatet vil blive skrevet somvarchar(max).varchar(max)+nvarchar(n)afkortes ikke (for <2 GB), og resultatet vil blive skrevet somnvarchar(max).nvarchar(max)+varchar(n)vil først konverterevarchar(n)input tilnvarchar(n)og lav derefter sammenkædningen. Hvis længden af varchar(n)strengen er større end 4.000 tegn, castet vil være tilnvarchar(4000)og trunkering vil forekomme .
Datatyper af strengliteraler
Hvis du bruger N præfiks og strengen er <=4.000 tegn lang den vil blive skrevet som nvarchar(n) hvor n er længden af strengen. Så N'Foo' vil blive behandlet som nvarchar(3) for eksempel. Hvis strengen er længere end 4.000 tegn vil den blive behandlet som nvarchar(max)
Hvis du ikke bruger N præfiks og strengen er <=8.000 tegn lang den vil blive skrevet som varchar(n) hvor n er længden af strengen. Hvis længere som varchar(max)
For begge ovenstående, hvis længden af strengen er nul, så n er indstillet til 1.
Nyere syntakselementer.
1. CONCAT funktion hjælper ikke her
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
Ovenstående returnerer 8000 for begge sammenkædningsmetoder.
2. Vær forsigtig med +=
DECLARE @A VARCHAR(MAX) = '';
SET @A+= REPLICATE('A',5000) + REPLICATE('A',5000)
DECLARE @B VARCHAR(MAX) = '';
SET @B = @B + REPLICATE('A',5000) + REPLICATE('A',5000)
SELECT DATALENGTH(@A),
DATALENGTH(@B);`
Returnerer
-------------------- --------------------
8000 10000
Bemærk at @A stødt på trunkering.
Sådan løser du det problem, du oplever.
Du får enten trunkering, fordi du sammenkæder to ikke max datatyper sammen, eller fordi du sammenkæder en varchar(4001 - 8000) streng til en nvarchar indtastet streng (selv nvarchar(max) ).
For at undgå det andet problem skal du blot sørge for, at alle strengliteraler (eller i det mindste dem med længder i intervallet 4001 - 8000) er indledt med N .
For at undgå det første problem skal du ændre opgaven fra
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Til
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
så en NVARCHAR(MAX) er involveret i sammenkædningen fra begyndelsen (da resultatet af hver sammenkædning også vil være NVARCHAR(MAX) dette vil forplante sig)
Undgå trunkering ved visning
Sørg for, at du har valgt "resultater til gitter"-tilstand, så kan du bruge
select @SQL as [processing-instruction(x)] FOR XML PATH
SSMS-indstillingerne giver dig mulighed for at indstille ubegrænset længde for XML resultater. processing-instruction bit undgår problemer med tegn såsom < vises som < .