Tengo una mesa con una columna varchar. Está permitiendo Trademark (™), copyright (©) y otros caracteres Unicode como se muestra a continuación.
Create table VarcharUnicodeCheck
(
col1 varchar(100)
)
insert into VarcharUnicodeCheck (col1) values ('MyCompany')
insert into VarcharUnicodeCheck (col1) values ('MyCompany™')
insert into VarcharUnicodeCheck (col1) values ('MyCompany░')
insert into VarcharUnicodeCheck (col1) values ('MyCompanyï')
insert into VarcharUnicodeCheck (col1) values ('MyCompany')
select * from VarcharUnicodeCheck
Pero la definición de varchar dice que permite datos de cadena no unicode. Pero los símbolos Trademark (™) y Registered (®) son caracteres Unicode . ¿La definición contradice la propiedad del tipo de datos varchar? Leí un par de enlaces como el primero y el segundo . Pero aún así no podía entender por qué permite la cadena unicode cuando la definición dice que solo permite valores de cadena no unicode.
Respuestas:
Estás equivocado aquí. Sus cadenas contienen solo
ascii
caracteres.Aquí hay una prueba simple que muestra que tus personajes son todos ascii (+ algunos
extended ascii
con códigos ascii entre 128 y 255):Aquí puede ver claramente que todos sus personajes están codificados con 1 byte:
Sí, no son caracteres ascii puros, sino ASCII extendido .
Aquí te muestro el verdadero carácter unicode
Trademark(™)
y su código y representación binaria:Finalmente, puede ver que el
Trademark(™)
carácter unicode tiene código 8482 y no 153:fuente
Ö
) toma ese lugar y en ISO-8859-1 (a veces llamado Latin1) es un código de control sin representación imprimible. A menos que sepa que siempre usará la misma página de códigos, es más seguro adherirse a los caracteres ANSI (127 o menos) o usar tipos Unicode. La página de códigos 1252 es más común en SQL Server pero está lejos de ser omnipresente.De los comentarios, estoy de acuerdo que "ASCII extendido" es un término realmente malo que en realidad significa una página de códigos que asigna caracteres / puntos de código en el rango de 128-255, más allá del rango de puntos de código estándar de 0-127 definido por ASCII.
SQL Server admite muchas páginas de códigos a través de intercalaciones. Los caracteres no ASCII se pueden almacenar en varchar siempre que la clasificación subyacente admita el carácter.
El carácter '™' se puede almacenar en columnas varchar / char cuando la página de códigos de ordenación de SQL Server es 1250 o superior. La consulta a continuación enumerará estos:
Pero solo un subconjunto de estos también admite el carácter '©', por lo que la clasificación de columnas deberá ser una de las siguientes para admitir ambos:
fuente
Si bien las otras respuestas no son incorrectas, creo que ayudaría señalar una confusión en la terminología básica. He enfatizado dos palabras en la cita anterior de la pregunta como un ejemplo de esta confusión. Cuando la documentación de SQL Server habla de no Unicode Unicode y datos , que están no hablan de los personajes . Están hablando de las secuencias de bytes que representan ciertos caracteres. La principal diferencia entre los tipos Unicode (
NCHAR
,NVARCHAR
,XML
, y el desuso / malosNTEXT
) y los tipos no Unicode (CHAR
,VARCHAR
y el desuso / malTEXT
) es lo que los tipos de secuencias de bytes que pueden almacenar.Los tipos no Unicode almacenan una de varias codificaciones de 8 bits, mientras que los tipos Unicode almacenan una sola codificación Unicode de 16 bits: UTF-16 Little Endian. Como las otras respuestas han mencionado, qué caracteres se pueden almacenar en una codificación de 8 bits / no Unicode depende de la página de códigos, que está determinada por la Clasificación. Mientras que otros han notado que el valor de byte de un "carácter" puede variar entre las páginas de códigos en las que se encuentra, el valor de byte incluso puede variar dentro de la misma página de códigos cuando se trata de una de las varias páginas de códigos EBCDIC (variaciones de Windows- 1252), que solo se encuentran en las clasificaciones de SQL Server más antiguas, no deberían usarse realmente (es decir, aquellas que tienen nombres que comienzan con
SQL_
).Por lo tanto, la definición es precisa: los caracteres que puede almacenar en un tipo que no sea Unicode son siempre de 8 bits (incluso si usan dos valores de 8 bits en combinación como un solo "carácter", que es lo que el Double- El conjunto de caracteres de bytes / las páginas de códigos DBCS lo permiten). Y los tipos de datos Unicode son siempre de 16 bits, incluso si a veces usan dos valores de 16 bits en combinación como un solo "carácter" (es decir, un par sustituto que a su vez representa un carácter suplementario).
Y, debido a que SQL Server admite de forma nativa la codificación UTF-8
VARCHAR
y losCHAR
tipos de datos a partir de SQL Server 2019,VARCHAR
ya no puede denominarse "no Unicode". Entonces, comenzando con la primera versión beta pública de SQL Server 2019 en septiembre de 2018, deberíamos referirnosVARCHAR
como un "tipo de datos de 8 bits", incluso cuando se habla en términos de versiones anteriores a SQL Server 2019. Esta terminología es válida para los 4 tipos de codificaciones que se pueden usar conVARCHAR
:Solo el
TEXT
tipo de datos (en desuso a partir de SQL Server 2005, así que no lo use) es "no Unicode", pero eso es solo un tecnicismo, y referirse a él como un "tipo de datos de 8 bits" es exacto.NVARCHAR
,NCHAR
yNTEXT
puede denominarse "UTF-16" o "tipo de datos de 16 bits". Oracle, creo, usa la terminología de "Unicode-only" paraNVARCHAR
, pero eso no descarta claramente la posibilidad de usar UTF-8 (también una codificación Unicode), que no funcionará, así que probablemente sea mejor quedarse con Las dos primeras opciones.Para obtener detalles sobre las nuevas codificaciones UTF-8, consulte mi publicación:
Soporte nativo de UTF-8 en SQL Server 2019: ¿Salvador o falso profeta?
PD: Estoy trabajando lentamente para actualizar la documentación de SQL Server para reflejar estos cambios.
PPS Microsoft ya ha actualizado algunas páginas con información de UTF-8, incluida la documentación de char y varchar a la que se hace referencia en la pregunta. Ya no contiene la frase "no Unicode". Pero eso es solo un FYI; no cambia la pregunta, ya que se trata de codificaciones no Unicode que contienen caracteres que se pensaban erróneamente que eran solo Unicode.
fuente
La pregunta contiene un error central sobre lo que es Unicode. El conjunto de caracteres Unicode, junto con sus codificaciones como UTF-8 y UTF-16, es una de las muchas formas de representar texto en una computadora, y una cuyo objetivo es reemplazar todos los demás conjuntos de caracteres y codificaciones. Si "datos que no son Unicode" significan "caracteres no presentes en Unicode", entonces ninguno de los textos que he usado en esta respuesta podría almacenarse en ese tipo, porque todas las letras del alfabeto latino y la puntuación común utilizada en inglés cotidiano son incluido en Unicode.
Las representaciones de texto se pueden considerar ampliamente en dos partes: un conjunto de caracteres que asigna los diferentes caracteres (letras, dígitos, símbolos, etc.) a números en un gráfico de referencia; y una codificación que representa esos números como patrones de bits (en el disco, a través de una conexión de red, etc.). Aquí nos ocupamos principalmente de la primera parte: qué caracteres se enumeran en los gráficos para un conjunto de caracteres en particular.
Dado que Unicode tiene como objetivo tener números (que llama "puntos de código") para cada personaje en el mundo, las referencias como Wikipedia a menudo se referirán a la posición Unicode de un personaje como información estándar de referencia. Sin embargo, eso no significa que otros conjuntos de caracteres no tengan una asignación para ese mismo carácter.
Uno de los conjuntos de caracteres (y codificaciones) más antiguos y más simples que todavía se usan es ASCII, que tiene asignaciones para 128 caracteres diferentes (0 a 127), ya que utiliza 7 bits para codificar cada carácter. Dado que esto excluye muchos caracteres acentuados y símbolos comunes, las codificaciones posteriores usan 8 bits y mapean los mismos primeros 128 caracteres, agregando al conjunto de caracteres al llenar las posiciones 128 a 255. Entre estos destacan los estándares ISO 8859-1 e ISO 8859- 15 , y la página de códigos de Windows específica de Microsoft 1252 .
Por lo tanto, para volver a MS SQL Server: una "cadena Unicode", como se almacena en una
nchar
,nvarchar
ontext
columna, puede representar a todos los caracteres asignados en el conjunto de caracteres Unicode, ya que utiliza una codificación Unicode para almacenar los datos. Una "cadena no Unicode", como se almacena en unachar
,varchar
otext
columna, puede representar sólo los caracteres mapeadas en alguna otra codificación . Cualquier cosa que pueda almacenar en una columna que no sea Unicode también se puede almacenar en una columna Unicode, pero no al revés.Para saber exactamente qué caracteres puede almacenar, debe conocer la "clasificación" en uso, que dicta lo que Microsoft denomina "página de códigos", como se explica en esta página de referencia de Microsoft . En su caso, es probable que esté utilizando el Código de página 1252, que mencioné anteriormente.
Los caracteres que mencionó existen tanto en Unicode como en la página de códigos 1252:
fuente