sql >> Database teknologi >  >> RDS >> Sqlserver

SQL NVARCHAR- og VARCHAR-grænser

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.

  1. varchar(n) + varchar(n) afkortes med 8.000 tegn.
  2. nvarchar(n) + nvarchar(n) afkortes med 4.000 tegn.
  3. varchar(n) + nvarchar(n) vil afkortes med 4.000 tegn. nvarchar har højere forrang, så resultatet er nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) afkortes ikke (for <2 GB).
  5. varchar(max) + varchar(n) afkortes ikke (for <2 GB), og resultatet vil blive skrevet som varchar(max) .
  6. varchar(max) + nvarchar(n) afkortes ikke (for <2 GB), og resultatet vil blive skrevet som nvarchar(max) .
  7. nvarchar(max) + varchar(n) vil først konvertere varchar(n) input til nvarchar(n) og lav derefter sammenkædningen. Hvis længden af ​​varchar(n) strengen er større end 4.000 tegn, castet vil være til nvarchar(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 &lt; vises som &lt; .



  1. Få alle forældre til et barn

  2. Returner antallet af rækker, der er påvirket af UPDATE-sætninger

  3. MySQL, Få brugerrangering

  4. Indsættelse af SQL Server-data med Oracle® SQL*Loader