Quelle est la difference entre varchar et nvarchar?

1355

Est-ce juste que cela nvarcharprend en charge les caractères multi-octets? Si c'est le cas, y a-t-il vraiment un intérêt, autre que des problèmes de stockage, à utiliser varchars?

stimms
la source
6
J'aime le point incomudro, c'est ce qui m'a amené à creuser autour de la différence entre varchar et nvarchar en premier lieu. Notre application Java contre une base de données SQL Server utilise myBatis, qui semble envoyer des chaînes en tant que nvarchar par défaut (toujours pas sûr de savoir comment (ou si) cela est remplaçable). Une requête simple apparaissait comme un énorme problème de performances car j'avais défini la colonne sur laquelle elle sélectionnait en tant que varchar, pas nvarchar, et ignorait l'index de la colonne.
Sean Read

Réponses:

1653

Une nvarcharcolonne peut stocker toutes les données Unicode. Une varcharcolonne est limitée à une page de codes 8 bits. Certaines personnes pensent que cela varchardevrait être utilisé car il prend moins de place. Je pense que ce n'est pas la bonne réponse. Les incompatibilités de page de code sont une douleur et Unicode est le remède aux problèmes de page de code. Avec un disque et une mémoire bon marché de nos jours, il n'y a vraiment plus de raison de perdre du temps à fouiller avec les pages de codes.

Tous les systèmes d'exploitation et plates-formes de développement modernes utilisent Unicode en interne. En utilisant nvarcharplutôt que varchar, vous pouvez éviter de faire des conversions d'encodage chaque fois que vous lisez ou écrivez dans la base de données. Les conversions prennent du temps et sont sujettes à des erreurs. Et la récupération des erreurs de conversion est un problème non trivial.

Si vous vous connectez avec une application qui utilise uniquement ASCII, je recommanderais toujours d'utiliser Unicode dans la base de données. Les algorithmes de classement du système d'exploitation et de la base de données fonctionneront mieux avec Unicode. Unicode évite les problèmes de conversion lors de l'interfaçage avec d' autres systèmes. Et vous vous préparez pour l'avenir. Et vous pouvez toujours valider que vos données sont limitées à ASCII 7 bits pour tout système hérité que vous devez maintenir, même en profitant de certains des avantages du stockage Unicode complet.

Jeffrey L Whitledge
la source
8
C'est une bonne information à avoir. Alors, est-ce que je comprends bien si je déduis que le choix devient finalement l'une des - quelle ressource est moins chère: processeur + frais généraux de développement ou stockage?
Matt Cashatt
141
@MatthewPatrickCashatt - Vous pouvez le voir de cette façon. Mais si vous imaginez un monde glorieux dans lequel toutes les données de texte sont en Unicode, et les développeurs n'ont tout simplement jamais à penser à quel encodage quelque chose se trouve, et une classe entière d'erreurs ne se produit tout simplement jamais, alors vous pouvez voir qu'il y a vraiment pas le choix du tout.
Jeffrey L Whitledge
8
@Martin Smith - Dans ces cas, le petit avantage que confère varchar (stockage compact) disparaît. Je suppose que varchar est encore pire que ce que je pensais!
Jeffrey L Whitledge
9
@PeterAllenWebb - Vous pouvez "stocker" toutes les données Unicode, car les paires de substitution en UTF-16 peuvent être stockées dans UCS-2 comme s'il s'agissait de caractères. Cela fonctionnera de manière transparente pour le stockage et la récupération des données. Maintenant, ce que vous ne pouvez pas faire, c'est obtenir des transformations de cas et des comparaisons fiables en dehors du BMP, mais je n'ai fait aucune réclamation à ce sujet. Donc, si vous avez beaucoup de texte Desseret sur lequel vous souhaitez effectuer un traitement, il serait préférable de le faire en dehors de la base de données. Mais c'est très bien pour le stocker là-bas. (Bien sûr, varchar ne vous y aidera pas non plus!)
Jeffrey L Whitledge
260

varchar : données de caractères non Unicode de longueur variable. Le classement de la base de données détermine la page de codes à partir de laquelle les données sont stockées.

nvarchar : données de caractères Unicode de longueur variable. Dépend du classement de la base de données pour les comparaisons.

Armé de ces connaissances, utilisez celui qui correspond à vos données d'entrée (ASCII v. Unicode).

user7116
la source
5
Existe-t-il une restriction comme varchar ne peut pas stocker de données Unicode? C'est tous les 1 et les 0. Je peux enregistrer le contenu chinois sous forme de varchar très bien dans ma base de données. Je précise juste son UTF-8 cependant. Comment ça marche alors ?
Nishant
3
@Nishant réponse tardive : bien sûr, vous pouvez stocker UTF-8 dans varchar mais cela cassera les fonctions de chaîne de SQL Server. Si vous effectuez toutes les recherches / transformations dans votre application, alors oui, vous pouvez le faire (mais quel est l'avantage?). Seul le codage Unicode pris en charge par SS est UCS-2 (oui, pas UTF-16 avant SS2k16) et ses fonctions de chaîne fonctionnent uniquement avec ce codage. BTW qu'en est-il des indices? Si vous souhaitez stocker des données arbitraires, vous feriez mieux d'utiliser le binaire à la place.
Adriano Repetti
Oui, cela brise simplement les fonctions de recherche de chaînes.
Nishant
8
Donc, vous savez ... ça ne "marche" pas. C'est comme stocker un floatdans intet aller, "bien sûr que les décimales disparaissent." Mais ne le fais pas.
user7116
70

J'utilise toujours nvarchar car il permet à tout ce que je construis de résister à peu près à toutes les données que je lui jette. Mon système CMS utilise le chinois par accident, car j'ai utilisé nvarchar. De nos jours, toute nouvelle application ne devrait pas vraiment se préoccuper de la quantité d'espace requise.

tags2k
la source
25
L'idée que les nouvelles applications ne devraient pas se préoccuper des restrictions d'espace est quelque peu myope, et toute personne ayant traité avec des bases de données au niveau de l'entreprise moyenne à grande sera heureuse de vous le dire, complètement incorrect.
Frater
60
Pour prendre la liberté de mettre des mots dans la bouche de tags2k, je pense qu'une déclaration plus précise pourrait être `` il est de plus en plus improbable que de nouvelles applications soient plus préoccupées par l'espace requis que par l'internationalisation et d'autres problèmes de jeu de caractères ''.
Cowan
1
"De nos jours, toute nouvelle application ne devrait pas vraiment se soucier de la quantité d'espace requise." - Sauf si vous utilisez un stockage cloud gratuit, où le plan payant est un bond CONSIDÉRABLE en $ (voir les plans partagés AppHarbor SQL Server).
janders
3
@ganders Howl! Tu es là. Les déclarations généralisées ne sont au mieux que temporairement correctes. L'informatique est définitivement un jeu de balançoire et de rond-point. Je suis vraiment préoccupé par la quantité d'espace que j'utilise sur Windows Azure CCP. Cela dit, je n'utiliserais "jamais" varchar sur nvarchar. Ooo je viens de me contredire?
rism
1
@rism, je pense que vous avez éliminé tout risque de contradiction avec votre utilisation de devis sur "never", au moins techniquement.
Smandoli
30

Cela dépend de la façon dont Oracle a été installé. Au cours du processus d'installation, l'option NLS_CHARACTERSET est définie. Vous pourrez peut-être le trouver avec la requête SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Si votre NLS_CHARACTERSET est un encodage Unicode comme UTF8, tant mieux. L'utilisation de VARCHAR et NVARCHAR est à peu près identique. Arrêtez de lire maintenant, allez-y. Sinon, ou si vous n'avez aucun contrôle sur le jeu de caractères Oracle, lisez la suite.

VARCHAR - Les données sont stockées dans le codage NLS_CHARACTERSET. S'il y a d'autres instances de base de données sur le même serveur, vous pouvez être limité par elles; et vice versa, puisque vous devez partager le paramètre. Un tel champ peut stocker toutes les données qui peuvent être encodées à l'aide de ce jeu de caractères, et rien d'autre . Par exemple, si le jeu de caractères est MS-1252, vous ne pouvez stocker que des caractères comme des lettres anglaises, une poignée de lettres accentuées et quelques autres (comme € et -). Votre application ne serait utile qu'à quelques endroits, ne pouvant fonctionner nulle part ailleurs dans le monde. Pour cette raison, il est considéré comme une mauvaise idée.

NVARCHAR - Les données sont stockées dans un codage Unicode. Chaque langue est prise en charge. Une bonne idée.

Et l'espace de stockage? VARCHAR est généralement efficace, car le jeu de caractères / encodage a été conçu sur mesure pour un environnement local spécifique. Les champs NVARCHAR stockent au format UTF-8 ou UTF-16, en se basant assez ironiquement sur le paramètre NLS. UTF-8 est très efficace pour les langues "occidentales", tout en prenant en charge les langues asiatiques. UTF-16 est très efficace pour les langues asiatiques, tout en prenant en charge les langues "occidentales". Si vous êtes préoccupé par l'espace de stockage, choisissez un paramètre NLS pour amener Oracle à utiliser UTF-8 ou UTF-16 selon le cas.

Qu'en est-il de la vitesse de traitement? La plupart des nouvelles plates-formes de codage utilisent Unicode en mode natif (Java, .NET, même C ++ std :: wstring d'il y a des années!), Donc si le champ de la base de données est VARCHAR, il force Oracle à convertir entre les jeux de caractères à chaque lecture ou écriture, ce n'est pas si bon. L'utilisation de NVARCHAR évite la conversion.

Conclusion: utilisez NVARCHAR! Il évite les limitations et les dépendances, convient parfaitement à l'espace de stockage et est généralement préférable pour les performances également.

Jeremy Frank
la source
42
C'est une très bonne réponse, sauf que la question concerne sql-server.
stim
21

nvarchar stocke les données en Unicode, donc, si vous allez stocker des données multilingues (plus d'une langue) dans une colonne de données, vous avez besoin de la variante N.

albertein
la source
16

Mes deux centimes

  1. Les index peuvent échouer lorsque vous n'utilisez pas les types de données corrects:
    Dans SQL Server: lorsque vous avez un index sur une colonne VARCHAR et lui présentez une chaîne Unicode, SQL Server n'utilise pas l'index. La même chose se produit lorsque vous présentez un BigInt à une colonne indexée contenant SmallInt. Même si le BigInt est suffisamment petit pour être un SmallInt, SQL Server n'est pas en mesure d'utiliser l'index. Dans l'autre sens, vous n'avez pas ce problème (lorsque vous fournissez SmallInt ou Ansi-Code à une colonne BigInt ou NVARCHAR indexée).

  2. Les types de données peuvent varier entre différents SGBD (DataBase Management System):
    sachez que chaque base de données a des types de données légèrement différents et VARCHAR ne signifie pas la même chose partout. Alors que SQL Server a VARCHAR et NVARCHAR, une base de données Apache / Derby n'a que VARCHAR et là VARCHAR est en Unicode.

incomudro
la source
Mais sûrement, si vous écrivez votre code correctement (c'est-à-dire en utilisant des requêtes paramétrées, etc.), le point 1 présente moins de risque.
Paul
14

Principalement, nvarchar stocke les caractères Unicode et varchar stocke les caractères non Unicode.

"Unicodes" signifie un schéma de codage de caractères 16 bits permettant aux caractères de nombreuses autres langues comme l'arabe, l'hébreu, le chinois, le japonais, d'être codés dans un seul jeu de caractères.

Cela signifie que les unicodes utilisent 2 octets par caractère pour stocker et les non-unicodes n'utilisent qu'un seul octet par caractère pour stocker. Ce qui signifie que les unicodes ont besoin d'une double capacité de stockage par rapport aux non-unicodes.

ranjit pawar
la source
10

Tu as raison. nvarcharstocke les données Unicode tout en varcharstockant les données de caractère à un octet. Autres que les différences de stockage ( nvarcharnécessite l'espace de stockage deux fois plus varchar), que vous avez déjà mentionné, la principale raison de préférer nvarcharplus varcharserait l' internationalisation ( à savoir le stockage des chaînes dans d' autres langues).

Mike Spross
la source
10

Je dirais que ça dépend.

Si vous développez une application de bureau, où le système d'exploitation fonctionne en Unicode (comme tous les systèmes Windows actuels) et le langage prend en charge nativement Unicode (les chaînes par défaut sont Unicode, comme en Java ou C #), alors allez nvarchar.

Si vous développez une application Web, où les chaînes entrent en UTF-8 et le langage est PHP, qui ne prend toujours pas en charge Unicode en natif (dans les versions 5.x), alors varchar sera probablement un meilleur choix.

sleepy012
la source
9

Bien que NVARCHARstocke Unicode, vous devriez considérer à l'aide de la collation que vous pouvez également utiliser VARCHARet enregistrer vos données dans vos langues locales.

Imaginez simplement le scénario suivant.

Le classement de votre base de données est persan et vous enregistrez une valeur comme 'علی' (écriture persane d'Ali) dans le VARCHAR(10)type de données. Il n'y a aucun problème et le SGBD n'utilise que trois octets pour le stocker.

Cependant, si vous souhaitez transférer vos données vers une autre base de données et voir le résultat correct, votre base de données de destination doit avoir le même classement que la cible qui est persane dans cet exemple.

Si votre classement cible est différent, vous voyez des points d'interrogation (?) Dans la base de données cible.

Enfin, rappelez-vous que si vous utilisez une énorme base de données destinée à l'utilisation de votre langue locale, je recommanderais d'utiliser l'emplacement au lieu d'utiliser trop d'espaces.

Je pense que le design peut être différent. Cela dépend de l'environnement sur lequel vous travaillez.

Ali Elmi
la source
8

J'ai jeté un coup d'œil aux réponses et beaucoup semblent recommander d'utiliser nvarcharplus varchar, car l'espace n'est plus un problème, donc il n'y a aucun mal à activer Unicode pour peu de stockage supplémentaire. Eh bien, ce n'est pas toujours vrai lorsque vous souhaitez appliquer un index sur votre colonne. SQL Server a une limite de 900 octets sur la taille du champ que vous pouvez indexer. Donc, si vous en avez un, varchar(900)vous pouvez toujours l'indexer, mais pas varchar(901). Avec nvarchar, le nombre de caractères est divisé par deux, vous pouvez donc indexer jusqu'à nvarchar(450). Donc, si vous êtes sûr que vous n'en avez pas besoin nvarchar, je ne recommande pas de l'utiliser.

En général, dans les bases de données, je recommande de s'en tenir à la taille dont vous avez besoin, car vous pouvez toujours vous développer. Par exemple, un collègue de travail pensait autrefois qu'il n'y avait aucun mal à utiliser nvarchar(max)une colonne, car nous n'avons aucun problème avec le stockage. Plus tard, lorsque nous avons essayé d'appliquer un index sur cette colonne, SQL Server l'a rejeté. Si, cependant, il a commencé avec even varchar(5), nous aurions pu simplement l'étendre plus tard à ce dont nous avons besoin sans un tel problème qui nous obligera à faire un plan de migration sur le terrain pour résoudre ce problème.

Rafid
la source
7

nVarchar vous aidera à stocker des caractères Unicode. C'est la voie à suivre si vous souhaitez stocker des données localisées.

Vijesh VP
la source
7

Si un seul octet est utilisé pour stocker un caractère, il existe 256 combinaisons possibles et vous pouvez ainsi enregistrer 256 caractères différents. Le classement est le modèle qui définit les caractères et les règles selon lesquels ils sont comparés et triés.

1252, qui est le Latin1 (ANSI), est le plus courant. Les jeux de caractères à un octet sont également inadéquats pour stocker tous les caractères utilisés par de nombreuses langues. Par exemple, certaines langues asiatiques ont des milliers de caractères, elles doivent donc utiliser deux octets par caractère.

Norme Unicode

Lorsque des systèmes utilisant plusieurs pages de codes sont utilisés dans un réseau, il devient difficile de gérer la communication. Pour normaliser les choses, le consortium ISO et Unicode a introduit l' Unicode . Unicode utilise deux octets pour stocker chaque caractère. Cela signifie que 65 536 caractères différents peuvent être définis, donc presque tous les caractères peuvent être couverts avec Unicode. Si deux ordinateurs utilisent Unicode, chaque symbole sera représenté de la même manière et aucune conversion n'est nécessaire - c'est l'idée derrière Unicode.

SQL Server a deux catégories de types de données de caractères:

  • non Unicode (char, varchar et text)
  • Unicode (nchar, nvarchar et ntext)

Si nous devons enregistrer des données de caractères de plusieurs pays, utilisez toujours Unicode.

Jithin Shaji
la source
6

Je dois dire ici (je me rends compte que je vais probablement m'ouvrir à une liste!), Mais sûrement le seul moment où NVARCHARest réellement plus utile (remarquez-en plus !) Que VARCHARlorsque toutes les collations sur tous des systèmes dépendants et dans la base de données elle-même sont les mêmes ...? Si ce n'est pas le cas, la conversion de classement doit de toute façon se produire et est donc VARCHARaussi viable que NVARCHAR.

Pour ajouter à cela, certains systèmes de base de données, tels que SQL Server (avant 2012) ont une taille de page d'env. 8K. Donc, si vous cherchez à stocker des données consultables qui ne sont pas contenues dans quelque chose comme un champ TEXTou NTEXT, alors VARCHARfournit la valeur complète de 8k d'espace alors que NVARCHARseulement 4k (double les octets, double l'espace).

Je suppose, pour résumer, que l’utilisation de l’une ou de l’autre dépend:

  • Projet ou contexte
  • Infrastructure
  • Système de base de données
Paul
la source
6

Suivez la différence entre le serveur SQL Server VARCHAR et le type de données NVARCHAR . Ici, vous pouvez voir d'une manière très descriptive.

En général, nvarchar stocke les données en Unicode, donc, si vous allez stocker des données multilingues (plus d'une langue) dans une colonne de données, vous avez besoin de la variante N.

Pradeep Kesharwani
la source
Il s'agit d'un lien très utile, mais votre réponse ne représente pas beaucoup plus que cela: un lien.
RubberDuck
ckuhn203, je ne vais pas vous dire de voir celui-ci
Pradeep Kesharwani
6

La principale différence entre Varchar(n)et nvarchar(n)est: entrez la description de l'image ici

VarcharLa taille (données de caractères non Unicode de longueur variable) est jusqu'à 8000. 1.Il s'agit d'un type de données de longueur variable

  1. Utilisé pour stocker des caractères non Unicode

  2. Occupe 1 octet d'espace pour chaque caractère

entrez la description de l'image ici

Nvarchar: Données de caractères Unicode de longueur variable.

1.Il s'agit d'un type de données de longueur variable

2. Utilisé pour stocker des caractères Unicode.

  1. Les données sont stockées dans un codage Unicode. Chaque langue est prise en charge. (par exemple les langues arabe, allemand, hindi, etc., etc.)
Debendra Dash
la source
6

Jeffrey L Whitledge avec ~ 47000 points de réputation recommande l'utilisation de nvarchar

Solomon Rutzky avec un score de réputation d'environ 33200 recommande: N'utilisez PAS toujours NVARCHAR. C'est une attitude / approche très dangereuse et souvent coûteuse.

Quelles sont les principales différences de performances entre les types de données varchar et nvarchar SQL Server?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

Les deux personnes d'une telle réputation, que choisit un développeur de base de données de serveur SQL d'apprentissage?

Il existe de nombreux avertissements dans les réponses et les commentaires sur les problèmes de performances si vous n'êtes pas cohérent dans vos choix.

Il y a des commentaires pro / con nvarchar pour les performances.

Il y a des commentaires pro / con varchar pour les performances.

J'ai une exigence particulière pour une table avec plusieurs centaines de colonnes, ce qui en soi est probablement inhabituel?

Je choisis varchar pour éviter d'aller près de la limite de taille d'enregistrement de table de 8060 octets de SQL * server 2012.

L'utilisation de nvarchar, pour moi, dépasse cette limite de 8060 octets.

Je pense également que je devrais faire correspondre les types de données des tables de code associées aux types de données de la table centrale principale.

J'ai vu l'utilisation de la colonne varchar sur ce lieu de travail, gouvernement de l'Australie-Méridionale, par des développeurs de bases de données expérimentés précédents, où le nombre de lignes de table va être de plusieurs millions ou plus (et très peu de colonnes nvarchar, le cas échéant, dans ces très grandes tables), donc peut-être que les volumes de lignes de données attendus font partie de cette décision.

Allan F
la source
1

nvarcharest sûr à utiliser par rapport à varcharafin de rendre notre code sans erreur (incompatibilité de type) car il nvarcharautorise également les caractères unicode. Lorsque nous utilisons une wherecondition dans une requête SQL Server et si nous utilisons l' =opérateur, cela générera parfois des erreurs. La raison probable en est que notre colonne de mappage sera définie varchar. Si nous l'avons défini dans nvarcharce problème, cela ne se produira pas. Nous nous en tenons toujours à varcharet pour éviter ce problème, il vaut mieux utiliser LIKEdes mots clés plutôt que =.

Rinoy Ashokan
la source