Qual'è la differenza tra varchar e nvarchar?


1354

nvarcharSupporta solo caratteri multibyte? In tal caso, c'è davvero qualche punto, oltre ai problemi di archiviazione, da utilizzare varchars?


6
Mi piace il punto di vista di incomudro, è ciò che mi ha portato a scavare sulla differenza tra varchar e nvarchar in primo luogo. La nostra app Java su un db di SQL Server utilizza myBatis, che sembra inviare stringhe come nvarchar per impostazione predefinita (ancora non sono sicuro di come (o se) sia sostituibile). Una semplice query si presentava come un enorme problema di prestazioni perché avevo definito la colonna che stava selezionando come varchar, non nvarchar, e ignorava l'indice sulla colonna.
Sean Leggi

Risposte:


1652

Una nvarcharcolonna può memorizzare qualsiasi dato Unicode. Una varcharcolonna è limitata a una tabella codici a 8 bit. Alcune persone pensano che varchardovrebbe essere usato perché occupa meno spazio. Credo che questa non sia la risposta corretta. Le incompatibilità di codepage sono una seccatura e Unicode è la cura per i problemi di codepage. Al giorno d'oggi con dischi e memoria economici, non c'è davvero motivo di perdere tempo a perdere tempo con le pagine di codice.

Tutti i moderni sistemi operativi e piattaforme di sviluppo utilizzano Unicode internamente. Usando nvarcharpiuttosto che varchar, puoi evitare di fare conversioni di codifica ogni volta che leggi o scrivi sul database. Le conversioni richiedono tempo e sono soggette a errori. E il recupero da errori di conversione è un problema non banale.

Se stai interfacciando con un'applicazione che utilizza solo ASCII, consiglierei comunque di utilizzare Unicode nel database. Gli algoritmi di confronto del sistema operativo e del database funzioneranno meglio con Unicode. Unicode evita problemi di conversione quando si interfaccia con altri sistemi. E ti preparerai per il futuro. E puoi sempre convalidare che i tuoi dati sono limitati a ASCII a 7 bit per qualsiasi sistema legacy che devi mantenere, anche godendo di alcuni dei vantaggi dell'archiviazione Unicode completa.


8
Questa è un'ottima informazione da avere. Quindi lo capisco correttamente se deduco che la scelta alla fine diventa una delle - quale risorsa è più economica: processore + spese generali di sviluppo o archiviazione?
Matt Cashatt,

141
@MatthewPatrickCashatt - Potevi vederlo in quel modo. Ma se immagini un mondo glorioso in cui tutti i dati di testo si trovano in Unicode e gli sviluppatori semplicemente non devono mai pensare a cosa sta codificando qualcosa e un'intera classe di errori non si verifica mai, allora puoi vedere che c'è davvero nessuna scelta a tutti.
Jeffrey L Whitledge,


8
@Martin Smith - In quei casi, il piccolo vantaggio che conferisce varchar (memoria compatta) svanisce. Immagino che varchar sia anche peggio di quanto pensassi!
Jeffrey L Whitledge,

9
@PeterAllenWebb - È possibile "archiviare" qualsiasi dato Unicode, poiché le coppie surrogate in UTF-16 possono essere archiviate in UCS-2 come se fossero caratteri. Funzionerà in modo trasparente per l'archiviazione e il recupero dei dati. Ora, ciò che non puoi fare è ottenere trasformazioni di casi affidabili e confronti al di fuori del BMP, ma non ho fatto alcuna affermazione al riguardo. Quindi, se hai molto testo Desseret su cui vuoi eseguire l'elaborazione, sarebbe meglio farlo al di fuori del database. Ma va bene per riporlo lì. (Naturalmente, varchar non ti aiuterà neanche lì!)
Jeffrey L Whitledge,

259

varchar : dati di caratteri a lunghezza variabile, non Unicode. Le regole di confronto del database determinano la tabella codici utilizzata per i dati.

nvarchar : dati di caratteri Unicode a lunghezza variabile. Dipende dalle regole di confronto del database per i confronti.

Forti di questa conoscenza, usa quello che corrisponde ai tuoi dati di input (ASCII v. Unicode).


5
Esiste una limitazione come varchar non può archiviare i dati Unicode? Sono tutti 1 e 0. Sono in grado di salvare il contenuto cinese come varchar bene sul mio database. Ho appena specificato il suo UTF-8 però. Come funziona allora?
Nishant,

3
Ritardo @Nishant risposta : naturalmente è possibile memorizzare UTF-8 in varchar ma romperà le funzioni di stringa di SQL Server. Se si eseguono tutte le ricerche / trasformazioni all'interno dell'applicazione, sì, è possibile farlo (ma qual è il vantaggio?). Solo la codifica Unicode supportata da SS è UCS-2 (sì, non UTF-16 prima di SS2k16) e le sue funzioni di stringa funzionano solo con quella codifica. A proposito di indici? Se vuoi archiviare dati arbitrari, è meglio usare binario.
Adriano Repetti,

Sì, interrompe solo le funzioni di ricerca delle stringhe.
Nishant,

8
Quindi, sai ... non "funziona". È come memorizzare un floatin inte andare, "beh, certo che i decimali scompaiono." Non farlo.
user7116

70

Uso sempre nvarchar in quanto consente a qualsiasi cosa io stia costruendo di resistere praticamente a tutti i dati che gli lancio. Il mio sistema CMS fa il cinese per caso, perché ho usato nvarchar. Al giorno d'oggi, qualsiasi nuova applicazione non dovrebbe preoccuparsi davvero della quantità di spazio richiesta.


25
L'idea che le nuove app non debbano preoccuparsi delle restrizioni di spazio è in qualche modo miope e chiunque abbia avuto a che fare con database di livello medio-grande sarà felice di dirtelo, completamente errato.
Frater,

60
Per avere la libertà di mettere le parole in bocca a tag2k, penso che un'affermazione più accurata potrebbe essere "è sempre più improbabile che qualsiasi nuova app dovrebbe essere più preoccupata per lo spazio richiesto di quanto non dovrebbero essere per l'internazionalizzazione e altri problemi relativi ai set di caratteri".
Cowan,

1
"Al giorno d'oggi, qualsiasi nuova app non dovrebbe davvero preoccuparsi della quantità di spazio richiesta." - A meno che non si stia utilizzando l'archiviazione cloud gratuita, in cui il piano a pagamento è un salto CONSIDERABILE in $ (consultare Piani condivisi AppHarbor SQL Server).
Ganders,

3
@ganders Howl! Sei proprio lì. Le dichiarazioni generalizzate sono solo temporaneamente corrette nella migliore delle ipotesi. Il calcolo è sicuramente un gioco altalene e rotatoria. Sono decisamente interessato a quanto spazio sto usando su CCP di Windows Azure. Detto questo, non avrei mai "usato" varchar su nvarchar. Ooo mi sono appena contraddetto?
rism

1
@rism, credo che tu abbia rimosso qualsiasi rischio di contraddizione con il tuo uso delle citazioni "never", almeno tecnicamente.
Smandoli,

30

Dipende da come è stato installato Oracle. Durante il processo di installazione, viene impostata l'opzione NLS_CHARACTERSET. Potresti riuscire a trovarlo con la query SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Se il tuo NLS_CHARACTERSET è una codifica Unicode come UTF8, ottimo. L'uso di VARCHAR e NVARCHAR è praticamente identico. Smetti di leggere ora, provaci. Altrimenti, o se non hai alcun controllo sul set di caratteri Oracle, continua a leggere.

VARCHAR: i dati vengono archiviati nella codifica NLS_CHARACTERSET. Se ci sono altre istanze di database sullo stesso server, potresti essere limitato da esse; e viceversa, poiché è necessario condividere l'impostazione. Un tale campo può memorizzare qualsiasi dato che può essere codificato usando quel set di caratteri e nient'altro . Ad esempio, se il set di caratteri è MS-1252, è possibile memorizzare solo caratteri come lettere inglesi, una manciata di lettere accentate e poche altre (come € e -). La tua applicazione sarebbe utile solo per alcune impostazioni locali, incapace di operare in qualsiasi altra parte del mondo. Per questo motivo, è considerata una cattiva idea.

NVARCHAR: i dati sono archiviati in una codifica Unicode. Ogni lingua è supportata. Una buona idea.

Che dire dello spazio di archiviazione? VARCHAR è generalmente efficiente, poiché il set di caratteri / codifica è stato progettato su misura per una locale specifica. I campi NVARCHAR vengono archiviati nella codifica UTF-8 o UTF-16, basandosi sull'impostazione NLS abbastanza ironicamente. UTF-8 è molto efficiente per le lingue "occidentali", pur supportando le lingue asiatiche. UTF-16 è molto efficiente per le lingue asiatiche, pur supportando le lingue "occidentali". Se sei preoccupato per lo spazio di archiviazione, scegli un'impostazione NLS per fare in modo che Oracle usi UTF-8 o UTF-16 come appropriato.

Che dire della velocità di elaborazione? La maggior parte delle nuove piattaforme di codifica usano Unicode in modo nativo (Java, .NET, anche C ++ std :: wstring di anni fa!), Quindi se il campo del database è VARCHAR, costringe Oracle a convertire tra set di caratteri su ogni lettura o scrittura, non così bene. L'uso di NVARCHAR evita la conversione.

In conclusione: usa NVARCHAR! Evita limitazioni e dipendenze, va bene per lo spazio di archiviazione e di solito è anche meglio per le prestazioni.


42
Questa è una risposta davvero buona, tranne per il fatto che la domanda riguarda sql-server.
stimola il

21

nvarchar archivia i dati come Unicode, quindi, se hai intenzione di archiviare dati multilingue (più di una lingua) in una colonna di dati, hai bisogno della variante N.


16

I miei due centesimi

  1. Gli indici possono non riuscire quando non si utilizzano i tipi di dati corretti:
    In SQL Server: quando si dispone di un indice su una colonna VARCHAR e si presenta una stringa Unicode, SQL Server non utilizza l'indice. La stessa cosa accade quando si presenta un BigInt a una colonna indicizzata contenente SmallInt. Anche se il BigInt è abbastanza piccolo da essere un SmallInt, SQL Server non è in grado di utilizzare l'indice. Al contrario, non si verifica questo problema (quando si fornisce SmallInt o Ansi-Code a una colonna indicizzata di BigInt ot NVARCHAR).

  2. I tipi di dati possono variare tra diversi DBMS (DataBase Management System):
    sapere che ogni database ha tipi di dati leggermente diversi e VARCHAR non significa lo stesso ovunque. Mentre SQL Server ha VARCHAR e NVARCHAR, un database Apache / Derby ha solo VARCHAR e VARCHAR è in Unicode.


Ma sicuramente se stai scrivendo il tuo codice correttamente (cioè usando query con parametri ecc.) Allora il punto 1 è meno rischioso.
Paul,

14

Principalmente nvarchar memorizza i caratteri Unicode e varchar memorizza i caratteri non Unicode.

"Unicodes" significa schema di codifica dei caratteri a 16 bit che consente di codificare i caratteri di molte altre lingue come l'arabo, l'ebraico, il cinese e il giapponese in un singolo set di caratteri.

Ciò significa che unicodes sta usando 2 byte per carattere per memorizzare e i nonunicodes usano solo un byte per carattere per memorizzare. Ciò significa che gli Unicode necessitano di una doppia capacità di archiviazione rispetto ai non Unicode.


10

Hai ragione. nvarcharmemorizza i dati Unicode mentre varcharmemorizza i dati dei caratteri a byte singolo. Altro che le differenze di archiviazione ( nvarcharrichiede il doppio dello spazio di archiviazione come varchar), che già accennato, il motivo principale per preferire nvarcharsopra varcharsarebbe internazionalizzazione (cioè stringhe memorizzazione in altre lingue).


10

Direi che dipende.

Se sviluppi un'applicazione desktop, in cui il sistema operativo funziona in Unicode (come tutti gli attuali sistemi Windows) e il linguaggio supporta nativamente Unicode (le stringhe predefinite sono Unicode, come in Java o C #), vai su nvarchar.

Se sviluppi un'applicazione web, in cui le stringhe arrivano come UTF-8 e il linguaggio è PHP, che non supporta ancora Unicode in modo nativo (nelle versioni 5.x), allora varchar sarà probabilmente una scelta migliore.


9

Sebbene NVARCHARmemorizzi Unicode, dovresti prendere in considerazione l'aiuto della raccolta anche tu puoi usare VARCHARe salvare i tuoi dati delle tue lingue locali.

Immagina solo il seguente scenario.

Le regole di confronto del tuo DB sono persiane e tu salvi un valore come 'علی' (scrittura persiana di Ali) nel VARCHAR(10)tipo di dati. Non ci sono problemi e il DBMS utilizza solo tre byte per memorizzarlo.

Tuttavia, se si desidera trasferire i dati su un altro database e vedere il risultato corretto, il database di destinazione deve avere le stesse regole di confronto del target che è persiano in questo esempio.

Se le regole di confronto del target sono diverse, vengono visualizzati alcuni punti interrogativi (?) Nel database di destinazione.

Infine, ricorda se stai usando un enorme database che è per l'uso della tua lingua locale, ti consiglio di usare la posizione invece di usare troppi spazi.

Credo che il design possa essere diverso. Dipende dall'ambiente su cui lavori.


8

Ho dato un'occhiata alle risposte e molti sembra di raccomandare di utilizzare nvarcharoltre varchar, perché lo spazio non è più un problema, quindi non c'è nulla di male nel permettere Unicode per poco extra storage. Bene, questo non è sempre vero quando si desidera applicare un indice sulla colonna. SQL Server ha un limite di 900 byte per la dimensione del campo che è possibile indicizzare. Quindi se ne hai uno varchar(900)puoi comunque indicizzarlo, ma non varchar(901). Con nvarchar, il numero di caratteri viene dimezzato, quindi puoi indicizzare fino a nvarchar(450). Quindi, se sei sicuro di non averne bisogno nvarchar, non ti consiglio di usarlo.

In generale, nei database, consiglio di attenersi alle dimensioni necessarie, poiché è sempre possibile espandere. Ad esempio, un collega al lavoro una volta pensava che non ci fosse nulla di male nell'utilizzare nvarchar(max)una colonna, poiché non abbiamo alcun problema con l'archiviazione. Successivamente, quando abbiamo provato ad applicare un indice su questa colonna, SQL Server ha rifiutato questo. Se, tuttavia, avesse iniziato con even varchar(5), avremmo potuto semplicemente estenderlo in seguito a ciò di cui abbiamo bisogno senza un tale problema che ci richiederà di fare un piano di migrazione sul campo per risolvere questo problema.


7

nVarchar ti aiuterà a memorizzare i caratteri Unicode. È la strada da percorrere se si desidera archiviare dati localizzati.


7

Se viene utilizzato un singolo byte per memorizzare un carattere, ci sono 256 possibili combinazioni e quindi è possibile salvare 256 caratteri diversi. Le regole di confronto sono il modello che definisce i personaggi e le regole con cui vengono confrontati e ordinati.

1252, che è il Latin1 (ANSI), è il più comune. I set di caratteri a byte singolo sono inoltre inadeguati per memorizzare tutti i caratteri utilizzati da molte lingue. Ad esempio, alcune lingue asiatiche hanno migliaia di caratteri, quindi devono usare due byte per carattere.

Standard Unicode

Quando i sistemi che utilizzano più code page vengono utilizzati in una rete, diventa difficile gestire la comunicazione. Per standardizzare le cose, il consorzio ISO e Unicode ha introdotto Unicode . Unicode utilizza due byte per memorizzare ogni carattere. Cioè 65.536 caratteri diversi possono essere definiti, quindi quasi tutti i personaggi possono essere coperti con Unicode. Se due computer utilizzano Unicode, ogni simbolo verrà rappresentato allo stesso modo e non è necessaria alcuna conversione: questa è l'idea alla base di Unicode.

SQL Server ha due categorie di tipi di dati dei caratteri:

  • non Unicode (char, varchar e text)
  • Unicode (nchar, nvarchar e ntext)

Se dobbiamo salvare i dati dei personaggi da più paesi, usa sempre Unicode.


6

Devo dire qui (mi rendo conto che probabilmente mi aprirò ad una proiezione!), Ma sicuramente l'unica volta in cui NVARCHARè effettivamente più utile (nota più lì!) Di VARCHARquando tutte le regole di confronto su tutti dei sistemi dipendenti e all'interno del database stesso sono gli stessi ...? In caso contrario, la conversione delle regole di confronto deve comunque avvenire e quindi è VARCHARaltrettanto valida NVARCHAR.

Per aggiungere a ciò, alcuni sistemi di database, come SQL Server (prima del 2012) hanno una dimensione della pagina di ca. 8 MILA. Quindi, se stai cercando di archiviare dati ricercabili non contenuti in qualcosa come un campo TEXTo NTEXT, allora VARCHARfornisce lo spazio completo di 8k, mentre NVARCHARfornisce solo 4k (il doppio dei byte, il doppio dello spazio).

Suppongo, per riassumere, l'uso di uno dei due dipende da:

  • Progetto o contesto
  • Infrastruttura
  • Sistema di database

6

Seguire la differenza tra il server SQL VARCHAR e il tipo di dati NVARCHAR . Qui puoi vedere in modo molto descrittivo.

In generale nvarchar memorizza i dati come Unicode, quindi, se hai intenzione di archiviare dati multilingue (più di una lingua) in una colonna di dati hai bisogno della variante N.


Questo è un link molto utile, ma la tua risposta non è molto più di questo: un link.
RubberDuck,

ckuhn203, non ho intenzione di dirti di vederlo
Pradeep Kesharwani,

6

La differenza principale tra Varchar(n)e nvarchar(n)è: inserisci qui la descrizione dell'immagine

VarcharLa dimensione (dati di caratteri a lunghezza variabile e non Unicode) è fino a 8000. 1. È un tipo di dati a lunghezza variabile

  1. Utilizzato per memorizzare caratteri non Unicode

  2. Occupa 1 byte di spazio per ciascun personaggio

inserisci qui la descrizione dell'immagine

Nvarchar: Dati di caratteri Unicode a lunghezza variabile.

1.È un tipo di dati a lunghezza variabile

2. Utilizzato per memorizzare i caratteri Unicode.

  1. I dati sono memorizzati in una codifica Unicode. Ogni lingua è supportata. (ad esempio le lingue arabo, tedesco, hindi, ecc. ecc.)

6

Jeffrey L Whitledge con un punteggio di reputazione di ~ 47000 consiglia l'uso di nvarchar

Solomon Rutzky con un punteggio di reputazione di ~ 33200 consiglia: NON utilizzare sempre NVARCHAR. Questo è un atteggiamento / approccio molto pericoloso e spesso costoso.

Quali sono le principali differenze di prestazioni tra i tipi di dati varchar e nvarchar SQL Server?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

Entrambe le persone di così alta reputazione, cosa sceglie uno sviluppatore di database di server sql di apprendimento?

Ci sono molti avvisi nelle risposte e nei commenti sui problemi di prestazione se non sei coerente nelle scelte.

Ci sono commenti pro / con nvarchar per le prestazioni.

Ci sono commenti pro / con varchar per le prestazioni.

Ho un requisito particolare per una tabella con molte centinaia di colonne, che di per sé è probabilmente insolita?

Sto scegliendo varchar per evitare di avvicinarmi al limite della dimensione del record della tabella 8060 byte di SQL * server 2012.

L'uso di nvarchar, per me, supera questo limite di 8060 byte.

Sto anche pensando che dovrei abbinare i tipi di dati delle tabelle di codici correlati ai tipi di dati della tabella centrale primaria.

Ho visto l'uso della colonna varchar in questo luogo di lavoro, il governo del Sud Australia, da precedenti sviluppatori di database esperti, in cui il conteggio delle righe della tabella sarà di diversi milioni o più (e pochissime colonne nvarchar, se presenti, in questi molto grandi tabelle), quindi forse i volumi delle righe di dati previsti diventano parte di questa decisione.


1

nvarcharè sicuro da usare rispetto a varcharper rendere privo di errori il nostro codice (tipo non corrispondente) perché nvarcharconsente anche caratteri unicode. Quando utilizziamo la wherecondizione nella query di SQL Server e se utilizziamo l' =operatore, questo genererà un errore alcune volte. La ragione probabile per questo è che la nostra colonna di mappatura sarà definita in varchar. Se lo definissimo in nvarcharquesto problema, non accadrà. Tuttavia, ci atteniamo a varcharquesto problema ed è meglio che usiamo la LIKEparola chiave anziché =.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.