Dlaczego musimy umieścić N przed ciągami w Microsoft SQL Server?

34

Uczę się T-SQL. Z przykładów, które widziałem, aby wstawić tekst do varchar()komórki, mogę napisać tylko ciąg do wstawienia, ale w przypadku nvarchar()komórek każdy przykład poprzedza ciąg literą N.

Próbowałem następujące zapytanie w tabeli, która ma nvarchar()wiersze, i działa dobrze, więc przedrostek N nie jest wymagany:

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

Dlaczego ciągi są poprzedzone literą N w każdym przykładzie, który widziałem?

Jakie są zalety i wady używania tego prefiksu?

qinking126
źródło
Czy N nie jest potrzebne tylko dla literalnych ciągów znaków?
Wayne In Yak
Polski jest językiem innym niż łaciński ????
Heckflosse_230
2
Noznacza Krajowy, jak w „Różnych znakach narodowych”, patrz Równoważne typy danych ANSI SQL .
ErikE
Zgadzam się z tym pytaniem i jak dotąd nikt nie odpowiedział na to pytanie, AFAICT. Może to może być przekształcone w „dlaczego jest to złe pozwolić SQL niejawnie przekonwertować VARCHARdo NVARCHARkiedy mój ciąg dosłowny jest ASCII?”.
binki
To pytanie zostało już zadane i udzielono odpowiedzi tutaj: Jaka jest różnica między varchar i nvarchar?

Odpowiedzi:

27

NVarchar jest używany w Unicode. Jeśli baza danych nie przechowuje danych wielojęzycznych, możesz nadal korzystać z Varchar. Na przykład: N'abc'po prostu konwertuje łańcuch znaków na Unicode.

Pieter B.
źródło
2
Dlaczego więc nie musisz przedrostka U zamiast N?
Attila Kun,
U może być zdezorientowany jako zgadywanka
JB King
U&'abc'to właściwy sposób na określenie ciągów znaków Unicode. Zobacz SQL 2003 BNF
ceving
2
N faktycznie oznacza zestaw „National Language Character”.
Mike Bovenlander,
23

Domyślnie SQL Server używa kodów znakowych Windows-1252 dla varchar . Zawiera większość znaków dla języków łacińskich (angielski, niemiecki, francuski itp.), Ale nie zawiera znaków dla języków innych niż łaciński (polski, rosyjski itp.). Jak stwierdził @Pieter B, nvarchar służy do obejścia tego problemu, ponieważ dotyczy Unicode, który zawiera brakujące znaki. To kosztuje, zajmuje dwa razy więcej miejsca do przechowywania nvarchar niż varchar.

Umieszczenie N przed łańcuchem gwarantuje, że znaki zostaną przekonwertowane na Unicode przed umieszczeniem w kolumnie nvarchar. Przez większość czasu nic ci nie będzie, ale nie poleciłbym tego. O wiele lepiej być bezpiecznym niż żałować.

bwalk2895
źródło
3
Tylko wyjaśnienie: „Domyślnie” serwer SQL używa kodowania odpowiadającego sortowaniu pola Varchar, które jest możliwe do zastąpienia w momencie tworzenia pola, ogólnie w oparciu o domyślne sortowanie dla twojej instancji. Domyślne sortowanie dla instancji można ustawić w czasie instalacji, ale ogólnie odpowiada CP_ACP domyślnych ustawień narodowych systemu. Będzie to Windows 1252 na amerykańsko-angielskiej maszynie, ale 932 na maszynie z japońskimi ustawieniami systemowymi, 1251 na rosyjskiej maszynie itp. Morał tej historii? Użyj NVarchar :)
JasonTrue
1
Jak dotąd jest to jedyna odpowiedź, która odpowiada na pytanie: „Po co używać przedrostka N na ciągach literalnych, skoro SQL niejawnie transkoduje?”. Pozostałe odpowiedzi dotyczą innego pytania „Jaka jest różnica między nvarchar vs. varchar?”
Timbo
18

Ponieważ MS SQL Server ma słabą obsługę UTF-8 w porównaniu do innych RDBMS.

MS SQL Server jest zgodny z konwencją, używaną w samym systemie Windows, że „wąskie” ciągi znaków ( charw C ++ CHARlub VARCHARSQL) są zakodowane w starszej „stronie kodowej”. Problem ze stronami kodowymi polega na tym, że mają ograniczoną liczbę znaków (większość to kodowania jednobajtowe, co ogranicza reportoire do 256 znaków) i są zaprojektowane wokół jednego języka (lub grupy języków o podobnych alfabetach). Utrudnia to przechowywanie danych wielojęzycznych. Na przykład nie można przechowywać danych rosyjskich i hebrajskich, ponieważ rosyjski używa strony kodowej 1251, a hebrajski używa strony kodowej 1255 .

Unicode rozwiązuje ten problem, używając jednego gigantycznego zestawu kodowanych znaków z miejscem na ponad milion znaków, wystarczającym do reprezentowania każdego języka na świecie. Istnieje kilka schematów kodowania Unicode; Microsoft woli używać UTF-16 ze względów historycznych . Ponieważ UTF-16 reprezentuje ciągi jako sekwencję 16-bitowych jednostek kodu zamiast tradycyjnego 8-bitowego, potrzebny jest osobny typ znaku. W MSVC ++ jest to wchar_t. A w MS SQL to NCHARlub NVARCHAR. NStoi za „narodowe” , co wydaje się wstecz do mnie, bo jest o Unicode między -nationalization, ale to terminologia ISO.

Inne implementacje SQL pozwalają przechowywać tekst UTF-8 w VARCHARkolumnie. UTF-8 to kodowanie o zmiennej długości (1-4 bajtów na znak), które jest zoptymalizowane dla przypadku, gdy twoje dane są głównie w podstawowym zakresie łacińskim (które są reprezentowane jako taki sam 1 bajt na znak jak ASCII), ale mogą reprezentować dowolny znak Unicode. W ten sposób unikniesz problemu „dwa razy więcej miejsca” wspomnianego przez bwalk2895.

Niestety, MS SQL Server nie obsługuje UTF-8VARCHAR , więc zamiast tego musisz albo użyć UTF-16 (i marnować miejsce na tekst ASCII), użyć strony kodowej innej niż Unicode (i utracić możliwość reprezentowania obcych znaków), lub przechowywać UTF-8 w BINARYkolumnie (i radzić sobie z niedogodnościami, takimi jak nieprawidłowe działanie ciągów SQL lub konieczność przeglądania danych jako zrzut szesnastkowy w menedżerze DB GUI).

dan04
źródło
1
We wcześniejszych wersjach niż SQL Server 2012, używają kodowania UCS-2, które jest ściśle 2-bajtowe. W nowszych wersjach używają UTF-16, który jest mapowaniem zmiennej długości do 4 bajtów na znak (podobnie jak UTF-8, ale zaczyna się od 2 bajtów).
j123b567,