Saltar al contenido

¿Cuándo debemos usar NVARCHAR / NCHAR en lugar de VARCHAR / CHAR en SQL Server?

Solución:

La verdadera razón por la que desea utilizar NVARCHAR es cuando tiene diferente idiomas en la misma columna, debe abordar las columnas en T-SQL sin decodificar, desea poder ver los datos “de forma nativa” en SSMS o desea estandarizar en Unicode.

Si trata la base de datos como un almacenamiento tonto, es perfectamente posible almacenar cadenas anchas y codificaciones diferentes (incluso de longitud variable) en VARCHAR (por ejemplo, UTF-8). El problema surge cuando intenta codificar y decodificar, especialmente si la página de códigos es diferente para diferentes filas. También significa que SQL Server no podrá manejar los datos fácilmente para realizar consultas dentro de T-SQL en columnas codificadas (potencialmente de forma variable).

Usar NVARCHAR evita todo esto.

Recomendaría NVARCHAR para cualquier columna que contenga datos ingresados ​​por el usuario y que esté relativamente libre de restricciones.

Recomendaría VARCHAR para cualquier columna que sea una clave natural (como la placa de un vehículo, SSN, número de serie, etiqueta de servicio, número de pedido, indicativo del aeropuerto, etc.) que normalmente está definida y limitada por una norma, legislación o convención. También VARCHAR para usuario ingresado y muy restringido (como un número de teléfono) o un código (ACTIVO / CERRADO, S / N, M / F, M / S / D / W, etc.). No hay absolutamente ninguna razón para usar NVARCHAR para esos.

Entonces, para una regla simple:

VARCHAR cuando se garantiza que estará restringido NVARCHAR de lo contrario

Debe usar NVARCHAR siempre que tenga que almacenar varios idiomas. Creo que debe usarlo para los idiomas asiáticos, pero no me cite.

Aquí está el problema si toma el ruso, por ejemplo, y lo almacena en un varchar, estará bien siempre que defina la página de códigos correcta. Pero digamos que está utilizando una instalación predeterminada de sql en inglés, entonces los caracteres rusos no se manejarán correctamente. Si estuviera utilizando NVARCHAR (), se manejarían correctamente.

Editar

Ok, déjeme citar MSDN y tal vez sea demasiado específico, pero no desea almacenar más de una página de códigos en una columna varcar, mientras que puede, no debería

Cuando maneja datos de texto que se almacenan en el tipo de datos char, varchar, varchar (max) o text, la limitación más importante a considerar es que el sistema solo puede validar la información de una sola página de códigos. (Puede almacenar datos de varias páginas de códigos, pero esto no se recomienda). La página de códigos exacta utilizada para validar y almacenar los datos depende de la clasificación de la columna. Si no se ha definido una intercalación a nivel de columna, se utiliza la intercalación de la base de datos. Para determinar la página de códigos que se usa para una columna determinada, puede usar la función COLLATIONPROPERTY, como se muestra en los siguientes ejemplos de código:

Aquí hay algo más:

Este ejemplo ilustra el hecho de que muchas configuraciones regionales, como georgiano e hindi, no tienen páginas de códigos, ya que son intercalaciones solo Unicode. Esas intercalaciones no son apropiadas para columnas que usan el tipo de datos char, varchar o text.

Por lo tanto, el georgiano o el hindi realmente deben almacenarse como nvarchar. El árabe también es un problema:

Otro problema que puede encontrar es la incapacidad de almacenar datos cuando no todos los caracteres que desea admitir están contenidos en la página de códigos. En muchos casos, Windows considera que una página de códigos en particular es la página de códigos “que mejor se ajusta”, lo que significa que no hay garantía de que pueda confiar en la página de códigos para manejar todo el texto; es simplemente el mejor disponible. Un ejemplo de esto es la escritura árabe: admite una amplia gama de idiomas, incluidos baluchi, bereber, farsi, cachemira, kazajo, kirguís, pashto, sindhi, uigur, urdu y más. Todos estos idiomas tienen caracteres adicionales además de los del idioma árabe según se define en la página de códigos 1256 de Windows. Si intenta almacenar estos caracteres adicionales en una columna que no sea Unicode que tenga la intercalación árabe, los caracteres se convertirán en signos de interrogación.

Algo a tener en cuenta cuando usa Unicode, aunque puede almacenar diferentes idiomas en una sola columna, solo puede ordenarlos usando una sola intercalación. Hay algunos idiomas que usan caracteres latinos pero no se clasifican como otros idiomas latinos. Los acentos son un buen ejemplo de esto, no recuerdo el ejemplo, pero había un idioma de Europa del Este cuya Y no se clasificaba como la Y en inglés. Luego está la ch en español que los usuarios españoles esperan que se clasifique después de h.

Considerándolo todo con todos los problemas con los que tiene que lidiar cuando se trata de internalización. En mi opinión, es más fácil usar caracteres Unicode desde el principio, evitar las conversiones adicionales y aprovechar el espacio. De ahí mi declaración anterior.

Las dos respuestas más votadas son incorrectas. No debería tener nada que ver con “almacenar diferentes / múltiples idiomas”. Puedes admitir caracteres españoles como ñ e inglés, con solo comunes varchar campo y Latin1_General_CI_AS COLLATION, p.ej

Version corta

Deberías usar NVARCHAR/NCHAR siempre que el ENCODING, que está determinada por COLLATION del campo, no admite los caracteres necesarios.
Además, según la versión de SQL Server, puede utilizar COLLATIONs, igual que Latin1_General_100_CI_AS_SC_UTF8 que está disponible desde SQL Server 2019. Establecer esta intercalación en un VARCHAR campo (o toda la tabla / base de datos), utilizará UTF-8 ENCODING para almacenar y manejar los datos en ese campo, lo que permite un soporte total UNICODE personajes, y por lo tanto, cualquier idioma adoptado por él.

PARA ENTENDER COMPLETAMENTE:
Para comprender completamente lo que voy a explicar, es obligatorio tener los conceptos de UNICODE, ENCODING y COLLATION todo extremadamente claro en tu cabeza. Si no es así, primero eche un vistazo a mi humilde y simplificada explicación sobre “Qué es UNICODE, ENCODING, COLLATION y UTF-8, y cómo se relacionan” sección y enlaces de documentación suministrados. Además, todo lo que digo aquí es específico para Microsoft SQL Servery cómo almacena y maneja los datos en char/nchar y varchar/nvarchar los campos.

Digamos que queremos almacenar un texto peculiar en nuestra base de datos del servidor MSSQL. Podría ser un comentario de Instagram como “¡Me encanta stackoverflow!”.
La parte en inglés simple sería perfectamente compatible incluso con ASCII, pero dado que también hay un emoji, que es un carácter especificado en el UNICODE estándar, necesitamos un ENCODING que admite este carácter Unicode.

MSSQL Server utiliza el COLLATION para determinar que ENCODING se usa en char/nchar/varchar/nvarchar los campos. Entonces, a diferencia de lo que muchos piensan, COLLATION no es sólo sobre ordenar y comparar datos, sino también sobre ENCODING, y por consecuencia: ¡Cómo se almacenarán nuestros datos!

Entonces, ¿CÓMO SABEMOS CUÁL ES LA CODIFICACIÓN QUE UTILIZA NUESTRA COLLACIÓN? Con este:

SELECT COLLATIONPROPERTY( 'Latin1_General_CI_AI' , 'CodePage' ) AS [CodePage]
--returns 1252

Este simple SQL devuelve el Windows Code Page para COLLATION. A Windows Code Page no es más que otro mapeo para ENCODINGs. Para el Latin1_General_CI_AI COLLATION devuelve el Windows Code Page código 1252 , que se asigna a Windows-1252 ENCODING.
Entonces, por un varchar columna, con Latin1_General_CI_AI COLLATION, este campo manejará sus datos usando el Windows-1252 ENCODING, y solo almacena correctamente los caracteres admitidos por esta codificación.

Si comprobamos el Windows-1252 ENCODING Especificación Lista de caracteres para Windows-1252, descubriremos que esta codificación no es compatible con nuestro carácter emoji. Y si todavía lo probamos:

Un texto que contiene caracteres UNICODE, que se almacena incorrectamente debido a nuestra intercalación y codificación en el campo varchar.

OK, ¿CÓMO PODEMOS RESOLVER ESTO? De hecho, depende, ¡y eso es BUENO!

NCHAR/NVARCHAR

Antes de SQL Server 2019, todo lo que teníamos era NCHAR y NVARCHAR los campos. Algunos dicen que son UNICODE los campos. ¡ESO ESTÁ MAL!. Nuevamente, depende de la COLLATION y también Versión SQLServer. La documentación “nchar y nvarchar (Transact-SQL)” de Microsoft especifica perfectamente:

A partir de SQL Server 2012 (11.x), cuando se usa una intercalación habilitada para caracteres suplementarios (SC), estos tipos de datos almacenan el rango completo de datos de caracteres Unicode y usan la codificación de caracteres UTF-16. Si se especifica una intercalación no SC, estos tipos de datos almacenan solo el subconjunto de datos de caracteres admitidos por la codificación de caracteres UCS-2.

En otras palabras, si usamos SQL Server anterior a 2012, como SQL Server 2008 R2 por ejemplo, el ENCODING para esos campos usará UCS-2 ENCODING que admiten un subconjunto de UNICODE. Pero si usamos SQL Server 2012 o más reciente, y definimos un COLLATION que tiene Supplementary Character habilitado, que con nuestro campo usaremos el UTF-16 ENCODING, que apoya plenamente UNICODE.

¡PERO, HAY MÁS! ¡PODEMOS USAR UTF-8 AHORA!

CHAR/VARCHAR

A partir de SQL Server 2019, NOSOTROS PODEMOS USAR CHAR/VARCHAR campos y aún ser totalmente compatible UNICODE utilizando UTF-8 ENCODING!!!

De la documentación “char and varchar (Transact-SQL)” de Microsoft:

A partir de SQL Server 2019 (15.x), cuando se usa una intercalación habilitada para UTF-8, estos tipos de datos almacenan el rango completo de datos de caracteres Unicode y usan la codificación de caracteres UTF-8. Si se especifica una intercalación que no es UTF-8, estos tipos de datos almacenan solo un subconjunto de caracteres admitidos por la página de códigos correspondiente de esa intercalación.

Nuevamente, en otras palabras, si usamos SQL Server anterior a 2019, como SQL Server 2008 R2, por ejemplo, debemos verificar el ENCODING utilizando el método explicado anteriormente. Pero si usamos SQL Server 2019 o más reciente, y definimos un COLLATION igual que Latin1_General_100_CI_AS_SC_UTF8, entonces nuestro campo usará UTF-8 ENCODING que es, con mucho, la codificación más utilizada y eficiente que admite todas las UNICODE caracteres.

Información adicional:

En cuanto a la observación del PO sobre “He visto que la mayoría de los idiomas europeos (alemán, italiano, inglés, …) están bien en la misma base de datos en columnas VARCHAR”, Creo que es bueno saber por qué es:

Para los mas comunes COLLATIONs, como los predeterminados como Latin1_General_CI_AI o SQL_Latin1_General_CP1_CI_AS los ENCODING estarán Windows-1252 por varchar los campos. Si echamos un vistazo a su documentación, podemos ver que admite:

Inglés, irlandés, italiano, noruego, portugués, español, sueco. Además también alemán, finlandés y francés. Y holandés excepto el carácter IJ

Pero como dije antes, no se trata de lenguaje, se trata de qué caracteres esperas apoyar / almacenar, como se muestra en el ejemplo de emoji, o alguna oración como “La resistencia eléctrica de una batería de litio es 0.5Ω” donde tenemos nuevamente inglés simple, y una letra / carácter griego “omega” (que es el símbolo de resistencia en ohmios), que no será manejado correctamente por Windows-1252 ENCODING.

Conclusión:

¡Así que ahí está! Cuando se usa char/nchar y varchar/nvarchar depende de los caracteres que desea admitir, y también de la versión de su servidor SQL que determinará qué COLLATIONs y de ahí el ENCODINGs tienes disponible.

Qué es UNICODE, ENCODING, COLLATION y UTF-8, y cómo se relacionan
Nota: todas las explicaciones a continuación son simplificaciones. Consulte los enlaces de documentación suministrados para conocer todos los detalles sobre esos conceptos.

  • UNICODE – Es un estándar, una convención, que tiene como objetivo regular todos los personajes en una tabla unificada y organizada. En esta tabla, cada carácter tiene un número único. Este número comúnmente se llama carácter code point.
    ¡UNICODE NO ES UNA CODIFICACIÓN!

  • ENCODING – Es un mapeo entre un carácter y una secuencia de bytes / bytes. Entonces, una codificación se usa para “transformar” un carácter en bytes y también al revés, de bytes a un carácter. Entre los más populares se encuentran UTF-8, ISO-8859-1, Windows-1252 y ASCII. Puede pensar en ello como una “tabla de conversión” (realmente simplificado aquí).

  • COLLATION – Ese es importante. Incluso la documentación de Microsoft no deja esto claro como debería ser. Una intercalación especifica cómo se ordenarían, compararían, ¡Y ALMACENADO!. Sí, apuesto a que no esperabas ese último, ¿verdad? Las colaciones en SQL Server determina también cuál sería el ENCODING usado en ese particular char/nchar/varchar/nvarchar campo.

  • ASCII ENCODING – Fue una de las primeras codificaciones. Es tanto la tabla de caracteres (como una propia versión diminuta de UNICODE) y sus asignaciones de bytes. Entonces no asigna un byte a UNICODE, pero asigna un byte a la tabla de su propio carácter. Además, siempre usa solo 7 bits y admite 128 caracteres diferentes. Fue suficiente para admitir todas las letras inglesas en mayúsculas y minúsculas, números, puntuación y algún otro número limitado de caracteres. El problema con ASCII es que dado que solo usaba 7 bits y casi todas las computadoras tenían 8 bits en ese momento, había otras 128 posibilidades de caracteres para ser “explorados”, y todos comenzaron a asignar estos bytes “disponibles” a su propia tabla de caracteres. , creando un montón de diferentes ENCODINGs.

  • UTF-8 ENCODING – Este es otro ENCODING, uno de los más (si no el más) utilizados ENCODING alrededor. Utiliza un ancho de byte variable (un carácter puede tener de 1 a 6 bytes de largo, por especificación) y es totalmente compatible con todos UNICODE caracteres.

  • Windows-1252 ENCODING – También uno de los más usados ENCODING, se usa ampliamente en SQL Server. Tiene un tamaño fijo, por lo que cada carácter es siempre de 1 byte. También admite muchos acentos, de varios idiomas, pero no admite todos los existentes ni admite UNICODE. Es por eso que tu varchar campo con una colación común como Latin1_General_CI_AS apoyos á,é,ñ personajes, incluso que no está utilizando un apoyo UNICODE ENCODING.

Recursos:
https://blog.greglow.com/2019/07/25/sql-think-that-varchar-characters-if-so-think-again/
https://medium.com/@apiltamang/unicode-utf-8-and-ascii-encodings-made-easy-5bfbe3a1c45a
https://www.johndcook.com/blog/2019/09/09/how-utf-8-works/
https://www.w3.org/International/questions/qa-what-is-encoding

https://en.wikipedia.org/wiki/List_of_Unicode_characters
https://www.fileformat.info/info/charset/windows-1252/list.htm

https://docs.microsoft.com/en-us/sql/t-sql/data-types/char-and-varchar-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/en-us/sql/t-sql/data-types/nchar-and-nvarchar-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/en-us/sql/t-sql/statements/sql-server-collation-name-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver15#SQL-collations

Codificación de caracteres predeterminada de SQL Server
https://en.wikipedia.org/wiki/Windows_code_page

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *