web-dev-qa-db-fra.com

Pourquoi devons-nous mettre N avant les chaînes dans Microsoft SQL Server?

J'apprends T-SQL. À partir des exemples que j'ai vus, pour insérer du texte dans une cellule varchar(), je peux écrire juste la chaîne à insérer, mais pour les cellules nvarchar(), chaque exemple préfixe les chaînes avec la lettre N.

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

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

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

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

34
qinking126

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.

27
Pieter B

Par défaut, le serveur SQL 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 il ne contient pas de caractères pour les langues non latines (polonais, russe, etc.). Comme indiqué par @Pieter B, nvarchar est utilisé pour contourner ce problème car il s'agit de nicode 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 serez d'accord pour laisser le N éteint, mais je ne le recommanderais pas. Il vaut mieux être en sécurité que désolé.

23
bwalk2895

Parce que MS SQL Server a un support médiocre pour 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" (char en C++, CHAR ou VARCHAR en SQL) sont encodées dans une ancienne "page de code". Le problème avec les pages de codes est qu'elles ont un nombre limité de caractères (la plupart sont des codages à un octet, ce qui limite le reportoire à 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 à la fois des données russes et hébreux car le russe utilise la page de codes 1251 et l'hébreu utilise la page de codes 1255 .

nicode résout ce problème en utilisant un seul jeu de caractères codés géant avec de la place pour 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 TF-16 , pour raisons historiques . Parce que UTF-16 représente les chaînes comme une séquence d'unités de code 16 bits au lieu du traditionnel 8 bits, un type de caractère distinct est nécessaire. Dans MSVC++, c'est wchar_t. Et dans MS SQL, c'est NCHAR ou NVARCHAR. Le N signifie "national" , ce qui me semble à l'envers car Unicode concerne inter - nationalisation , mais c'est la terminologie ISO.

D'autres implémentations SQL vous permettent de stocker TF-8 texte dans une colonne VARCHAR. UTF-8 est un encodage de longueur variable (1-4 octets par caractère) optimisé pour le cas où vos données sont principalement dans la plage Latin de base (qui sont représentés comme le même 1 octet par caractère que ASCII), mais peuvent représenter n'importe quel caractère Unicode. Ainsi, vous éviteriez le problème "deux fois plus d'espace" mentionné par bwalk2895.

Malheureusement, MS SQL Server ne prend pas en charge UTF-8 VARCHAR , vous devez donc plutôt utiliser UTF-16 à la place (et gaspiller de l'espace pour ASCII = texte), utilisez une page de codes non Unicode (et perdez la possibilité de représenter des caractères étrangers) ou stockez UTF-8 dans une colonne BINARY (et faites face aux inconvénients comme SQL fonctions de chaîne ne fonctionne pas correctement, ou doit afficher les données sous forme de vidage hexadécimal dans votre gestionnaire de GUI DB).

18
dan04