¿Por qué necesitamos poner N antes de las cadenas en Microsoft SQL Server?


34

Estoy aprendiendo T-SQL. A partir de los ejemplos que he visto, para insertar texto en una varchar()celda, puedo escribir solo la cadena para insertar, pero para las nvarchar()celdas, en cada ejemplo se prefieren las cadenas con la letra N.

Intenté la siguiente consulta en una tabla que tiene nvarchar()filas, y funciona bien, por lo que no se requiere el prefijo N:

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

¿Por qué las cadenas tienen el prefijo N en todos los ejemplos que he visto?

¿Cuáles son las ventajas y desventajas de usar este prefijo?


¿No se necesita la N solo para cadenas literales?
Wayne In Yak

¿El polaco es un idioma no latino?
Heckflosse_230

2
Nsignifica nacional, como en "Carácter nacional variable", vea Tipos de datos ANSI SQL equivalentes .
ErikE

Estoy de acuerdo con esta pregunta y nadie la ha respondido hasta ahora, AFAICT. Tal vez podría ser reformulada como “¿por qué es malo para dejar SQL convertir implícitamente mi VARCHARa NVARCHARcuando mi cadena literal es el ASCII?”.
binki

Esta pregunta ya se hizo y respondió aquí: ¿Cuál es la diferencia entre varchar y nvarchar?

Respuestas:


27

NVarchar se utiliza para Unicode. Si su base de datos no almacena datos multilingües, puede seguir usando Varchar. Como ejemplo: N'abc'simplemente convierte tu cadena a unicode.


2
¿Por qué no tienes que prefijar con U en lugar de N entonces?
Attila Kun

U podría confundirse por no haber firmado como una suposición
JB King

U&'abc'es la forma correcta de especificar cadenas Unicode. Vea el SQL 2003 BNF
ceving

2
La N en realidad significa "conjunto de caracteres del idioma nacional".
Mike Bovenlander

23

Por defecto, el servidor SQL usa los códigos de caracteres de Windows-1252 para varchar . Contiene la mayoría de los caracteres para idiomas basados ​​en latín (inglés, alemán, francés, etc.) Pero no contiene caracteres para idiomas no latinos (polaco, ruso, etc.). Como lo indicó @Pieter B, nvarchar se usa para solucionar ese problema porque es para Unicode que contiene esos caracteres faltantes. Esto tiene un costo, se necesita el doble de espacio para almacenar nvarchar que varchar.

Poner N delante de su cadena asegura que los caracteres se conviertan a Unicode antes de colocarlos en una columna nvarchar. La mayoría de las veces estará bien dejando el N apagado, pero no lo recomendaría. Es mucho mejor prevenir que curar.


3
Solo una aclaración: el servidor SQL "Por defecto" usa la codificación correspondiente a la intercalación del campo Varchar, que se puede anular en el momento de la creación del campo, generalmente basada en la intercalación predeterminada para su instancia. La clasificación predeterminada para su instancia se puede establecer en el momento de la instalación, pero generalmente corresponde al CP_ACP del entorno local predeterminado del sistema. Será Windows 1252 en una máquina de EE. UU. E inglés, pero 932 en una máquina con una configuración regional del sistema japonés, 1251 en una máquina rusa, etc. ¿La moraleja de la historia? Use NVarchar :)
JasonTrue

1
Hasta ahora, esta es la única respuesta que responde a la pregunta "¿Por qué usar el prefijo N en las cadenas literales ya que SQL transcodificará implícitamente?". Las otras respuestas son todas para una pregunta diferente "¿Cuál es la diferencia entre nvarchar y varchar?"
Timbo

18

Porque MS SQL Server tiene poca compatibilidad con UTF-8 en comparación con otros RDBMS.

MS SQL Server sigue la convención, utilizada dentro de Windows, de que las cadenas "estrechas" ( charen C ++ CHARo VARCHARen SQL) están codificadas en una "página de códigos" heredada. El problema con las páginas de códigos es que tienen un número limitado de caracteres (la mayoría son codificaciones de un solo byte, lo que limita el informe a 256 caracteres) y están diseñadas en torno a un solo idioma (o grupo de idiomas con alfabetos similares). Esto dificulta el almacenamiento de datos multilingües. Por ejemplo, no puede almacenar datos en ruso y en hebreo porque el ruso usa la página de códigos 1251 y el hebreo usa la página de códigos 1255 .

Unicode resuelve este problema mediante el uso de un único conjunto de caracteres codificados con espacio para más de un millón de caracteres, suficiente para representar todos los idiomas del mundo. Hay varios esquemas de codificación Unicode; Microsoft prefiere usar UTF-16 , por razones históricas . Debido a que UTF-16 representa cadenas como una secuencia de unidades de código de 16 bits en lugar del tradicional de 8 bits, se necesita un tipo de carácter separado. En MSVC ++, esto es wchar_t. Y en MS SQL, es NCHARo NVARCHAR. El Nsinónimo de "nacional" , lo que parece imposible para mí porque se trata de Unicode entre -Nacionalización, pero eso es la terminología ISO.

Otras implementaciones de SQL le permiten almacenar texto UTF-8 en una VARCHARcolumna. UTF-8 es una codificación de longitud variable (1-4 bytes por carácter) que está optimizada para el caso en que sus datos se encuentran principalmente en el rango del latín básico (que se representan como el mismo 1 byte por carácter que ASCII), pero pueden representar cualquier personaje Unicode. Por lo tanto, evitaría el problema del "doble espacio" mencionado por bwalk2895.

Desafortunadamente, MS SQL Server no admite UTF-8VARCHAR , por lo que debe usar UTF-16 (y desperdiciar espacio para texto ASCII), usar una página de códigos que no sea Unicode (y perder la capacidad de representar caracteres extraños), o almacene UTF-8 en una BINARYcolumna (y lidie con inconvenientes como que las funciones de cadena SQL no funcionan correctamente o que tiene que ver los datos como un volcado hexadecimal en su administrador de DB GUI).


1
En versiones anteriores a SQL Server 2012, usaban codificación UCS-2, que es estrictamente de 2 bytes. En las versiones más nuevas, usan UTF-16, que es una asignación de longitud variable a 4bytes por carácter (similar a UTF-8 pero a partir de 2 bytes).
j123b567
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.