sql >> Database >  >> RDS >> Sqlserver

SQL NVARCHAR- en VARCHAR-limieten

Ik begrijp dat er een maximum van 4000 is ingesteld voor NVARCHAR(MAX)

Uw begrip is verkeerd. nvarchar(max) kan tot (en soms meer) 2 GB aan gegevens opslaan (1 miljard dubbelbyte tekens).

Van nchar en nvarchar in Books online is de grammatica

nvarchar [ ( n | max ) ]

De | karakter betekent dat dit alternatieven zijn. d.w.z. u specificeert ofwel n of de letterlijke max .

Als u ervoor kiest om een ​​specifieke n . op te geven dan moet dit tussen 1 en 4.000 zijn, maar gebruik max definieert het als een groot object datatype (vervanging voor ntext wat verouderd is).

In SQL Server 2008 lijkt het er zelfs op dat voor een variabele de limiet van 2 GB kan onbeperkt worden overschreden, mits er voldoende ruimte is in tempdb (Hier weergegeven)

Wat betreft de andere delen van uw vraag

Truncatie bij aaneenschakeling hangt af van datatype.

  1. varchar(n) + varchar(n) wordt afgekapt bij 8.000 tekens.
  2. nvarchar(n) + nvarchar(n) wordt afgekapt bij 4.000 tekens.
  3. varchar(n) + nvarchar(n) wordt afgekapt bij 4.000 tekens. nvarchar heeft een hogere prioriteit, dus het resultaat is nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) wordt niet afgekapt (voor <2 GB).
  5. varchar(max) + varchar(n) wordt niet afgekapt (voor <2 GB) en het resultaat wordt getypt als varchar(max) .
  6. varchar(max) + nvarchar(n) wordt niet afgekapt (voor <2 GB) en het resultaat wordt getypt als nvarchar(max) .
  7. nvarchar(max) + varchar(n) converteert eerst de varchar(n) invoer naar nvarchar(n) en doe dan de aaneenschakeling. Als de lengte van de varchar(n) string is groter dan 4.000 tekens, de cast zal zijn naar nvarchar(4000) en inkorting zal plaatsvinden .

Datatypes van letterlijke tekenreeksen

Als u de N . gebruikt prefix en de string is <=4.000 tekens lang en wordt getypt als nvarchar(n) waar n is de lengte van de string. Dus N'Foo' wordt behandeld als nvarchar(3) bijvoorbeeld. Als de tekenreeks langer is dan 4.000 tekens, wordt deze behandeld als nvarchar(max)

Als u de N . niet gebruikt prefix en de string is <=8.000 tekens lang en wordt getypt als varchar(n) waar n is de lengte van de string. Indien langer als varchar(max)

Voor beide bovenstaande, als de lengte van de string nul is, dan n is ingesteld op 1.

Nieuwere syntaxiselementen.

1. De CONCAT functie helpt hier niet

DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);

SELECT DATALENGTH(@A5000 + @A5000), 
       DATALENGTH(CONCAT(@A5000,@A5000));

Het bovenstaande geeft 8000 terug voor beide methoden van aaneenschakeling.

2. Wees voorzichtig met +=

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);`

Retourneren

-------------------- --------------------
8000                 10000

Merk op dat @A truncatie aangetroffen.

Hoe het probleem dat u ondervindt op te lossen.

U krijgt truncatie omdat u twee niet max . aaneenvoegt datatypes samen of omdat u een varchar(4001 - 8000) samenvoegt string naar een nvarchar getypte string (zelfs nvarchar(max) ).

Om het tweede probleem te voorkomen, moet u ervoor zorgen dat alle letterlijke tekenreeksen (of in ieder geval die met een lengte in het bereik van 4001 - 8000) worden voorafgegaan door N .

Wijzig de opdracht van

. om het eerste nummer te vermijden
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;

Naar

DECLARE @SQL NVARCHAR(MAX) = ''; 
SET @SQL = @SQL + N'Foo' + N'Bar'

zodat een NVARCHAR(MAX) is vanaf het begin betrokken bij de aaneenschakeling (omdat het resultaat van elke aaneenschakeling ook NVARCHAR(MAX) zal zijn dit zal zich verspreiden)

Truncatie vermijden tijdens het bekijken

Zorg ervoor dat u de modus "resultaten naar raster" hebt geselecteerd, dan kunt u

select @SQL as [processing-instruction(x)] FOR XML PATH 

Met de SSMS-opties kunt u een onbeperkte lengte instellen voor XML resultaten. De processing-instruction bit vermijdt problemen met tekens zoals &lt; weergegeven als &lt; .



  1. Gedeeltelijke index niet gebruikt in ON CONFLICT-clausule tijdens het uitvoeren van een upsert in Postgresql

  2. Standaard datum-/tijdnotatietekenreeksen ondersteund door FORMAT() in SQL Server

  3. Hoe u twee tabellen samenvoegt in MySQL

  4. Hoe een inner join op rijnummer in sql-server te doen?