Eu tenho uma tabela com uma coluna varchar. Ele permite marcas comerciais (™), direitos autorais (©) e outros caracteres Unicode, como mostrado abaixo.
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
Mas a definição de varchar diz que permite dados de string não unicode. Mas os símbolos de marca comercial (™) e registrada (®) são caracteres Unicode . A definição contradiz a propriedade do tipo de dados varchar? Eu li alguns links como o primeiro e o segundo . Mas ainda não consegui entender por que ele permite string unicode quando a definição diz que permite apenas valores de string não unicode.
Respostas:
Você está errado aqui. Suas seqüências contêm apenas
ascii
caracteres.Aqui está um teste simples que mostra que seus personagens são todos ascii (+ alguns
extended ascii
com códigos ascii entre 128 e 255):Aqui você pode ver claramente que todos os seus personagens são codificados em 1 byte:
Sim, eles não são caracteres ascii puros, mas são ASCII estendidos .
Aqui eu mostro o caractere unicode real
Trademark(™)
e seu código e representação binária:Finalmente, você pode ver que o
Trademark(™)
caractere unicode tem código 8482 e não 153:fonte
Ö
) e na ISO-8859-1 (às vezes chamada de Latin1) é um código de controle sem representação imprimível. A menos que você saiba que sempre usará a mesma página de código, é mais seguro aderir a caracteres ANSI (127 ou menos) ou usar tipos Unicode. A página de código 1252 é mais comum no SQL Server, mas está longe de ser onipresente.Pelos comentários, concordo que "ASCII estendido" é um termo muito ruim que realmente significa uma página de código que mapeia caracteres / pontos de código no intervalo 128-255, além do intervalo de pontos de código padrão 0-127 definido pelo ASCII.
O SQL Server oferece suporte a várias páginas de código por meio de agrupamentos. Caracteres não ASCII podem ser armazenados no varchar, desde que o agrupamento subjacente suporte o caractere.
O caractere '™' pode ser armazenado em colunas varchar / char quando a página de código de intercalação do SQL Server for 1250 ou superior. A consulta abaixo listará estes:
Mas apenas um subconjunto desses também suporta o caractere '©', portanto, o agrupamento da coluna precisará ser um dos seguintes para oferecer suporte a ambos:
fonte
Embora as outras respostas não estejam incorretas, acho que ajudaria a apontar uma confusão na terminologia básica. Eu enfatizei duas palavras na citação acima da pergunta como um exemplo dessa confusão. Quando a documentação do SQL Server fala de Unicode e não-Unicode de dados , eles são não falando sobre os personagens . Eles estão falando das seqüências de bytes que representam certos caracteres. A principal diferença entre os tipos de Unicode (
NCHAR
,NVARCHAR
,XML
, e a obsoleta / malNTEXT
) e os tipos não-Unicode (CHAR
,VARCHAR
e a obsoleta / malTEXT
) é o que tipos de sequências de bytes que podem armazenar.Os tipos não Unicode armazenam uma das várias codificações de 8 bits, enquanto os tipos Unicode armazenam uma única codificação Unicode de 16 bits: UTF-16 Little Endian. Como as outras respostas mencionaram, quais caracteres podem ser armazenados em uma codificação de 8 bits / não-Unicode depende da página de código, que é determinada pelo agrupamento. Enquanto outros observaram que o valor de byte de um "caractere" pode variar entre as páginas de código em que ele se encontra, o valor de byte pode até variar dentro da mesma página de código ao lidar com uma das várias páginas de código EBCDIC (variações do Windows- 1252), que são encontrados apenas nos mais antigos, não devem realmente ser usados Collations do SQL Server (ou seja, aqueles com nomes começando com
SQL_
).Portanto, a definição é precisa: todos os caracteres que você pode gerenciar para armazenar em um tipo não Unicode são sempre de 8 bits (mesmo que usem dois valores de 8 bits em combinação como um "caractere" único, que é o que o Double- As páginas de código do Byte Character Set / DBCS permitem). E os tipos de dados Unicode são sempre de 16 bits, mesmo que às vezes usem dois valores de 16 bits em combinação como um "caractere" único (ou seja, um par substituto que, por sua vez, representa um Caractere Suplementar).
E, devido ao suporte nativo do SQL Server à codificação UTF-8 para
VARCHAR
eCHAR
tipos de dados a partir do SQL Server 2019,VARCHAR
não pode mais ser chamado de "não Unicode". Portanto, começando com a primeira versão beta pública do SQL Server 2019 em setembro de 2018, devemos nos referirVARCHAR
como um "tipo de dados de 8 bits", mesmo quando falamos em termos de versões anteriores ao SQL Server 2019. Essa terminologia é válida para todos os quatro tipos de codificações que podem ser usadas comVARCHAR
:Apenas o
TEXT
tipo de dados (descontinuado no SQL Server 2005, portanto, não o use) é "não Unicode", mas isso é apenas um detalhe técnico, e a referência a ele como "tipo de dados de 8 bits" é precisa.NVARCHAR
,,NCHAR
eNTEXT
pode ser referido como "UTF-16" ou "tipo de dados de 16 bits". A Oracle, acredito, usa a terminologia de "somente Unicode" paraNVARCHAR
, mas isso não descarta claramente a possibilidade de usar UTF-8 (também uma codificação Unicode), que não funcionará, portanto, provavelmente é melhor as duas primeiras opções.Para detalhes sobre as novas codificações UTF-8, consulte o meu post:
Suporte nativo a UTF-8 no SQL Server 2019: Salvador ou falso profeta?
PS: Estou trabalhando lentamente na atualização da documentação do SQL Server para refletir essas alterações.
PPS A Microsoft já atualizou algumas páginas com informações UTF-8, incluindo a documentação char e varchar mencionada na pergunta. Ele não contém mais a frase "não Unicode". Mas isso é apenas um FYI; isso não muda a questão, pois trata-se de codificações não Unicode contendo caracteres que, por engano, foram pensados apenas como Unicode.
fonte
A pergunta contém um equívoco central sobre o que é Unicode. O conjunto de caracteres Unicode, juntamente com suas codificações, como UTF-8 e UTF-16, é uma das muitas maneiras de representar texto em um computador, e cujo objetivo é substituir todos os outros conjuntos de caracteres e codificações. Se "dados não Unicode" significasse "caracteres não presentes no Unicode", nenhum texto usado nesta resposta poderia ser armazenado nesse tipo, porque todas as letras do alfabeto latino e pontuação comum usada no inglês comum são incluído no Unicode.
As representações de texto podem ser amplamente pensadas em duas partes: um conjunto de caracteres mapeando os diferentes caracteres (letras, dígitos, símbolos, etc.) para números em um gráfico de referência; e uma codificação representando esses números como padrões de bits (no disco, em uma conexão de rede, etc.). Aqui estamos preocupados principalmente com a primeira parte: quais caracteres estão listados nos gráficos para um conjunto de caracteres específico.
Como o Unicode pretende ter números (chamados de "pontos de código") para todos os caracteres do mundo, referências como a Wikipedia geralmente se referem à posição Unicode de um caractere como uma peça padrão de informação de referência. No entanto, isso não significa que outros conjuntos de caracteres também não tenham um mapeamento para o mesmo caractere.
Um dos conjuntos de caracteres mais antigos e mais simples (e codificações) ainda em uso é o ASCII, que possui mapeamentos para 128 caracteres diferentes (0 a 127), porque usa 7 bits para codificar cada caractere. Como isso exclui muitos caracteres acentuados e símbolos comuns, as codificações posteriores usam 8 bits e mapeiam os mesmos 128 caracteres, adicionando ao conjunto de caracteres preenchendo as posições 128 a 255. Destacam- se os padrões ISO 8859-1 e ISO 8859- 15 e o código do Windows específico da Microsoft, página 1252 .
Então, para voltar para o MS SQL Server: a "seqüência de caracteres Unicode", como armazenados em um
nchar
,nvarchar
ountext
coluna, pode representar todos os caracteres mapeados no conjunto de caracteres Unicode, porque ele usa uma codificação Unicode para armazenar os dados. Uma "cadeia não-Unicode", como armazenado em umchar
,varchar
outext
coluna, podem representar apenas os caracteres mapeados em alguma outra codificação . Tudo o que você pode armazenar em uma coluna não Unicode também pode ser armazenado em uma coluna Unicode, mas não vice-versa.Para saber exatamente quais caracteres você pode armazenar, é necessário conhecer o "agrupamento" em uso, que determina o que a Microsoft chama de "página de código", conforme explicado nesta página de referência da Microsoft . Provavelmente, no seu caso, você está usando a muito comum Página de Código 1252, que mencionei anteriormente.
Os caracteres que você mencionou existem no Unicode e no Code Page 1252:
fonte