¿Cuál es la diferencia entre varchar y nvarchar?

1355

¿Es solo que nvarcharadmite caracteres multibyte? Si ese es el caso, ¿hay realmente algún punto, aparte de las preocupaciones de almacenamiento, para usar varchars?

estimula
fuente
66
Me gusta el punto de incomudro, es lo que me llevó a investigar sobre la diferencia entre varchar y nvarchar en primer lugar. Nuestra aplicación Java contra una base de datos SQL Server utiliza myBatis, que parece enviar cadenas como nvarchar por defecto (todavía no estoy seguro de cómo (o si) eso se puede anular). Una consulta simple aparecía como un gran problema de rendimiento porque había definido la columna que estaba seleccionando como varchar, no nvarchar, e ignoraba el índice en la columna.
Sean leyó

Respuestas:

1653

Una nvarcharcolumna puede almacenar cualquier dato Unicode. Una varcharcolumna está restringida a una página de códigos de 8 bits. Algunas personas piensan que varchardebería usarse porque ocupa menos espacio. Creo que esta no es la respuesta correcta. Las incompatibilidades de la página de códigos son un problema, y ​​Unicode es la cura para los problemas de la página de códigos. Con un disco y una memoria baratos hoy en día, ya no hay razón para perder el tiempo revisando páginas de códigos.

Todos los sistemas operativos y plataformas de desarrollo modernos utilizan Unicode internamente. Al usar en nvarcharlugar de varchar, puede evitar hacer conversiones de codificación cada vez que lee o escribe en la base de datos. Las conversiones toman tiempo y son propensas a errores. Y la recuperación de los errores de conversión es un problema no trivial.

Si está interactuando con una aplicación que usa solo ASCII, todavía recomendaría usar Unicode en la base de datos. El sistema operativo y los algoritmos de recopilación de bases de datos funcionarán mejor con Unicode. Unicode evita problemas de conversión al interactuar con otros sistemas. Y te estarás preparando para el futuro. Y siempre puede validar que sus datos están restringidos a ASCII de 7 bits para cualquier sistema heredado que tenga que mantener, incluso mientras disfruta de algunos de los beneficios del almacenamiento Unicode completo.

Jeffrey L Whitledge
fuente
8
Esta información será muy util. Entonces, ¿estoy entendiendo esto correctamente si deduzco que la elección finalmente se convierte en una de qué recurso es más barato: procesador + gastos generales de desarrollo o almacenamiento?
Matt Cashatt
141
@MatthewPatrickCashatt: puedes verlo de esa manera. Pero si imagina un mundo glorioso en el que todos los datos de texto están en Unicode, y los desarrolladores simplemente no tienen que pensar en qué codificación hay algo, y toda una clase de errores simplemente nunca ocurren, entonces puede ver que hay Realmente no hay otra opción.
Jeffrey L Whitledge
8
@ Martin Smith: en esos casos, la pequeña ventaja que confiere varchar (almacenamiento compacto) se desvanece. ¡Supongo que varchar es incluso peor de lo que pensaba!
Jeffrey L Whitledge
99
@PeterAllenWebb: puede "almacenar" cualquier dato Unicode, porque los pares sustitutos en UTF-16 pueden almacenarse en UCS-2 como si fueran caracteres. Eso funcionará de forma transparente para el almacenamiento y recuperación de datos. Ahora, lo que no puede hacer es obtener transformaciones de casos confiables y comparaciones fuera del BMP, pero no hice ninguna afirmación al respecto. Entonces, si tiene una gran cantidad de texto de Desseret en el que desea realizar el procesamiento, sería mejor hacerlo fuera de la base de datos. Pero está bien para almacenarlo allí. (¡Por supuesto, varchar tampoco te ayudará allí!)
Jeffrey L Whitledge
260

varchar : datos de caracteres de longitud variable, no Unicode. La clasificación de la base de datos determina qué página de códigos se utilizan los datos.

nvarchar : datos de caracteres Unicode de longitud variable. Depende de la recopilación de la base de datos para las comparaciones.

Armado con este conocimiento, use el que coincida con sus datos de entrada (ASCII v. Unicode).

usuario7116
fuente
55
¿Hay alguna restricción como varchar no puede almacenar datos Unicode? Es todo de 1 y 0. Puedo guardar contenido chino como varchar muy bien para mi DB. Sin embargo, solo especifico su UTF-8. ¿Cómo funciona eso entonces?
Nishant
3
@Nishant finales de respuesta : por supuesto que puede almacenar UTF-8 en varchar sino que va a romper las funciones de cadena de SQL Server. Si realiza todas las búsquedas / transformaciones dentro de su aplicación, entonces sí, puede hacerlo (pero ¿cuál es el beneficio?). Solo la codificación Unicode admitida por SS es UCS-2 (sí, no UTF-16 antes de SS2k16) y sus funciones de cadena solo funcionan con esa codificación. Por cierto, ¿qué pasa con los índices? Si desea almacenar datos arbitrarios, es mejor que use binarios.
Adriano Repetti
Sí, simplemente rompe las funciones de búsqueda de cadenas.
Nishant
8
Entonces, ya sabes ... no "funciona". Eso es como almacenar un floaten un inty decir, "bien seguro que los decimales desaparecen". Solo no lo hagas.
user7116
70

Siempre uso nvarchar, ya que permite que todo lo que estoy construyendo resista casi cualquier dato que le arroje. Mi sistema CMS hace chino por accidente, porque usé nvarchar. En estos días, las nuevas aplicaciones no deberían preocuparse realmente por la cantidad de espacio requerido.

etiquetas2k
fuente
25
La idea de que las nuevas aplicaciones no deberían preocuparse por las restricciones de espacio es algo miope, y cualquier persona que haya tratado con bases de datos a nivel de empresa mediana a grande estará encantado de decirte que es completamente incorrecta.
Frater
6060
Para tomar la libertad de poner palabras en la boca de tags2k, creo que una declaración más precisa podría ser 'es cada vez más improbable que las aplicaciones nuevas se preocupen más por el espacio requerido que por la internacionalización y otros problemas de carácter'.
Cowan
1
"En estos días, las aplicaciones nuevas no deberían preocuparse realmente por la cantidad de espacio requerido". - A menos que esté utilizando almacenamiento gratuito en la nube, donde el plan pagado es un salto CONSIDERABLE en $ (consulte los planes compartidos de AppHarbor SQL Server).
reúne el
3
@ganders Howl! Estás ahí. Las declaraciones generalizadas solo son temporalmente correctas en el mejor de los casos. La informática es definitivamente un juego de columpios y rotonda. Definitivamente me preocupa cuánto espacio estoy usando en Windows Azure CCP. Dicho esto, "nunca" usaría varchar sobre nvarchar. Ooo, ¿acabo de contradecirme?
rism
1
@rism, creo que eliminó cualquier riesgo de contradicción con el uso de citas "never", al menos técnicamente.
Smandoli
30

Depende de cómo se instaló Oracle. Durante el proceso de instalación, se establece la opción NLS_CHARACTERSET. Es posible que pueda encontrarlo con la consulta SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Si su NLS_CHARACTERSET es una codificación Unicode como UTF8, genial. Usar VARCHAR y NVARCHAR son bastante idénticos. Deja de leer ahora, solo adelante. De lo contrario, o si no tiene control sobre el conjunto de caracteres de Oracle, siga leyendo.

VARCHAR: los datos se almacenan en la codificación NLS_CHARACTERSET. Si hay otras instancias de la base de datos en el mismo servidor, puede estar restringido por ellas; y viceversa, ya que debes compartir la configuración. Tal campo puede almacenar cualquier información que pueda codificarse usando ese juego de caracteres, y nada más . Entonces, por ejemplo, si el conjunto de caracteres es MS-1252, solo puede almacenar caracteres como letras en inglés, un puñado de letras acentuadas y algunos otros (como € y -). Su aplicación sería útil solo para algunos entornos locales, ya que no puede operar en ningún otro lugar del mundo. Por esta razón, se considera una mala idea.

NVARCHAR: los datos se almacenan en una codificación Unicode. Todos los idiomas son compatibles. Una buena idea.

¿Qué pasa con el espacio de almacenamiento? VARCHAR es generalmente eficiente, ya que el conjunto de caracteres / codificación se diseñó a medida para un entorno local específico. Los campos NVARCHAR se almacenan en codificación UTF-8 o UTF-16, basándose en la configuración de NLS, irónicamente. UTF-8 es muy eficiente para los idiomas "occidentales", mientras que todavía admite idiomas asiáticos. UTF-16 es muy eficiente para los idiomas asiáticos, al tiempo que admite idiomas "occidentales". Si le preocupa el espacio de almacenamiento, elija una configuración de NLS para que Oracle use UTF-8 o UTF-16 según corresponda.

¿Qué pasa con la velocidad de procesamiento? La mayoría de las nuevas plataformas de codificación usan Unicode de forma nativa (Java, .NET, incluso C ++ std :: wstring de hace años!), Por lo que si el campo de la base de datos es VARCHAR, obliga a Oracle a convertir entre conjuntos de caracteres en cada lectura o escritura, no tan bueno. Usar NVARCHAR evita la conversión.

En pocas palabras: ¡use NVARCHAR! Evita limitaciones y dependencias, está bien para el espacio de almacenamiento y generalmente también es mejor para el rendimiento.

Jeremy Frank
fuente
42
Esta es una muy buena respuesta, excepto que la pregunta es sobre sql-server.
estimula
21

nvarchar almacena datos como Unicode, por lo tanto, si va a almacenar datos multilingües (más de un idioma) en una columna de datos, necesita la variante N.

alberteína
fuente
16

Mis dos centavos

  1. Los índices pueden fallar cuando no se usan los tipos de datos correctos:
    En SQL Server: cuando tiene un índice sobre una columna VARCHAR y le presenta una Cadena Unicode, SQL Server no hace uso del índice. Lo mismo sucede cuando presenta un BigInt a una columna indexada que contiene SmallInt. Incluso si BigInt es lo suficientemente pequeño como para ser SmallInt, SQL Server no puede usar el índice. Al revés, no tiene este problema (cuando proporciona SmallInt o Ansi-Code a una columna indexada BigInt ot NVARCHAR).

  2. Los tipos de datos pueden variar entre diferentes DBMS (DataBase Management System):
    sepa que cada base de datos tiene tipos de datos ligeramente diferentes y VARCHAR no significa lo mismo en todas partes. Si bien SQL Server tiene VARCHAR y NVARCHAR, una base de datos Apache / Derby solo tiene VARCHAR y VARCHAR está en Unicode.

incomudro
fuente
Pero seguramente si está escribiendo su código correctamente (es decir, utilizando consultas parametrizadas, etc.), entonces el punto 1 es menos riesgoso.
Paul
14

Principalmente nvarchar almacena caracteres Unicode y varchar almacena caracteres no Unicode.

"Unicodes" significa un esquema de codificación de caracteres de 16 bits que permite codificar caracteres de muchos otros idiomas como árabe, hebreo, chino y japonés en un solo conjunto de caracteres.

Eso significa que los Unicodes están usando 2 bytes por carácter para almacenar y los no Unicodes usan solo un byte por carácter para almacenar. Lo que significa que los Unicodes necesitan una capacidad doble para almacenar en comparación con los no Unicodes.

Ranjit Pawar
fuente
10

Tienes razón. nvarcharalmacena datos Unicode mientras varcharalmacena datos de caracteres de un solo byte. Aparte de las diferencias de almacenamiento ( nvarcharrequiere el doble de espacio de almacenamiento varchar), que ya se ha mencionado, la principal razón para preferir nvarcharmás varcharsería internacionalización (es decir, cadenas de almacenamiento en otros idiomas).

Mike Spross
fuente
10

Yo diría que depende.

Si desarrolla una aplicación de escritorio, donde el sistema operativo funciona en Unicode (como todos los sistemas Windows actuales) y el lenguaje es compatible de forma nativa con Unicode (las cadenas predeterminadas son Unicode, como en Java o C #), entonces vaya a nvarchar.

Si desarrolla una aplicación web, donde las cadenas aparecen como UTF-8, y el lenguaje es PHP, que aún no es compatible con Unicode de forma nativa (en las versiones 5.x), entonces varchar probablemente será una mejor opción.

soñoliento012
fuente
9

Aunque NVARCHARalmacena Unicode, debe considerar, con la ayuda de la recopilación, que también puede usar VARCHARy guardar sus datos de sus idiomas locales.

Solo imagine el siguiente escenario.

La clasificación de su base de datos es persa y guarda un valor como 'علی' (escritura persa de Ali) en el VARCHAR(10)tipo de datos. No hay problema y el DBMS solo usa tres bytes para almacenarlo.

Sin embargo, si desea transferir sus datos a otra base de datos y ver el resultado correcto, su base de datos de destino debe tener la misma clasificación que el objetivo que es persa en este ejemplo.

Si su clasificación de destino es diferente, verá algunos signos de interrogación (?) En la base de datos de destino.

Finalmente, recuerde que si está usando una gran base de datos que es para el uso de su idioma local, recomendaría usar la ubicación en lugar de usar demasiados espacios.

Creo que el diseño puede ser diferente. Depende del entorno en el que trabajes.

Ali Elmi
fuente
8

Eché un vistazo a las respuestas y muchos parecen recomendar usarlo nvarcharmás varchar, porque el espacio ya no es un problema, por lo que no hay ningún daño en habilitar Unicode para un poco de almacenamiento adicional. Bueno, esto no siempre es cierto cuando desea aplicar un índice sobre su columna. SQL Server tiene un límite de 900 bytes en el tamaño del campo que puede indexar. Entonces, si tiene un varchar(900), aún puede indexarlo, pero no varchar(901). Con nvarchar, el número de caracteres se reduce a la mitad, por lo que puede indexar hasta nvarchar(450). Entonces, si está seguro de que no necesita nvarchar, no le recomiendo usarlo.

En general, en las bases de datos, recomiendo ajustarse al tamaño que necesita, porque siempre puede expandirse. Por ejemplo, un colega en el trabajo alguna vez pensó que no hay daño en el uso nvarchar(max)de una columna, ya que no tenemos ningún problema con el almacenamiento. Más adelante, cuando intentamos aplicar un índice sobre esta columna, SQL Server lo rechazó. Sin embargo, si comenzó con incluso varchar(5), podríamos simplemente haberlo ampliado más tarde a lo que necesitamos sin un problema que nos obligue a hacer un plan de migración de campo para solucionar este problema.

Rafid
fuente
7

nVarchar te ayudará a almacenar caracteres Unicode. Es el camino a seguir si desea almacenar datos localizados.

Vicepresidente de Vijesh
fuente
7

Si se usa un solo byte para almacenar un carácter, hay 256 combinaciones posibles y, por lo tanto, puede guardar 256 caracteres diferentes. La clasificación es el patrón que define los caracteres y las reglas mediante las cuales se comparan y ordenan.

1252, que es el Latin1 (ANSI), es el más común. Los juegos de caracteres de un solo byte también son inadecuados para almacenar todos los caracteres utilizados por muchos idiomas. Por ejemplo, algunos idiomas asiáticos tienen miles de caracteres, por lo que deben usar dos bytes por carácter.

Estándar Unicode

Cuando los sistemas que usan múltiples páginas de códigos se usan en una red, se hace difícil administrar la comunicación. Para estandarizar las cosas, el consorcio ISO y Unicode introdujo el Unicode . Unicode usa dos bytes para almacenar cada carácter. Es decir, se pueden definir 65.536 caracteres diferentes, por lo que casi todos los caracteres se pueden cubrir con Unicode. Si dos computadoras usan Unicode, cada símbolo se representará de la misma manera y no se necesita conversión; esta es la idea detrás de Unicode.

SQL Server tiene dos categorías de tipos de datos de caracteres:

  • no Unicode (char, varchar y text)
  • Unicode (nchar, nvarchar y ntext)

Si necesitamos guardar datos de caracteres de varios países, use siempre Unicode.

Jithin Shaji
fuente
6

Tengo que decir aquí (¡me doy cuenta de que probablemente voy a abrirme a una paliza!), Pero seguramente la única vez en que NVARCHARes realmente más útil (¡noten más allí!) Que VARCHARcuando todas las colaciones en general de los sistemas dependientes y dentro de la base de datos son los mismos ...? Si no, entonces la conversión de colación tiene que suceder de todos modos, por lo que VARCHARes tan viable como NVARCHAR.

Para agregar a esto, algunos sistemas de bases de datos, como SQL Server (antes de 2012) tienen un tamaño de página de aprox. 8K. Entonces, si está buscando almacenar datos de búsqueda que no se encuentran en algo como un campo TEXTo NTEXT, entonces VARCHARproporciona el espacio completo de 8k mientras que NVARCHARsolo proporciona 4k (el doble de bytes, el doble de espacio).

Supongo que, para resumir, el uso de cualquiera depende de:

  • Proyecto o contexto
  • Infraestructura
  • Sistema de bases de datos
Pablo
fuente
6

Siga la diferencia entre el servidor SQL VARCHAR y el tipo de datos NVARCHAR . Aquí puedes ver de una manera muy descriptiva.

En general, nvarchar almacena datos como Unicode, por lo tanto, si va a almacenar datos multilingües (más de un idioma) en una columna de datos, necesita la variante N.

Pradeep Kesharwani
fuente
Este es un enlace muy útil, pero su respuesta no es mucho más que eso: un enlace.
RubberDuck
ckuhn203, no voy a decirte que veas esto
Pradeep Kesharwani
6

La principal diferencia entre Varchar(n)y nvarchar(n)es: ingrese la descripción de la imagen aquí

VarcharEl tamaño de los datos (longitud variable, caracteres no Unicode) es de hasta 8000. 1. Es un tipo de datos de longitud variable

  1. Se usa para almacenar caracteres no Unicode

  2. Ocupa 1 byte de espacio para cada personaje

ingrese la descripción de la imagen aquí

Nvarchar: Datos de caracteres Unicode de longitud variable.

1.Es un tipo de datos de longitud variable

2. Utilizado para almacenar caracteres Unicode.

  1. Los datos se almacenan en una codificación Unicode. Todos los idiomas son compatibles. (por ejemplo, los idiomas árabe, alemán, hindi, etc., etc.)
Debendra Dash
fuente
6

Jeffrey L Whitledge con ~ 47000 puntos de reputación recomienda el uso de nvarchar

Solomon Rutzky con un puntaje de reputación de ~ 33200 recomienda: NO use siempre NVARCHAR. Esa es una actitud / enfoque muy peligroso, y a menudo costoso.

¿Cuáles son las principales diferencias de rendimiento entre los tipos de datos varchar y nvarchar SQL Server?

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

Ambas personas de tan alta reputación, ¿qué elige un desarrollador de base de datos de servidor sql de aprendizaje?

Hay muchas advertencias en las respuestas y comentarios sobre problemas de rendimiento si no es consistente en las elecciones.

Hay comentarios pro / con nvarchar para el rendimiento.

Hay comentarios pro / con varchar para el rendimiento.

Tengo un requisito particular para una tabla con muchos cientos de columnas, lo que en sí mismo es probablemente inusual.

Elijo varchar para evitar acercarme al límite de tamaño de registro de la tabla de 8060 bytes del servidor SQL * 2012.

El uso de nvarchar, para mí, supera este límite de 8060 bytes.

También estoy pensando que debería hacer coincidir los tipos de datos de las tablas de códigos relacionadas con los tipos de datos de la tabla central primaria.

He visto el uso de la columna varchar en este lugar de trabajo, el gobierno de Australia del Sur, por desarrolladores de bases de datos con experiencia anterior, donde el recuento de filas de la tabla será de varios millones o más (y muy pocas columnas nvarchar, si las hay, en estos muy grandes tablas), por lo que quizás los volúmenes de fila de datos esperados se vuelvan parte de esta decisión.

Allan F
fuente
1

nvarchares seguro de usar en comparación con el varcharfin de hacer que nuestro código esté libre de errores (no coinciden los tipos) porque también nvarcharpermite caracteres unicode. Cuando usamos wherecondición en la consulta de SQL Server y si estamos usando el =operador, arrojará errores algunas veces. La razón probable de esto es que nuestra columna de mapeo será diferenciada varchar. Si lo definimos en nvarchareste problema, no sucederá. Aún así nos atenemos varchary evitamos este problema, mejor usamos LIKEpalabras clave en lugar de =.

Rinoy Ashokan
fuente