Pourquoi avons-nous besoin de mettre N avant les chaînes dans Microsoft SQL Server?

34

J'apprends T-SQL. D'après les exemples que j'ai vus, pour insérer du texte dans une varchar()cellule, je peux écrire uniquement la chaîne à insérer, mais pour les nvarchar()cellules, tous les exemples préfixent les chaînes avec la lettre N.

J'ai essayé la requête suivante sur une table qui a des nvarchar()lignes, et cela fonctionne bien, donc le préfixe N n'est pas requis:

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

Pourquoi les chaînes sont-elles préfixées par N dans chaque exemple que j'ai vu?

Quels sont les avantages ou les inconvénients de l'utilisation de ce préfixe?

qinking126
la source
Le N n'est-il pas seulement nécessaire pour les chaînes littérales?
Wayne In Yak
Le polonais est une langue non-latine ????
Heckflosse_230
2
Nsignifie National, comme dans "Caractère national variable", voir Types de données ANSI SQL équivalents .
ErikE
Je suis d'accord avec cette question et personne n'y a répondu jusqu'à présent, AFAICT. Peut-être pourrait-il être reformulé comme suit: «Pourquoi est-il mauvais de laisser SQL implicitement convertir mon VARCHARen NVARCHARlorsque ma chaîne de caractères est ASCII?».
binki
Cette question a déjà été posée et répondue ici: Quelle est la différence entre varchar et nvarchar?

Réponses:

27

NVarchar est utilisé pour Unicode. Si votre base de données ne stocke pas de données multilingues, vous pouvez continuer à utiliser Varchar. Par exemple: N'abc'convertit simplement votre chaîne en unicode.

Pieter B
la source
2
Pourquoi ne pas préfixer par U au lieu de N alors?
Attila Kun
U pourrait être confondu pour non signé
JB King
U&'abc'est le bon moyen de spécifier des chaînes Unicode. Voir le SQL 2003 BNF
Ceving
2
Le N représente en fait "le caractère de la langue nationale".
Mike Bovenlander
23

Par défaut, SQL Server utilise les codes de caractères Windows-1252 pour varchar . Il contient la plupart des caractères pour les langues latines (anglais, allemand, français, etc.), mais ne contient pas de caractères pour les langues autres que latines (polonais, russe, etc.). Comme indiqué par @Pieter B, nvarchar est utilisé pour contourner ce problème car il s’agit de l’ Unicode qui contient ces caractères manquants. Cela a un coût, il faut deux fois plus d’espace pour stocker nvarchar que varchar.

Mettre N devant votre chaîne garantit que les caractères sont convertis en Unicode avant d’être placés dans une colonne nvarchar. La plupart du temps, vous pourrez laisser le N éteint, mais je ne le recommanderais pas. Il vaut mieux prévenir que guérir.

bwalk2895
la source
3
Juste une précision: "Par défaut", le serveur SQL utilise le codage correspondant au classement du champ Varchar, qui peut être remplacé au moment de la création du champ, généralement basé sur le classement par défaut de votre instance. Le classement par défaut de votre instance peut être défini au moment de l'installation, mais correspond généralement aux paramètres régionaux par défaut du système, CP_ACP. Ce sera Windows 1252 sur une machine anglo-américaine, mais 932 sur une machine avec une localisation système japonaise, 1251 sur une machine russe, etc. La morale de l'histoire? Utilisez NVarchar :)
JasonTrue
1
Jusqu'à présent, c'est la seule réponse qui répond à la question "Pourquoi utiliser le préfixe N dans les chaînes littérales, car SQL transcode implicitement?". Les autres réponses sont toutes pour une question différente "Quelle est la différence entre nvarchar et varchar?"
Timbo le
18

Parce que MS SQL Server supporte mal UTF-8 par rapport aux autres SGBDR.

MS SQL Server suit la convention, utilisée dans Windows lui-même, selon laquelle les chaînes "étroites" ( charen C ++ CHARou VARCHARen SQL) sont codées dans une "page de code" héritée. Le problème avec les pages de codes est qu’elles ont un nombre limité de caractères (la plupart sont des encodages sur un octet, ce qui limite le rapport à 256 caractères) et sont conçues autour d’une seule langue (ou d’un groupe de langues avec des alphabets similaires). Cela rend difficile le stockage de données multilingues. Par exemple, vous ne pouvez pas stocker des données en russe et en hébreu, car le russe utilise la page de codes 1251 et l'hébreu utilise la page de codes 1255 .

Unicode résout ce problème en utilisant un seul jeu de caractères codé géant pouvant contenir plus d'un million de caractères, suffisamment pour représenter toutes les langues du monde. Il existe plusieurs schémas de codage Unicode; Microsoft préfère utiliser UTF-16 , pour des raisons historiques . Etant donné que UTF-16 représente les chaînes sous la forme d'une séquence d'unités de code 16 bits au lieu des 8 bits traditionnels, un type de caractère séparé est nécessaire. En MSVC ++, c'est wchar_t. Et en MS SQL, c'est NCHARou NVARCHAR. Le Nsignifie « national » , qui semble en arrière pour moi parce que Unicode est sur le point entre -nationalization, mais c'est la terminologie ISO.

D'autres implémentations SQL vous permettent de stocker du texte UTF-8 dans une VARCHARcolonne. UTF-8 est un codage de longueur variable (1 à 4 octets par caractère) optimisé pour le cas où vos données se situent principalement dans la plage Basic Basic (représentées par le même octet qu'un caractère par caractère ASCII), mais peuvent représenter. n'importe quel caractère Unicode. Ainsi, vous éviteriez le problème de "deux fois plus d'espace" mentionné par bwalk2895.

Malheureusement, MS SQL Server ne prend pas en charge UTF-8VARCHAR . Vous devez donc utiliser UTF-16 à la place (et gaspiller de l'espace pour du texte ASCII), utiliser une page de code non Unicode (et perdre la possibilité de représenter des caractères étrangers), ou stockez UTF-8 dans une BINARYcolonne (et faites face à des inconvénients tels que les fonctions de chaîne SQL ne fonctionnant pas correctement ou devant afficher les données sous forme de vidage hexadécimal dans votre gestionnaire de base de données GUI).

dan04
la source
1
Dans les versions antérieures à SQL Server 2012, ils utilisaient le codage UCS-2, strictement 2 octets. Dans les versions plus récentes, ils utilisent UTF-16, qui correspond à 4 octets de longueur par caractère (similaire à UTF-8 mais commençant à 2 octets).
j123b567