sql >> Databasteknik >  >> RDS >> Sqlserver

SQL NVARCHAR och VARCHAR gränser

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.

  1. varchar(n) + varchar(n) kommer att trunkeras med 8 000 tecken.
  2. nvarchar(n) + nvarchar(n) kommer att trunkeras med 4 000 tecken.
  3. varchar(n) + nvarchar(n) kommer att trunkeras med 4 000 tecken. nvarchar har högre prioritet så resultatet är nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) kommer inte att trunkeras (för <2 GB).
  5. varchar(max) + varchar(n) kommer inte att trunkeras (för <2 GB) och resultatet kommer att skrivas som varchar(max) .
  6. varchar(max) + nvarchar(n) kommer inte att trunkeras (för <2 GB) och resultatet kommer att skrivas som nvarchar(max) .
  7. nvarchar(max) + varchar(n) konverterar först varchar(n) inmatning till nvarchar(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 till nvarchar(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 &lt; visas som &lt; .



  1. Skillnad mellan numerisk, float och decimal i SQL Server

  2. phpMyAdmin på MySQL 8.0

  3. Hur man aktiverar SQL Server Agent XPs med T-SQL

  4. Distribuera Cloudera CDP Data Center på Oracle Cloud Infrastructure (OCI)