AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 196570
Accepted
Shiva
Shiva
Asked: 2018-01-31 01:15:53 +0800 CST2018-01-31 01:15:53 +0800 CST 2018-01-31 01:15:53 +0800 CST

Por que o tipo de dados varchar permite valores unicode?

  • 772

Eu tenho uma tabela com uma coluna varchar. Está permitindo Trademark(™), copyright(©) e outros caracteres Unicode, conforme 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 Trademark(™) e Registered(®) 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.

sql-server datatypes
  • 5 5 respostas
  • 17450 Views

5 respostas

  • Voted
  1. Best Answer
    sepupic
    2018-01-31T02:07:41+08:002018-01-31T02:07:41+08:00

    Mas os símbolos Trademark(™) e Registered(®) são caracteres Unicode.

    Você está errado aqui. Suas strings contêm apenas caracteres ASCII.

    Aqui está um teste simples que mostra que seus caracteres são todos ASCII (+ alguns ASCII estendidos com códigos ASCII entre 128 e 255):

    declare @VarcharUnicodeCheck table
    (
    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 *,
            right(col1, 1)as last_char, 
            ascii(right(col1, 1)) as_last_char_ascii
    from @VarcharUnicodeCheck;
    

    Aqui você pode ver claramente que todos os seus caracteres são codificados em 1 byte:

    insira a descrição da imagem aqui

    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:

    declare @t table (uni_ch nchar(1), ascii_ch char(1));
    insert into @t values (N'™', '™');
    
    select unicode(uni_ch) as [unicode of ™], 
           ascii(ascii_ch) [ascii of ™], 
           cast(uni_ch as varbinary(10)) as [uni_ch as varbinary], 
           cast(ascii_ch as varbinary(10)) as [ascii_ch as varbinary]
    from @t;
    

    insira a descrição da imagem aqui

    Finalmente, você pode ver que o caractere Unicode Trademark(™) tem código 8482 e não 153:

    select nchar(8482), nchar(153)
    
    • 14
  2. Dan Guzman
    2018-01-31T05:03:19+08:002018-01-31T05:03:19+08:00

    Pelos comentários, concordo que "Extended ASCII" é um termo muito ruim que na verdade significa uma página de código que mapeia caracteres/pontos de código no intervalo 128-255, além do intervalo de ponto de código padrão 0-127 definido pelo ASCII.

    O SQL Server oferece suporte a muitas páginas de código por meio de agrupamentos. Caracteres não ASCII podem ser armazenados em varchar, desde que a ordenação subjacente suporte o caractere.

    O caractere '™' pode ser armazenado em colunas varchar/char quando a página de código de agrupamento do SQL Server for 1250 ou superior. A consulta abaixo listará estes:

    SELECT COLLATIONPROPERTY(name, 'CodePage') AS code_page, name, description
    FROM sys.fn_helpcollations()
    WHERE COLLATIONPROPERTY(name, 'CodePage') >= 1250
    ORDER BY name;
    

    Mas apenas um subconjunto deles também suporta o caractere '©', portanto, o agrupamento de colunas precisará ser um dos seguintes para oferecer suporte a ambos:

    SELECT COLLATIONPROPERTY(name, 'CodePage') AS code_page, name, description
    FROM sys.fn_helpcollations()
    WHERE COLLATIONPROPERTY(name, 'CodePage') IN(
        1250
        ,1251
        ,1252
        ,1253
        ,1254
        ,1255
        ,1256
        ,1257
        ,1258
    )
    ORDER BY name;
    
    • 7
  3. Solomon Rutzky
    2018-01-31T14:55:52+08:002018-01-31T14:55:52+08:00

    Mas a definição de varchar diz que permite dados de string não unicode . Mas os símbolos Trademark(™) e Registered(®) são caracteres Unicode . A definição contradiz a propriedade do tipo de dados varchar?

    Embora as outras respostas não estejam incorretas, acho que ajudaria 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 dados Unicode e não Unicode , eles não estão falando sobre os caracteres . Eles estão falando das sequências de bytes que representam determinados caracteres. A principal diferença entre os tipos Unicode ( NCHAR, NVARCHAR, XML, e o obsoleto / evil NTEXT) e os tipos não Unicode ( CHAR, VARCHAR, e o obsoleto / evil TEXT) são os tipos de sequências de bytes que eles 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 Collation. Enquanto outros notaram que o valor do byte de um "caractere" pode variar entre as páginas de código em que ele é encontrado, o valor do 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 de Windows- 1252), que são encontrados apenas no SQL Server Collations mais antigos e que não deveriam ser usados ​​(ou seja, aqueles com nomes começando com SQL_).

    Portanto, a definição é precisa: quaisquer caracteres que você consiga 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 único "caracter", que é o que o Double- Byte Character Set / páginas de código 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 único "caractere" (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 VARCHARe aos CHARtipos de dados a partir do SQL Server 2019,

    VARCHARnã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 referir VARCHARcomo um "tipo de dados de 8 bits", mesmo quando falamos de versões anteriores ao SQL Server 2019. Essa terminologia é válida para todos os 4 tipos de codificações que podem ser usadas com VARCHAR:

    1. ASCII Estendido
    2. Conjuntos de caracteres de byte duplo (DBCS)
    3. EBCDIC
    4. UTF-8 (Unicode)

    Apenas o tipo de TEXTdados (desatualizado a partir do SQL Server 2005, portanto, não o use) é "não-Unicode", mas isso é apenas um detalhe técnico, e referir-se a ele como um "tipo de dados de 8 bits" é preciso.

    NVARCHAR, NCHAR, e NTEXTpode ser referido como "UTF-16" ou um "tipo de dados de 16 bits". A Oracle, acredito, usa a terminologia de "somente Unicode" para NVARCHAR, mas isso não exclui claramente a possibilidade de usar UTF-8 (também uma codificação Unicode), que não funcionará, então provavelmente é melhor ficar com as duas primeiras opções.

    Para obter detalhes sobre as novas codificações UTF-8, consulte minha postagem:

    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 de UTF-8, incluindo a documentação de char e varchar referenciada na pergunta. Ele não contém mais a frase "não-Unicode". Mas isso é apenas um FYI; isso não altera a pergunta, pois trata-se de codificações não Unicode contendo caracteres que foram erroneamente considerados apenas Unicode.

    • 5
  4. IMSoP
    2018-01-31T11:41:31+08:002018-01-31T11:41:31+08:00

    A questão 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 que usei nesta resposta poderia ser armazenado nesse tipo, porque todas as letras do alfabeto latino e a pontuação comum usadas no inglês cotidiano são incluído no Unicode.

    As representações de texto podem ser divididas 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 principalmente preocupados com a primeira parte: quais caracteres são listados nos gráficos para um conjunto de caracteres específico.

    Como o Unicode visa ter números (que ele chama de "pontos de código") para cada caractere do mundo, referências como a Wikipedia geralmente se referem à posição Unicode de um caractere como uma informação padrão de referência. No entanto, isso não significa que outros conjuntos de caracteres também não tenham um mapeamento para esse mesmo caractere.

    Um dos conjuntos de caracteres (e codificações) mais antigos e simples ainda em uso é o ASCII, que possui mapeamentos para 128 caracteres diferentes (0 a 127), pois utiliza 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 primeiros 128 caracteres, adicionando ao conjunto de caracteres preenchendo as posições 128 a 255. Entre eles, destacam-se os padrões ISO 8859-1 e ISO 8859- 15 e a página de código do Windows específica da Microsoft 1252 .

    Então, voltando ao MS SQL Server: uma "string Unicode", conforme armazenada em uma coluna , , ou , pode representar nchartodos nvarcharos caracteres mapeados no conjunto de caracteres Unicode, pois usa uma codificação Unicode para armazenar os dados. Uma "string não Unicode", conforme armazenada em uma coluna , , ou pode representar apenas os caracteres mapeados em alguma outra codificação . Qualquer coisa que você possa armazenar em uma coluna não Unicode também pode ser armazenada em uma coluna Unicode, mas não vice-versa.ntextcharvarchartext

    Para saber exatamente quais caracteres você pode armazenar, você precisa 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 . É provável que no seu caso você esteja usando a página de código 1252 muito comum, que mencionei anteriormente.

    Os caracteres que você mencionou existem em Unicode e Code Page 1252:

    • Trademark(™) aparece em Unicode na posição 8482 e em CP1252 na posição 153
    • Registered(®), por acaso, aparece em Unicode e CP1252 na posição 174
    • 3
  5. Kyle Rondeau
    2021-05-21T20:50:13+08:002021-05-21T20:50:13+08:00

    Aceitar algo e SOMENTE aceitar algo NÃO são a mesma coisa. Se você for a um drive-thru que diz "aceitamos notas de $ 50", isso significa que eles SÓ aceitam notas de $ 50? Claro que não. Da mesma forma, nem aceita Unicode e APENAS aceita Unicode o mesmo. Você adicionou a palavra "SOMENTE" onde, de acordo com sua pergunta, ela não existia na definição que você citou.

    • -1

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve