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

Limiti SQL NVARCHAR e VARCHAR

Comprendo che è stato impostato un massimo di 4000 per NVARCHAR(MAX)

La tua comprensione è sbagliata. nvarchar(max) può memorizzare fino a (e talvolta oltre) 2 GB di dati (1 miliardo di caratteri a byte doppio).

Da nchar e nvarchar in Libri online la grammatica è

nvarchar [ ( n | max ) ]

Il | carattere significa che queste sono alternative. cioè specifichi uno dei due n o il letterale max .

Se scegli di specificare un n specifico quindi questo deve essere compreso tra 1 e 4.000 ma utilizzando max lo definisce come un tipo di dati di oggetti di grandi dimensioni (in sostituzione di ntext che è deprecato).

Infatti in SQL Server 2008 sembra che per una variabile il limite di 2 GB può essere superato indefinitamente in base allo spazio sufficiente in tempdb (Mostrato qui)

Per quanto riguarda le altre parti della tua domanda

Il troncamento durante la concatenazione dipende dal tipo di dati.

  1. varchar(n) + varchar(n) verrà troncato a 8.000 caratteri.
  2. nvarchar(n) + nvarchar(n) troncherà a 4.000 caratteri.
  3. varchar(n) + nvarchar(n) troncherà a 4.000 caratteri. nvarchar ha una precedenza maggiore, quindi il risultato è nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) non verrà troncato (per <2 GB).
  5. varchar(max) + varchar(n) non verrà troncato (per <2 GB) e il risultato verrà digitato come varchar(max) .
  6. varchar(max) + nvarchar(n) non verrà troncato (per <2 GB) e il risultato verrà digitato come nvarchar(max) .
  7. nvarchar(max) + varchar(n) convertirà prima il varchar(n) inserisci nvarchar(n) e poi fai la concatenazione. Se la lunghezza di varchar(n) la stringa è maggiore di 4.000 caratteri il cast sarà in nvarchar(4000) e si verificherà un troncamento .

Tipi di dati di letterali stringa

Se usi il N prefisso e la stringa è lunga <=4.000 caratteri verrà digitata come nvarchar(n) dove n è la lunghezza della stringa. Quindi N'Foo' verrà trattato come nvarchar(3) Per esempio. Se la stringa è più lunga di 4.000 caratteri verrà trattata come nvarchar(max)

Se non usi il N prefisso e la stringa è lunga <=8.000 caratteri verrà digitata come varchar(n) dove n è la lunghezza della stringa. Se più lungo come varchar(max)

Per entrambi i precedenti se la lunghezza della stringa è zero allora n è impostato su 1.

Elementi di sintassi più recenti.

1. Il CONCAT la funzione non aiuta qui

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

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

Quanto sopra restituisce 8000 per entrambi i metodi di concatenazione.

2. Fai attenzione con +=

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

Resi

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

Nota che @A ha riscontrato un troncamento.

Come risolvere il problema che stai riscontrando.

Stai ricevendo il troncamento perché stai concatenando due non max tipi di dati insieme o perché stai concatenando un varchar(4001 - 8000) stringa in un nvarchar stringa digitata (anche nvarchar(max) ).

Per evitare il secondo problema, assicurati semplicemente che tutte le stringhe letterali (o almeno quelle con lunghezze nell'intervallo 4001 - 8000) siano precedute da N .

Per evitare il primo problema, cambia il compito da

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

A

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

in modo che un NVARCHAR(MAX) è coinvolto nella concatenazione dall'inizio (poiché il risultato di ogni concatenazione sarà anche NVARCHAR(MAX) questo si propagherà)

Evitare il troncamento durante la visualizzazione

Assicurati di aver selezionato la modalità "risultati sulla griglia", quindi puoi utilizzare

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

Le opzioni SSMS ti consentono di impostare una lunghezza illimitata per XML risultati. Le processing-instruction bit evita problemi con caratteri come &lt; visualizzato come &lt; .