Quelle est la différence entre char, nchar, varchar et nvarchar dans SQL Server?

626

Qu'entend-on par nvarchar?

Quelle est la différence entre char, nchar, varcharet nvarchardans SQL Server?

MrDatabase
la source

Réponses:

859

Juste pour éclaircir ... ou résumer ...

  • ncharet nvarcharpeut stocker des caractères Unicode .
  • charet ne peut pas stocker de caractères Unicode .varchar
  • charet ncharsont de longueur fixe qui réservent de l'espace de stockage pour le nombre de caractères que vous spécifiez même si vous n'utilisez pas tout cet espace.
  • varcharet nvarcharsont de longueur variable qui n'utilisera que des espaces pour les personnages que vous stockez. Il ne réservera pas de stockage comme charounchar .

ncharet nvarcharoccupera deux fois plus d'espace de stockage, il peut donc être judicieux de les utiliser uniquement si vous avez besoin de la prise en charge Unicode .

Brian Kim
la source
15
char et varchar ne sont pas destinés à stocker unicode, mais avec quelques astuces de codage supplémentaires et une logique supplémentaire, vous pouvez toujours mal utiliser un champ [var] char pour le stockage unicode.
Wim ten Brink
10
Cela dépend du classement, que les n...versions occupent ou non deux fois plus d'espace de stockage que ma réponse le montre
Martin Smith
7
Quel est l'avantage de réserver du stockage?
mlissner
4
Sur le dernier point: l'utilisation de Unicode nchar et nvarchar sont toujours meilleurs dans la plupart des cas, un meilleur classement, une flexibilité pour les utilisateurs, supprime les futurs problèmes de compatibilité. Et d'ailleurs, l'espace de stockage n'est pas un problème dans ce cas, car l'utilisation du classement sans Unicode est très compliquée et les taux de mémoire continueront de diminuer à l'avenir
Jaison Varghese
6
@BenCaine char (20) utilisera 20 octets (en supposant un classement 8 bits); varchar (20) utilisera len (données) +2 octets, soit 22 pour 20 octets de données, mais seulement 12 pour 10 octets de données. Les deux octets supplémentaires sont les enregistrements de longueur. Si vos données auront toujours la longueur totale, utilisez un caractère, car cela économise de l'espace et peut être plus rapide. Veuillez ne jamais utiliser un varchar (1), ni même quelque chose de plus petit qu'un varchar (4). Un seul caractère au format varchar utilise trois octets, donc un char (3) n'utilisera jamais plus d'espace qu'un varchar (3).
Richard Gadsden
95

Jusqu'à présent, toutes les réponses indiquent qu'il varchars'agit d'un octet simple, d' nvarchar un octet double. La première partie de cela dépend en fait du classement comme illustré ci-dessous.

DECLARE @T TABLE
(
C1 VARCHAR(20) COLLATE Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS,
C2 NVARCHAR(20)COLLATE  Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS
)

INSERT INTO @T 
    VALUES (N'中华人民共和国',N'中华人民共和国'),
           (N'abc',N'abc');

SELECT C1,
       C2,
       LEN(C1)        AS [LEN(C1)],
       DATALENGTH(C1) AS [DATALENGTH(C1)],
       LEN(C2)        AS [LEN(C2)],
       DATALENGTH(C2) AS [DATALENGTH(C2)]
FROM   @T  

Retour

entrez la description de l'image ici

Notez que les caractères et n'étaient toujours pas représentés dans la VARCHARversion et ont été remplacés silencieusement par ?.

Il n'y a en fait toujours aucun caractère chinois qui puisse être représenté par un seul octet dans ce classement. Les seuls caractères à un octet sont l'ensemble ASCII occidental typique.

De ce fait, il est possible qu'un insert d'une nvarchar(X)colonne à une varchar(X)colonne échoue avec une erreur de troncature (où X désigne un nombre identique dans les deux cas).

SQL Server 2012 ajoute des classements SC (caractère supplémentaire) qui prennent en charge UTF-16. Dans ces classements, un seul nvarcharcaractère peut prendre 2 ou 4 octets.

Martin Smith
la source
4
Le genre de réponse que je cherchais. Aussi pour gagner du temps à mon goût - le texte non anglais se traduit par "République populaire de Chine" translate.google.com/#auto/en/…
Igand
34

nchar et char fonctionnent à peu près de la même manière l'un que l'autre, tout comme nvarchar et varchar. La seule différence entre eux est que nchar / nvarchar stocke les caractères Unicode (essentiel si vous avez besoin d'utiliser des jeux de caractères étendus) tandis que varchar ne le fait pas.

Étant donné que les caractères Unicode nécessitent plus de stockage, les champs nchar / nvarchar prennent deux fois plus d'espace (par exemple, dans les versions antérieures de SQL Server, la taille maximale d'un champ nvarchar est de 4000).

Cette question est un double de celle-ci .

Luke Bennett
la source
3
Vous oubliez une chose: nchar utilise une longueur fixe, donc nchar (10) doit toujours recevoir dix caractères. Et varchar (10) est en effet Unicode et acceptera n'importe quel nombre de caractères, jusqu'à 10 caractères. Voir également msdn.microsoft.com/en-us/library/ms186939.aspx
Wim ten Brink
33

Juste pour ajouter quelque chose de plus: nchar - ajoute des espaces de fin aux données. nvarchar - n'ajoute pas d'espaces de fin aux données.

Donc, si vous allez filtrer votre jeu de données par un champ 'nchar', vous pouvez utiliser RTRIM pour supprimer les espaces. Par exemple, le champ nchar (10) appelé BRAND stocke le mot NIKE. Il ajoute 6 espaces à droite du mot. Ainsi, lors du filtrage, l'expression doit se lire: RTRIM (Fields! BRAND.Value) = "NIKE"

J'espère que cela aide quelqu'un là-bas parce que je me débattais avec ça un peu tout à l'heure!

Dimuthu
la source
24

Ma tentative de résumer et de corriger les réponses existantes:

Tout d'abord, charet ncharutilisera toujours une quantité fixe d'espace de stockage, même lorsque la chaîne à stocker est plus petite que l'espace disponible, tandis que varcharet nvarcharutilisera uniquement autant d'espace de stockage que nécessaire pour stocker cette chaîne (plus deux octets de surcharge, probablement pour stocker la longueur de la chaîne). N'oubliez donc pas que "var" signifie "variable", comme dans l'espace variable.

Le deuxième point important à comprendre est que, ncharet nvarcharstockez les chaînes en utilisant exactement deux octets par caractère, tandis que charet varcharutilisez un codage déterminé par la page de code de classement, qui sera généralement exactement un octet par caractère (bien qu'il y ait des exceptions, voir ci-dessous). En utilisant deux octets par caractère, une très large gamme de caractères peut être stockée, donc la chose de base à retenir ici est cela ncharet a nvarchartendance à être un bien meilleur choix lorsque vous souhaitez une prise en charge de l'internationalisation, ce que vous faites probablement.

Maintenant pour quelques points plus fins.

Tout d' abord, ncharet des nvarcharcolonnes toujours stocker des données en utilisant UCS-2. Cela signifie qu'exactement deux octets par caractère seront utilisés, et tout caractère Unicode dans le plan multilingue de base (BMP) peut être stocké par un champ ncharou nvarchar. Cependant, il n'est pas possible que n'importe quel caractère Unicode puisse être stocké. Par exemple, selon Wikipedia, les points de code pour les hiéroglyphes égyptiens ne relèvent pas du BMP. Il existe donc des chaînes Unicode qui peuvent être représentées en UTF-8 et d'autres vrais encodages Unicode qui ne peuvent pas être stockés dans un serveur ncharou un nvarcharchamp SQL , et des chaînes écrites en hiéroglyphes égyptiens en feraient partie. Heureusement, vos utilisateurs n'écrivent probablement pas dans ce script, mais c'est quelque chose à garder à l'esprit!

Une autre source de confusion , mais le point intéressant que d' autres affiches ont mis en évidence que charet les varcharchamps peuvent utiliser deux octets par caractère pour certains caractères si la page de code de classement exige. (Martin Smith donne un excellent exemple dans lequel il montre comment Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS présente ce comportement. Vérifiez-le.)

MISE À JOUR: Depuis SQL Server 2012, il existe enfin des pages de codes pour UTF-16 , par exemple Latin1_General_100_CI_AS_SC, qui peuvent vraiment couvrir toute la plage Unicode.

PeterAllenWebb
la source
14
  • char: données de caractères de longueur fixe avec une longueur maximale de 8000 caractères.
  • nchar: données unicode de longueur fixe avec une longueur maximale de 4000 caractères.
  • Char = Longueur 8 bits
  • NChar = Longueur de 16 bits
ss.
la source
charne pouvait pas avoir une longueur de 8 bits. Il n'a pas besoin de stocker la longueur et la longueur fixe peut contenir jusqu'à 8 000 caractères.
John B. Lambe
12

nchar[(n)] (caractère national)

  • Données de chaîne Unicode de longueur fixe .
  • n définit la longueur de la chaîne et doit être une valeur comprise entre 1 et 4 000.
  • La taille de stockage est deux fois noctets.

nvarchar [(n | max)] (caractère national variable.)

  • Données de chaîne Unicode de longueur variable .
  • n définit la longueur de la chaîne et peut être une valeur comprise entre 1 et 4 000.
  • max indique que la taille de stockage maximale est de 2 ^ 31-1 octets (2 Go).
  • La taille de stockage, en octets, est deux fois la longueur réelle des données entrées + 2 octets

char [(n)] (personnage)

  • non-UnicodeDonnées de chaîne de longueur fixe .
  • n définit la longueur de la chaîne et doit être une valeur comprise entre 1 et 8 000.
  • La taille de stockage est en noctets.

varchar [(n | max)] (caractère variable)

  • Données de chaîne de longueur variable, non Unicode .
  • n définit la longueur de la chaîne et peut être une valeur comprise entre 1 et 8 000.
  • max indique que la taille de stockage maximale est de 2 ^ 31-1 octets (2 Go).
  • La taille de stockage est la longueur réelle des données entrées + 2 octets.
Rasel
la source
7

Les différences sont les suivantes:

  1. n [var] char stocke unicode tandis que [var] char ne stocke que des caractères codés sur un octet.
  2. [n] char requiert un nombre fixe de caractères de la longueur exacte tandis que [n] varchar accepte un nombre variable de caractères jusqu'à et y compris la longueur définie.

Une autre différence est la longueur. Nchar et nvarchar peuvent contenir jusqu'à 4 000 caractères. Et char et varchar peuvent contenir jusqu'à 8 000 caractères. Mais pour SQL Server, vous pouvez également utiliser un [n] varchar (max) qui peut gérer jusqu'à 2 147 483 648 caractères. (Deux gigaoctets, un entier signé de 4 octets.)

Wim ten Brink
la source
7

nchar nécessite plus d'espace que nvarchar.

par exemple,

Un nchar (100) stockera toujours 100 caractères même si vous n'en saisissez que 5, les 95 caractères restants seront remplis d'espaces. Stocker 5 caractères dans un nvarchar (100) économisera 5 caractères.

Venkataraman R
la source
6
Pas tout à fait vrai, car vous devez remplir un caractère (100) avec jusqu'à 100 caractères. Vous l'utiliseriez lorsque vous stockez, par exemple, des numéros de téléphone dans votre base de données ou des numéros de commande d'une longueur fixe. Étant donné que la longueur du champ est fixe, vous n'avez pas le choix de le remplir jusqu'au nombre maximal de caractères. Mais lorsque toutes vos données sont de 100 caractères par enregistrement, un char (100) prendra moins de stockage qu'un varchar (100) car il n'a pas besoin d'indication de longueur: chaque valeur serait exactement de 100 caractères.
Wim ten Brink
5

nchar (10) est une chaîne Unicode de longueur fixe de longueur 10. nvarchar (10) est une chaîne Unicode de longueur variable avec une longueur maximale de 10. En règle générale, vous utiliseriez la première si toutes les valeurs de données sont de 10 caractères et la seconde si les longueurs varient.

Jason Kresowaty
la source
Mauvaise comparaison - la question concerne nchar et varchar, pas nchar et nvarchar.
Luke Bennett
4
  • nchar est de longueur fixe et peut contenir des caractères unicode. il utilise deux octets de stockage par caractère.

  • varchar est de longueur variable et ne peut pas contenir de caractères unicode. il utilise un stockage d'octets par caractère.

Manu
la source
Faux. Unicode peut utiliser 1 à 4 octets (en général) pour chaque caractère. En outre, un varchar peut contenir unicode, mais il n'est pas reconnu comme unicode. Par conséquent, un varchar est considéré comme non fiable pour le stockage unicode. (Surtout qu'il y a un risque que le code qui accède au champ ne le traduise pas correctement.)
Wim ten Brink
@Alex: Je pense que vous avez fait valoir votre point de vue, mais je ne suis toujours pas d'accord avec vous. Ce que vous dites, c'est qu'un int PEUT tenir un long si le long se trouve être inférieur à 2 ^ 32. Ce n'est pas seulement «peu fiable», c'est une limitation inhérente qui rend impossible de couvrir toute la plage de valeurs.
Manu
4
@Workshop Alex: Faux. Unicode codé comme UCS-2(qui se trouve être le codage utilisé par SQL Server) stocke tous les caractères dans exactement deux octets, voir msdn.microsoft.com/en-us/library/bb330962%28v=sql.90%29.aspx : SQL Server stores Unicode in the UCS-2 encoding scheme... UCS-2 is a fixed-length encoding that represents all characters as a 16-bit value (2 bytes). SQL Server 2008 peut utiliser la compression SCSU, mais est toujours la compression des chaînes Unicode codées UCS-2: msdn.microsoft.com/en-us/library/ee240835.aspx
Remus Rusanu
2

NVARCHAR peut stocker des caractères Unicode et prend 2 octets par caractère.

Gustavo Rubio
la source
1
FAUX! Unicode utilise entre 1 et 4 octets par caractère! Beaucoup de gens l'oublient! Même l'utilisation de UTF-16 peut entraîner le fait que certains caractères prennent 4 octets au lieu de 2, bien que la longueur commune soit de 2 octets. Certains autres sous-formats d'Unicode peuvent prendre encore plus de 4 octets!
Wim ten Brink
7
@WimtenBrink - La question concerne SQL Server et nvarcharprend toujours 2 octets par caractère.
Martin Smith
@Wim, vous avez raison, il existe plusieurs encodages pour Unicode qui peuvent produire un nombre différent d'octets. Mais SQL Server ne vous donne pas le choix du codage Unicode. SQL Server avant 2012 n'utilisait que UCS-2, deux octets de large, donc Martin avait raison au moment où il a écrit la réponse. Comme d'autres réponses ci-dessus l'ont dit, SQL Server 2012 fournit maintenant UTF-16, donc deux octets pour de nombreux caractères (ceux du plan multiliingue de base Unicode), quatre octets pour les autres.
Concrete Gannet