Jag förstår att det finns ett maxvärde på 4000 för
NVARCHAR(MAX)
Din förståelse är felaktig. nvarchar(max)
kan lagra upp till (och ibland mer än) 2 GB data (1 miljard dubbelbyte-tecken).
Från nchar och nvarchar i Books online grammatiken är
nvarchar [ ( n | max ) ]
|
karaktär betyder att dessa är alternativ. dvs du anger antingen n
eller den bokstavliga max
.
Om du väljer att ange en specifik n
då måste detta vara mellan 1 och 4 000 men med max
definierar den som en datatyp för stort objekt (ersättning för ntext
som är utfasad).
Faktum är att i SQL Server 2008 verkar det som för en variabel gränsen på 2 GB kan överskridas på obestämd tid under förutsättning att det finns tillräckligt med utrymme i tempdb
(Visas här)
Angående de andra delarna av din fråga
Trunkering vid sammanlänkning beror på datatyp.
varchar(n) + varchar(n)
kommer att trunkeras med 8 000 tecken.nvarchar(n) + nvarchar(n)
kommer att trunkeras med 4 000 tecken.varchar(n) + nvarchar(n)
kommer att trunkeras med 4 000 tecken.nvarchar
har högre prioritet så resultatet ärnvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
kommer inte att trunkeras (för <2 GB).varchar(max)
+varchar(n)
kommer inte att trunkeras (för <2 GB) och resultatet kommer att skrivas somvarchar(max)
.varchar(max)
+nvarchar(n)
kommer inte att trunkeras (för <2 GB) och resultatet kommer att skrivas somnvarchar(max)
.nvarchar(max)
+varchar(n)
konverterar förstvarchar(n)
inmatning tillnvarchar(n)
och gör sedan sammanlänkningen. Om längden påvarchar(n)
strängen är större än 4 000 tecken som ska bestå av tillnvarchar(4000)
och trunkering kommer att ske .
Datatyper för strängliteraler
Om du använder N
prefix och strängen är <=4 000 tecken lång den kommer att skrivas som nvarchar(n)
där n
är längden på strängen. Så N'Foo'
kommer att behandlas som nvarchar(3)
till exempel. Om strängen är längre än 4 000 tecken kommer den att behandlas som nvarchar(max)
Om du inte använder N
prefix och strängen är <=8 000 tecken lång den kommer att skrivas som varchar(n)
där n
är längden på strängen. Om längre som varchar(max)
För båda ovanstående om längden på strängen är noll så n
är inställd på 1.
Nyere syntaxelement.
1. CONCAT
Funktionen hjälper inte här
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
Ovanstående returnerar 8000 för båda metoderna för sammanlänkning.
2. Var försiktig 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);`
Retur
-------------------- --------------------
8000 10000
Observera att @A
stött på trunkering.
Hur du löser problemet du upplever.
Du får trunkering antingen eftersom du sammanfogar två icke max
datatyper tillsammans eller för att du sammanfogar en varchar(4001 - 8000)
sträng till en nvarchar
typad sträng (även nvarchar(max)
).
För att undvika det andra problemet, se bara till att alla strängliteraler (eller åtminstone de med längder i intervallet 4001–8000) föregås av N
.
För att undvika det första problemet, ändra tilldelningen från
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Till
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
så att en NVARCHAR(MAX)
är involverad i sammanlänkningen från början (eftersom resultatet av varje sammanlänkning också blir NVARCHAR(MAX)
detta kommer att spridas)
Undvik trunkering vid visning
Se till att du har valt läget "resultat till rutnät" så kan du använda
select @SQL as [processing-instruction(x)] FOR XML PATH
SSMS-alternativen låter dig ställa in obegränsad längd för XML
resultat. processing-instruction
bit undviker problem med tecken som <
visas som <
.