Warum müssen wir in Microsoft SQL Server N vor Zeichenfolgen setzen?

34

Ich lerne T-SQL. Aus den Beispielen, die ich gesehen habe, kann ich zum Einfügen von Text in eine varchar()Zelle nur die einzufügende Zeichenfolge schreiben, aber für nvarchar()Zellen wird in jedem Beispiel den Zeichenfolgen der Buchstabe N vorangestellt.

Ich habe die folgende Abfrage für eine Tabelle mit nvarchar()Zeilen versucht, und sie funktioniert einwandfrei, sodass das Präfix N nicht erforderlich ist:

insert into [TableName] values ('Hello', 'World')

Warum wird den Zeichenfolgen in jedem Beispiel, das ich gesehen habe, N vorangestellt?

Welche Vor- oder Nachteile hat die Verwendung dieses Präfixes?

qinking126
quelle
Wird das N nicht nur für wörtliche Zeichenfolgen benötigt?
Wayne In Yak
Polnisch ist eine nicht lateinische Sprache ????
Heckflosse_230
2
Nbedeutet National, wie in "National Varying Character", siehe Äquivalente ANSI SQL-Datentypen .
ErikE
Ich stimme dieser Frage zu und bisher hat sie niemand beantwortet, AFAICT. Vielleicht könnte man das so formulieren: "Warum ist es schlecht VARCHAR, NVARCHARwenn SQL implizit meine Zeichen konvertiert , wenn mein Zeichenfolgenliteral ASCII ist?".
binki
Diese Frage wurde bereits hier gestellt und beantwortet: Was ist der Unterschied zwischen varchar und nvarchar?

Antworten:

27

NVarchar wird für Unicode verwendet. Wenn Ihre Datenbank keine mehrsprachigen Daten speichert, können Sie Varchar weiterhin verwenden. Als Beispiel: N'abc'Konvertiert einfach Ihren String in Unicode.

Pieter B
quelle
2
Warum müssen Sie dann nicht U anstelle von N voranstellen?
Attila Kun
U könnte für unsigniert als eine Vermutung verwechselt werden
JB King
U&'abc'ist der richtige Weg, um Unicode-Zeichenfolgen anzugeben. Siehe SQL 2003 BNF
26.
2
Das N steht eigentlich für "National Language Character Set".
Mike Bovenlander
23

Standardmäßig verwendet SQL Server die Windows-1252- Zeichencodes für varchar . Es enthält die meisten Zeichen für lateinische Sprachen (Englisch, Deutsch, Französisch usw.), jedoch keine Zeichen für nicht lateinische Sprachen (Polnisch, Russisch usw.). Wie von @Pieter B angegeben, wird nvarchar verwendet, um dieses Problem zu umgehen, da Unicode diese fehlenden Zeichen enthält. Dies ist mit Kosten verbunden, da der Speicherplatz für nvarchar doppelt so groß ist wie für varchar.

Wenn Sie N vor Ihre Zeichenfolge setzen, wird sichergestellt, dass die Zeichen in Unicode konvertiert werden, bevor sie in eine nvarchar-Spalte eingefügt werden. Meistens ist es in Ordnung, wenn Sie das N auslassen, aber ich würde es nicht empfehlen. Es ist viel besser als Nachsicht.

bwalk2895
quelle
3
Nur eine Klarstellung: "Standardmäßig" SQL Server verwendet die Codierung, die der Sortierung des Varchar-Felds entspricht und die zum Zeitpunkt der Erstellung des Felds überschrieben werden kann. Dies basiert im Allgemeinen auf der Standard-Sortierung für Ihre Instanz. Die Standardkollatierung für Ihre Instanz kann zum Zeitpunkt der Installation festgelegt werden, entspricht jedoch im Allgemeinen dem CP_ACP des Systemstandardgebietsschemas. Das wird Windows 1252 auf einem US-englischen Computer sein, aber 932 auf einem Computer mit einem japanischen Systemgebietsschema, 1251 auf einem russischen Computer usw. Die Moral der Geschichte? Verwenden Sie NVarchar :)
JasonTrue
1
Bisher ist dies die einzige Antwort, die sich mit der Frage beschäftigt, warum das Präfix N für Literalzeichenfolgen verwendet wird, da SQL implizit transkodiert. Die anderen Antworten beziehen sich alle auf eine andere Frage: "Was ist der Unterschied zwischen nvarchar und varchar?"
Timbo
18

Weil MS SQL Server UTF-8 im Vergleich zu anderen RDBMS schlecht unterstützt.

MS SQL Server folgt der in Windows selbst verwendeten Konvention, dass "schmale" Zeichenfolgen ( charin C ++ CHARoder VARCHARSQL) in einer alten "Codepage" codiert werden . Das Problem bei Codepages besteht darin, dass sie eine begrenzte Anzahl von Zeichen haben (die meisten sind Einzelbyte-Codierungen, die das Reportoire auf 256 Zeichen begrenzen) und auf eine einzelne Sprache (oder eine Gruppe von Sprachen mit ähnlichen Alphabeten) ausgelegt sind. Dies macht es schwierig, mehrsprachige Daten zu speichern. Beispielsweise können Sie nicht sowohl russische als auch hebräische Daten speichern, da Russisch die Codepage 1251 und Hebräisch die Codepage 1255 verwendet .

Unicode löst dieses Problem, indem ein einziger riesiger Zeichensatz mit Platz für mehr als eine Million Zeichen verwendet wird, der für alle Sprachen der Welt ausreicht. Es gibt verschiedene Unicode-Codierungsschemata. Microsoft bevorzugt aus historischen Gründen die Verwendung von UTF-16 . Da UTF-16 Zeichenfolgen als Folge von 16-Bit-Codeeinheiten anstelle der herkömmlichen 8-Bit-Zeichen darstellt, ist ein separater Zeichentyp erforderlich. In MSVC ++ ist dies . Und in MS SQL ist es oder . Das steht für „national“ , die mir scheint nach hinten , weil Unicode etwa ist unter -nationalization, aber das ist die ISO - Terminologie.wchar_tNCHARNVARCHARN

In anderen SQL-Implementierungen können Sie UTF-8- Text in einer VARCHARSpalte speichern . UTF-8 ist eine Codierung mit variabler Länge (1 bis 4 Bytes pro Zeichen), die für den Fall optimiert ist, dass sich Ihre Daten hauptsächlich im Bereich Basic Latin befinden (die als dasselbe 1 Byte pro Zeichen wie ASCII dargestellt werden, jedoch darstellen können) ein beliebiges Unicode-Zeichen. So vermeiden Sie das von bwalk2895 erwähnte Problem "doppelt so viel Speicherplatz".

Leider unterstützt MS SQL Server UTF-8 nichtVARCHAR . Stattdessen müssen Sie entweder UTF-16 verwenden (und Platz für ASCII-Text verschwenden), eine Nicht-Unicode-Codepage verwenden (und die Fähigkeit zur Darstellung von Fremdzeichen verlieren). oder speichern Sie UTF-8 in einer BINARYSpalte (und umgehen Sie Unannehmlichkeiten wie nicht ordnungsgemäß funktionierende SQL- Zeichenfolgenfunktionen oder das Anzeigen der Daten als Hex-Dump in Ihrem GUI-DB-Manager).

dan04
quelle
1
In früheren Versionen als SQL Server 2012 wurde die UCS-2-Codierung verwendet, die ausschließlich 2 Byte beträgt. In neueren Versionen wird UTF-16 verwendet, bei dem es sich um eine Zuordnung variabler Länge zu 4 Byte pro Zeichen handelt (ähnlich wie UTF-8, jedoch ab 2 Byte).
j123b567