Was ist der Unterschied zwischen varchar und nvarchar?

1354

nvarcharUnterstützt es nur Multibyte-Zeichen? Wenn dies der Fall ist, gibt es wirklich einen anderen Grund als Speicherprobleme bei der Verwendung varchars?

stimms
quelle
6
Ich mag den Punkt von incomudro, es hat mich dazu gebracht, überhaupt über den Unterschied zwischen varchar & nvarchar zu graben. Unsere Java-App für eine SQL Server-Datenbank verwendet myBatis, das standardmäßig Zeichenfolgen als nvarchar zu senden scheint (immer noch nicht sicher, wie (oder ob) dies überschreibbar ist). Eine einfache Abfrage stellte sich als großes Leistungsproblem heraus, da ich die Spalte, für die sie ausgewählt wurde, als varchar und nicht als nvarchar definiert hatte und den Index für die Spalte ignorierte.
Sean Read

Antworten:

1652

In einer nvarcharSpalte können beliebige Unicode-Daten gespeichert werden. Eine varcharSpalte ist auf eine 8-Bit-Codepage beschränkt. Einige Leute denken, dass varchardies verwendet werden sollte, weil es weniger Platz beansprucht. Ich glaube, das ist nicht die richtige Antwort. Codepage-Inkompatibilitäten sind ein Schmerz, und Unicode ist das Heilmittel für Codepage-Probleme. Bei billigen Festplatten und Speicher gibt es heutzutage wirklich keinen Grund mehr, Zeit mit Codepages zu verschwenden.

Alle modernen Betriebssysteme und Entwicklungsplattformen verwenden Unicode intern. Wenn Sie nvarcharanstatt verwenden varchar, können Sie vermeiden, dass bei jedem Lesen oder Schreiben in die Datenbank Codierungskonvertierungen durchgeführt werden. Konvertierungen brauchen Zeit und sind fehleranfällig. Die Wiederherstellung nach Konvertierungsfehlern ist ein nicht triviales Problem.

Wenn Sie eine Schnittstelle zu einer Anwendung herstellen, die nur ASCII verwendet, würde ich weiterhin die Verwendung von Unicode in der Datenbank empfehlen. Die Betriebssystem- und Datenbankkollatierungsalgorithmen funktionieren mit Unicode besser. Unicode vermeidet Konvertierungsprobleme bei der Verbindung mit anderen Systemen. Und Sie bereiten sich auf die Zukunft vor. Sie können jederzeit überprüfen, ob Ihre Daten für jedes zu wartende Legacy-System auf 7-Bit-ASCII beschränkt sind, auch wenn Sie einige der Vorteile des vollständigen Unicode-Speichers nutzen.

Jeffrey L Whitledge
quelle
8
Das sind großartige Informationen. Verstehe ich das also richtig, wenn ich daraus schließe, dass die Wahl letztendlich eine der folgenden ist: Welche Ressource ist billiger: Prozessor + Entwicklungsaufwand oder Speicher?
Matt Cashatt
141
@MatthewPatrickCashatt - Sie könnten es so sehen. Wenn Sie sich jedoch eine herrliche Welt vorstellen, in der sich alle Textdaten in Unicode befinden und Entwickler einfach nie darüber nachdenken müssen, in welcher Codierung sich etwas befindet, und eine ganze Klasse von Fehlern einfach nie auftritt, können Sie sehen, dass dies der Fall ist wirklich überhaupt keine Wahl.
Jeffrey L Whitledge
8
@ Martin Smith - In diesen Fällen verschwindet der winzige Vorteil, den Varchar bietet (kompakte Lagerung). Ich denke, Varchar ist noch schlimmer als ich dachte!
Jeffrey L Whitledge
9
@PeterAllenWebb - Sie können alle Unicode-Daten „speichern“, da die Ersatzpaare in UTF-16 in UCS-2 so gespeichert werden können, als wären sie Zeichen. Das funktioniert transparent für das Speichern und Abrufen von Daten. Was Sie jetzt nicht tun können, ist zuverlässige Falltransformationen und Vergleiche außerhalb des BMP zu erhalten, aber ich habe keine Behauptungen darüber aufgestellt. Wenn Sie also viel Desseret-Text haben, für den Sie die Verarbeitung durchführen möchten, ist es am besten, dies außerhalb der Datenbank zu tun. Aber es ist in Ordnung, es dort aufzubewahren. (Natürlich wird Varchar Ihnen auch dort nicht helfen!)
Jeffrey L Whitledge
259

varchar : Nicht-Unicode-Zeichendaten variabler Länge. Die Datenbanksortierung bestimmt, auf welcher Codepage die Daten gespeichert werden.

nvarchar : Unicode-Zeichendaten variabler Länge. Abhängig von der Datenbanksortierung für Vergleiche.

Verwenden Sie mit diesem Wissen diejenige, die Ihren Eingabedaten entspricht (ASCII v. Unicode).

user7116
quelle
5
Gibt es eine Einschränkung, dass varchar keine Unicode-Daten speichern kann? Es sind alles Einsen und Nullen. Ich bin in der Lage, chinesische Inhalte als varchar in meiner Datenbank zu speichern. Ich spezifiziere nur sein UTF-8. Wie funktioniert das dann?
Nishant
3
@Nishant späte Antwort : Natürlich können Sie UTF-8 in varchar speichern, aber es wird die SQL Server-Zeichenfolgenfunktionen beschädigen. Wenn Sie alle Suchvorgänge / Transformationen in Ihrer Anwendung durchführen, können Sie dies tun (aber was ist der Vorteil?). Nur die von SS unterstützte Unicode-Codierung ist UCS-2 (ja, nicht UTF-16 vor SS2k16), und die Zeichenfolgenfunktionen funktionieren nur mit dieser Codierung. Übrigens, was ist mit Indizes? Wenn Sie beliebige Daten speichern möchten, verwenden Sie stattdessen Binärdaten.
Adriano Repetti
Ja, es bricht nur die String-Suchfunktionen.
Nishant
8
Also, weißt du ... es "funktioniert" nicht. Das ist so, als würde man ein floatin ein speichern intund sagen: "Sicher, die Dezimalstellen gehen verloren." Tu es einfach nicht.
user7116
70

Ich benutze immer nvarchar, da es ermöglicht, dass alles, was ich baue, so ziemlich allen Daten standhält, die ich darauf werfe. Mein CMS-System spricht versehentlich Chinesisch, weil ich nvarchar verwendet habe. Heutzutage sollten sich neue Anwendungen nicht wirklich mit dem erforderlichen Speicherplatz befassen.

tags2k
quelle
25
Die Idee, dass neue Apps sich nicht mit Speicherplatzbeschränkungen befassen sollten, ist etwas kurzsichtig, und jeder, der sich mit Datenbanken auf mittlerer bis großer Unternehmensebene befasst hat, wird Ihnen gerne mitteilen, dass dies völlig falsch ist.
Frater
60
Um sich die Freiheit zu nehmen, Wörter in den Mund von tags2k zu stecken, könnte eine genauere Aussage lauten: "Es ist zunehmend unwahrscheinlich, dass neue Apps sich mehr Gedanken über den erforderlichen Speicherplatz machen als über Internationalisierung und andere Probleme mit Zeichensätzen."
Cowan
1
"Heutzutage sollten sich neue Apps nicht wirklich mit dem benötigten Speicherplatz befassen." - Es sei denn, Sie verwenden kostenlosen Cloud-Speicher, bei dem der bezahlte Plan ein beträchtlicher Sprung in $ ist (siehe Gemeinsame Pläne für AppHarbor SQL Server).
Ganders
3
@ganders Heulen! Du bist genau dort. Verallgemeinerte Aussagen sind im besten Fall nur vorübergehend korrekt. Computing ist definitiv ein Swings and Roundabout-Spiel. Ich bin definitiv besorgt darüber, wie viel Speicherplatz ich unter Windows Azure CCP verwende. Das heißt, ich würde "nie" varchar über nvarchar verwenden. Ooo habe ich mich nur widersprochen?
Risma
1
@rism, ich glaube, Sie haben das Risiko eines Widerspruchs bei der Verwendung von Zitaten "never"zumindest technisch beseitigt .
Smandoli
30

Dies hängt davon ab, wie Oracle installiert wurde. Während des Installationsvorgangs wird die Option NLS_CHARACTERSET festgelegt. Möglicherweise können Sie es mit der Abfrage finden SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Wenn Ihr NLS_CHARACTERSET eine Unicode-Codierung wie UTF8 ist, ist das großartig. Die Verwendung von VARCHAR und NVARCHAR ist ziemlich identisch. Hör jetzt auf zu lesen, mach es einfach. Andernfalls oder wenn Sie keine Kontrolle über den Oracle-Zeichensatz haben, lesen Sie weiter.

VARCHAR - Daten werden in der NLS_CHARACTERSET-Codierung gespeichert. Wenn sich andere Datenbankinstanzen auf demselben Server befinden, werden Sie möglicherweise von diesen eingeschränkt. und umgekehrt, da Sie die Einstellung teilen müssen. In einem solchen Feld können alle Daten gespeichert werden, die mit diesem Zeichensatz codiert werden können, und sonst nichts . Wenn der Zeichensatz beispielsweise MS-1252 ist, können Sie nur Zeichen wie englische Buchstaben, eine Handvoll Buchstaben mit Akzent und einige andere (wie € und -) speichern. Ihre Anwendung ist nur für wenige Gebietsschemas nützlich, die nirgendwo anders auf der Welt eingesetzt werden können. Aus diesem Grund wird es als eine schlechte Idee angesehen.

NVARCHAR - Daten werden in einer Unicode-Codierung gespeichert. Jede Sprache wird unterstützt. Eine gute Idee.

Was ist mit Speicherplatz? VARCHAR ist im Allgemeinen effizient, da der Zeichensatz / die Codierung für ein bestimmtes Gebietsschema speziell entwickelt wurde. NVARCHAR-Felder werden entweder in UTF-8- oder UTF-16-Codierung gespeichert, basierend auf der NLS-Einstellung, ironischerweise. UTF-8 ist sehr effizient für "westliche" Sprachen und unterstützt weiterhin asiatische Sprachen. UTF-16 ist für asiatische Sprachen sehr effizient und unterstützt weiterhin "westliche" Sprachen. Wenn Sie Bedenken hinsichtlich des Speicherplatzes haben, wählen Sie eine NLS-Einstellung aus, damit Oracle UTF-8 oder UTF-16 verwendet.

Was ist mit der Verarbeitungsgeschwindigkeit? Die meisten neuen Codierungsplattformen verwenden Unicode nativ (Java, .NET, sogar C ++ std :: wstring von vor Jahren!). Wenn das Datenbankfeld also VARCHAR ist, wird Oracle gezwungen, bei jedem Lesen oder Schreiben zwischen Zeichensätzen zu konvertieren, was nicht so gut ist. Durch die Verwendung von NVARCHAR wird die Konvertierung vermieden.

Fazit: Verwenden Sie NVARCHAR! Es vermeidet Einschränkungen und Abhängigkeiten, ist gut für den Speicherplatz und normalerweise auch für die Leistung am besten geeignet.

Jeremy Frank
quelle
42
Dies ist eine wirklich gute Antwort, außer dass es sich bei der Frage um SQL-Server handelt.
Stimms
21

nvarchar speichert Daten als Unicode. Wenn Sie also mehrsprachige Daten (mehr als eine Sprache) in einer Datenspalte speichern möchten, benötigen Sie die N-Variante.

Albertein
quelle
16

Meine zwei Cent

  1. Indizes können fehlschlagen, wenn nicht die richtigen Datentypen verwendet werden:
    In SQL Server: Wenn Sie einen Index über eine VARCHAR-Spalte haben und eine Unicode-Zeichenfolge anzeigen, verwendet SQL Server den Index nicht. Das gleiche passiert, wenn Sie ein BigInt einer indizierten Spalte präsentieren, die SmallInt enthält. Selbst wenn der BigInt klein genug ist, um ein SmallInt zu sein, kann SQL Server den Index nicht verwenden. Umgekehrt tritt dieses Problem nicht auf (wenn Sie SmallInt oder Ansi-Code für eine indizierte BigInt ot NVARCHAR-Spalte bereitstellen).

  2. Datentypen können zwischen verschiedenen DBMS (DataBase Management System) variieren:
    Wissen Sie, dass jede Datenbank leicht unterschiedliche Datentypen hat und VARCHAR nicht überall dasselbe bedeutet. Während SQL Server über VARCHAR und NVARCHAR verfügt, verfügt eine Apache / Derby-Datenbank nur über VARCHAR und VARCHAR befindet sich in Unicode.

incomudro
quelle
Aber wenn Sie Ihren Code richtig schreiben (dh parametrisierte Abfragen usw. verwenden), ist Punkt 1 sicherlich ein geringeres Risiko.
Paul
14

In nvarchar werden hauptsächlich Unicode-Zeichen und in varchar Nicht-Unicode-Zeichen gespeichert .

"Unicodes" bedeutet ein 16-Bit-Zeichencodierungsschema, mit dem Zeichen aus vielen anderen Sprachen wie Arabisch, Hebräisch, Chinesisch, Japanisch in einem einzigen Zeichensatz codiert werden können.

Das bedeutet, dass Unicodes 2 Bytes pro Zeichen zum Speichern verwenden und Nicht-Unicodes nur ein Byte pro Zeichen zum Speichern verwenden. Dies bedeutet, dass Unicodes im Vergleich zu Nicht-Unicodes eine doppelte Speicherkapazität benötigen.

Ranjit Pawar
quelle
10

Du hast recht. nvarcharspeichert Unicode-Daten, während varcharEinzelbyte-Zeichendaten gespeichert werden. Anders als Speicher Unterschiede ( nvarcharerfordert den doppelten Speicherplatz als varchar), die Sie schon der Hauptgrund für die Bevorzugung erwähnt, nvarcharüber die varcharInternationalisierung wäre (dh die Speicherung Strings in anderen Sprachen).

Mike Spross
quelle
10

Ich würde sagen, es kommt darauf an.

Wenn Sie eine Desktop-Anwendung entwickeln, bei der das Betriebssystem in Unicode funktioniert (wie alle aktuellen Windows-Systeme) und die Sprache Unicode nativ unterstützt (Standardzeichenfolgen sind Unicode, wie in Java oder C #), gehen Sie zu nvarchar.

Wenn Sie eine Webanwendung entwickeln, bei der Zeichenfolgen als UTF-8 eingehen und die Sprache PHP ist, das Unicode nativ (in Version 5.x) immer noch nicht unterstützt, ist varchar wahrscheinlich die bessere Wahl.

sleepy012
quelle
9

Obwohl NVARCHARUnicode VARCHARgespeichert wird , sollten Sie mithilfe der Sortierung berücksichtigen, dass Sie auch Ihre Daten Ihrer Landessprachen verwenden und speichern können.

Stellen Sie sich das folgende Szenario vor.

Die Sortierung Ihrer Datenbank ist persisch und Sie speichern einen Wert wie 'علی' (persische Schrift von Ali) im VARCHAR(10)Datentyp. Es gibt kein Problem und das DBMS verwendet nur drei Bytes, um es zu speichern.

Wenn Sie jedoch Ihre Daten in eine andere Datenbank übertragen möchten und das richtige Ergebnis sehen möchten, muss Ihre Zieldatenbank dieselbe Sortierung aufweisen wie das in diesem Beispiel persische Ziel.

Wenn Ihre Zielsortierung unterschiedlich ist, werden in der Zieldatenbank einige Fragezeichen (?) Angezeigt.

Denken Sie schließlich daran, wenn Sie eine große Datenbank verwenden, die für die Verwendung Ihrer Landessprache vorgesehen ist, würde ich empfehlen, den Standort zu verwenden, anstatt zu viele Leerzeichen zu verwenden.

Ich glaube, das Design kann anders sein. Dies hängt von der Umgebung ab, in der Sie arbeiten.

Ali Elmi
quelle
8

Ich hatte einen Blick auf den Antworten und viele scheinen zu empfehlen zu verwenden , nvarcharüber varchar, weil der Platz kein Problem mehr ist, so gibt es keinen Schaden in ermöglicht Unicode für wenig zusätzlichen Speicherplatz. Dies ist nicht immer der Fall, wenn Sie einen Index auf Ihre Spalte anwenden möchten. SQL Server hat ein Limit von 900 Byte für die Größe des Feldes, das Sie indizieren können. Wenn Sie also eine haben varchar(900), können Sie diese trotzdem indizieren, aber nicht varchar(901). Mit nvarcharwird die Anzahl der Zeichen halbiert, sodass Sie bis zu indizieren können nvarchar(450). Wenn Sie also sicher sind, dass Sie es nicht brauchen nvarchar, empfehle ich es nicht.

Im Allgemeinen empfehle ich, in Datenbanken die gewünschte Größe beizubehalten, da Sie jederzeit erweitern können. Zum Beispiel hat ein Arbeitskollege einmal gedacht, dass die Verwendung nvarchar(max)für eine Spalte keinen Schaden anrichtet , da wir überhaupt kein Problem mit der Speicherung haben. Als wir später versuchten, einen Index auf diese Spalte anzuwenden, lehnte SQL Server dies ab. Wenn er jedoch mit Even angefangen hätte varchar(5), hätten wir es später einfach auf das erweitern können, was wir brauchen, ohne ein solches Problem, das es erforderlich macht, einen Feldmigrationsplan zu erstellen, um dieses Problem zu beheben.

Rafid
quelle
7

Mit nVarchar können Sie Unicode-Zeichen speichern. Dies ist der richtige Weg, wenn Sie lokalisierte Daten speichern möchten.

Vijesh VP
quelle
7

Wenn ein einzelnes Byte zum Speichern eines Zeichens verwendet wird, gibt es 256 mögliche Kombinationen, wodurch Sie 256 verschiedene Zeichen speichern können. Kollatierung ist das Muster, das die Zeichen und Regeln definiert, nach denen sie verglichen und sortiert werden.

1252, das ist Latin1 (ANSI), ist das häufigste. Einzelbyte-Zeichensätze reichen auch nicht aus, um alle von vielen Sprachen verwendeten Zeichen zu speichern. Einige asiatische Sprachen haben beispielsweise Tausende von Zeichen, daher müssen zwei Bytes pro Zeichen verwendet werden.

Unicode-Standard

Wenn Systeme mit mehreren Codepages in einem Netzwerk verwendet werden, wird es schwierig, die Kommunikation zu verwalten. Um die Dinge zu standardisieren, führte das ISO- und Unicode-Konsortium den Unicode ein . Unicode verwendet zwei Bytes zum Speichern jedes Zeichens. Das heißt, 65.536 verschiedene Zeichen können definiert werden, sodass fast alle Zeichen mit Unicode abgedeckt werden können. Wenn zwei Computer Unicode verwenden, wird jedes Symbol auf dieselbe Weise dargestellt und es ist keine Konvertierung erforderlich - dies ist die Idee hinter Unicode.

SQL Server verfügt über zwei Kategorien von Zeichendatentypen:

  • Nicht-Unicode (char, varchar und text)
  • Unicode (nchar, nvarchar und ntext)

Wenn wir Zeichendaten aus mehreren Ländern speichern müssen, verwenden Sie immer Unicode.

Jithin Shaji
quelle
6

Ich muss sagen , hier (ich weiß , dass ich mich wahrscheinlich werde ein Verriss öffnen!), Aber sicher das einzige Mal , wenn NVARCHARtatsächlich mehr nützlich ( man beachte die mehr dort!) Als VARCHARist , wenn alle der Sortierungen auf allen der abhängigen Systeme und innerhalb der Datenbank selbst sind die gleichen ...? Wenn nicht, muss die Kollatierungskonvertierung trotzdem erfolgen und ist daher VARCHARgenauso realisierbar wie NVARCHAR.

Einige Datenbanksysteme, wie z. B. SQL Server (vor 2012), haben eine Seitengröße von ca. 8 TAUSEND. Wenn Sie also durchsuchbare Daten speichern möchten, die nicht in einem TEXToder einem NTEXTFeld gespeichert sind, VARCHARwird der gesamte Speicherplatz von 8 KB bereitgestellt, während NVARCHARnur 4 KB bereitgestellt werden (doppelte Bytes, doppelter Speicherplatz).

Ich nehme zusammen, um zusammenzufassen, die Verwendung von beidem hängt ab von:

  • Projekt oder Kontext
  • Infrastruktur
  • Datenbanksystem
Paul
quelle
6

Folgen Sie dem Unterschied zwischen dem SQL Server VARCHAR- und dem NVARCHAR-Datentyp . Hier konnte man sehr anschaulich sehen.

Im Allgemeinen speichert nvarchar Daten als Unicode. Wenn Sie also mehrsprachige Daten (mehr als eine Sprache) in einer Datenspalte speichern möchten, benötigen Sie die N-Variante.

Pradeep Kesharwani
quelle
Dies ist ein sehr nützlicher Link, aber Ihre Antwort ist nicht viel mehr als das: ein Link.
RubberDuck
ckuhn203, ich werde dir nicht sagen, dass du diesen sehen sollst
Pradeep Kesharwani
6

Der Hauptunterschied zwischen Varchar(n)und nvarchar(n)ist: Geben Sie hier die Bildbeschreibung ein

VarcharDie Größe (Nicht-Unicode-Zeichendaten variabler Länge) beträgt bis zu 8000. 1. Es handelt sich um einen Datentyp variabler Länge

  1. Wird zum Speichern von Nicht-Unicode-Zeichen verwendet

  2. Belegt 1 Byte Platz für jedes Zeichen

Geben Sie hier die Bildbeschreibung ein

Nvarchar: Unicode-Zeichendaten variabler Länge.

1. Es ist ein Datentyp variabler Länge

2. Wird zum Speichern von Unicode-Zeichen verwendet.

  1. Daten werden in einer Unicode-Codierung gespeichert. Jede Sprache wird unterstützt. (zum Beispiel die Sprachen Arabisch, Deutsch, Hindi usw.)
Debendra Dash
quelle
6

Jeffrey L Whitledge mit ~ 47000 Reputation Score empfiehlt die Verwendung von nvarchar

Solomon Rutzky mit einem Reputationswert von ~ 33200 empfiehlt: Verwenden Sie NVARCHAR NICHT immer. Das ist eine sehr gefährliche und oft kostspielige Einstellung.

Was sind die Hauptleistungsunterschiede zwischen den Datentypen varchar und nvarchar SQL Server?

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

Was wählt ein lernender SQL Server-Datenbankentwickler für beide Personen mit einem so hohen Ansehen?

Es gibt viele Warnungen in Antworten und Kommentaren zu Leistungsproblemen, wenn Sie bei der Auswahl nicht konsistent sind.

Es gibt Kommentare pro / con nvarchar für die Leistung.

Es gibt Kommentare pro / con varchar für die Leistung.

Ich habe eine besondere Anforderung an eine Tabelle mit vielen hundert Spalten, was an sich wahrscheinlich ungewöhnlich ist?

Ich wähle varchar, um zu vermeiden, dass die Größenbeschränkung für 8060-Byte-Tabellendatensätze von SQL * Server 2012 erreicht wird.

Die Verwendung von nvarchar überschreitet für mich diese 8060-Byte-Grenze.

Ich denke auch, dass ich die Datentypen der zugehörigen Codetabellen mit den Datentypen der primären zentralen Tabelle abgleichen sollte.

Ich habe an diesem Arbeitsplatz, der südaustralischen Regierung, die Verwendung von varchar-Spalten durch frühere erfahrene Datenbankentwickler gesehen, bei denen die Anzahl der Tabellenzeilen mehrere Millionen oder mehr betragen wird (und nur sehr wenige nvarchar-Spalten, wenn überhaupt, in diesen sehr großen Tabellen), so dass möglicherweise die erwarteten Datenzeilenvolumina Teil dieser Entscheidung werden.

Allan F.
quelle
1

nvarcharist im Vergleich zu sicher zu verwenden varchar, um unseren Code fehlerfrei zu machen (Typ-Nichtübereinstimmung), da auch nvarcharUnicode-Zeichen zulässig sind. Wenn wir die whereBedingung in der SQL Server-Abfrage verwenden und den =Operator verwenden, wird manchmal ein Fehler ausgegeben. Wahrscheinlicher Grund dafür ist, dass in unserer Mapping-Spalte unterschieden wird varchar. Wenn wir es in nvarchardiesem Problem definiert haben, passiert es nicht. Trotzdem halten wir uns an varchardieses Problem und vermeiden es besser. Wir verwenden lieber LIKESchlüsselwörter als =.

Rinoy Ashokan
quelle