Quero definir uma variável de seqüência de caracteres Unicode para um caractere específico com base em seu ponto de código Unicode.
Desejo usar um ponto de código além de 65535, mas o banco de dados do SQL Server 2008 R2 possui um agrupamento de SQL_Latin1_General_CP1_CI_AS
.
De acordo com a documentação NCHAR da Microsoft , a NCHAR
função assume um número inteiro da seguinte maneira:
expressão inteira
Quando o agrupamento do banco de dados não contém o sinalizador de caracteres suplementares (SC), esse é um número inteiro positivo de 0 a 65535 (0 a 0xFFFF). Se um valor fora desse intervalo for especificado, NULL será retornado. Para obter mais informações sobre caracteres suplementares, consulte Suporte a agrupamento e Unicode.
Quando o agrupamento do banco de dados suporta o sinalizador de caracteres suplementares (SC), esse é um número inteiro positivo de 0 a 1114111 (0 a 0x10FFFF). Se um valor fora desse intervalo for especificado, NULL será retornado.
Portanto, este código:
SELECT NCHAR(128512);
Retorna NULL
neste banco de dados.
Gostaria que retornasse o mesmo que este:
SELECT N'😀';
Como posso definir uma variável de seqüência de caracteres Unicode (por exemplo, nvarchar) para um emoji usando código (sem usar o caractere emoji real) em um banco de dados em que o agrupamento "não contém o sinalizador de caracteres suplementares (SC)"?
Lista completa de pontos de código Unicode emoji
(Por fim, quero que qualquer personagem funcione. Acabei de escolher emoji para facilitar a referência.)
(Embora o servidor seja o SQL Server 2008 R2, também estou curioso sobre quaisquer soluções para versões posteriores.)
Supondo que não há como, eu poderia referenciar uma função definida pelo usuário em linha em outro banco de dados que tivesse um agrupamento apropriado?
Como encontro um agrupamento com o sinalizador "caráter suplementar"?
Isso não retorna registros em nosso servidor:
SELECT * FROM sys.fn_helpcollations()
WHERE name LIKE 'SQL%[_]SC';
Parece que o SQL Server 2012 foi introduzido, o Latin1_General_100_CI_AS_SC
que funcionaria. Você pode instalar agrupamentos em instâncias mais antigas?
Referências de agrupamento:
- Resposta para Qual é a diferença entre char, nchar, varchar e nvarchar no SQL Server?
- Informações suplementares sobre o agrupamento de caracteres da Microsoft
- Lista de agrupamento do SQL Server 2008 R2 da Microsoft
Existe uma explicação para o motivo pelo qual, independentemente do agrupamento, o SQL Server pode entender e lidar com os caracteres estendidos, exceto na perspectiva de NCHAR
?
Respostas:
A codificação UCS-2 é sempre de 2 bytes por caractere e tem um intervalo de 0 a 65535 (0x0000 - 0xFFFF). UTF-16 (independentemente de Big Endian ou Little Endian) tem um intervalo de 0 - 1114111 (0x0000 - 0x10FFFF). O intervalo de 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 é de 2 bytes por caractere, enquanto o intervalo acima de 65536 / 0xFFFF é de 4 bytes por caractere.
O Windows e o SQL Server começaram usando a codificação UCS-2 porque estava disponível e o UTF-16 ainda não havia sido finalizado. Felizmente, no entanto, houve bastante previsão nos designs do UCS-2 e UTF-16 para que os mapeamentos UCS-2 sejam um subconjunto completo dos mapeamentos UTF-16 (o que significa: o intervalo 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 é UCS-2). AND, o intervalo 65536 - 1114111 (0x10000 - 0x10FFFF) do UTF-16 é construído a partir de dois pontos de código no intervalo UCS-2 (intervalos 0xD800 - 0xDBFF e 0xDC00 - 0xDFFF, especificamente) que foram reservados para esse fim e, caso contrário, não possuem significado. Essa combinação de dois Pontos de Código é conhecida como Par Substituto, e Pares Substitutos representam caracteres além do intervalo UCS-2, conhecidos como Caracteres Suplementares.
Todas essas informações explicam dois aspectos dos
NVARCHAR
dados / Unicode no SQL Server:NCHAR()
) não manuseiam pares substitutos / caracteres suplementares quando não se usa um caractere de Ciente Agrupamento Complementar (SCA; isto é, um com_SC
, ou_140_
, mas não_BIN*
no nome), porque o não-SCA agrupamentos (especialmente oSQL_
Collations) foram originalmente implementados antes da conclusão da UTF-16 (em algum momento de 2000, acredito). Os nãoSQL_
agrupamentos que possuem_90_
ou_100_
em seus nomes, mas não_SC
têm suporte mínimo para caracteres suplementares em termos de comparação e classificação.NVARCHAR
/NCHAR
/XML
/NTEXT
tipos de dados porque UCS-2 e UTF-16 são as mesmas sequências exacto de bytes. A única diferença é que o UTF-16 utiliza os pontos de código substitutos para construir pares substitutos, e o UCS-2 simplesmente não pode mapeá-los para nenhum caractere; portanto, eles aparecem nas funções internas como dois caracteres desconhecidos.Com essas informações em segundo plano, agora podemos passar por perguntas específicas:
Isso só pode acontecer se o banco de dados atual - onde a consulta está sendo executada - tiver um agrupamento padrão que seja sensível a caracteres suplementares e que tenha sido introduzido no SQL Server 2012. Funções internas que possuem parâmetros de entrada de sequência podem ter o agrupamento fornecido inline por meio da
COLLATE
cláusula (ieLEN(N'string' COLLATE Some_Collation_SC)
) e não precisa ser executada em um banco de dados que tenha um agrupamento padrão de SCA. No entanto, funções internas comoNCHAR()
aceitar umINT
parâmetro de entrada e aCOLLATE
cláusula não são válidas nesse contexto (é por isso queNCHAR()
apenas suporta caracteres suplementares quando o banco de dados atual possui um agrupamento padrão que é sensível a caracteres suplementares; mas isso é desnecessário inconveniência que pode ser alterada, por favor vote na minha sugestão:A função NCHAR () sempre deve retornar Caractere Suplementar para os valores 0x10000 - 0x10FFFF, independentemente do agrupamento padrão do banco de dados ativo ).Como o SQL Server pode armazenar e recuperar caracteres suplementares sem perda de dados foi explicado na seção superior desta resposta. Mas, não é verdade que essa
NCHAR
seja a única função interna que possui problemas com caracteres suplementares (quando não estiver usando um agrupamento SCA). Por exemplo,LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
retorna um valor de 2 enquantoLEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
retorna um valor de 1.Se você acessar o segundo link publicado na pergunta (por exemplo, "Informações adicionais sobre o agrupamento de caracteres da Microsoft") e rolar um pouco para baixo, verá um gráfico das funções internas e como elas se comportam com base no agrupamento efetivo.
Em uma versão do SQL Server anterior a 2012, você não pode. Mas, começando no SQL Server 2012, você pode usar a seguinte consulta:
Sua consulta foi encerrada, mas o padrão foi iniciado
SQL
e os agrupamentos do SQL Server (ou seja, aqueles que começaram comSQL_
) foram descontinuados por um tempo a favor dos agrupamentos do Windows (aqueles que não começaramSQL_
). Portanto, osSQL_
agrupamentos não estão sendo atualizados e, portanto, não têm versões mais recentes que incluam a_SC
opção (e, a partir do SQL Server 2017, todos os novos agrupamentos suportam automaticamente caracteres suplementares e não precisam ou têm o_SC
sinalizador; e sim, a consulta mostrado imediatamente acima é responsável por isso, além de coletar os_UTF8
agrupamentos adicionados no SQL Server 2019).Não, você não pode instalar agrupamentos em uma versão anterior do SQL Server.
Quando não estiver usando um agrupamento SCA, é possível injetar pontos de código acima de 65535 / U + FFFF de duas maneiras:
NCHAR()
função, cada uma com uma parte do parVARBINARY
forma da sequência de bytes Little Endian (ou seja, invertida).Esses dois métodos de inserção de pares de caracteres suplementares / substitutos funcionarão mesmo que o agrupamento efetivo seja sensível a caracteres suplementares e devem funcionar da mesma forma em todas as versões do SQL Server, pelo menos desde 2005 (embora provavelmente também funcione em SQL Server 2000 também).
Exemplo:
💩
ATUALIZAR
Você pode usar o seguinte iTVF para obter os valores do Par Substituto (em ambos
INT
e naBINARY
forma) de qualquer Ponto de Código entre 65536 - 1114111 (0x010000 - 0x10FFFF). E, embora o parâmetro de entrada seja do tipoINT
, você pode passar na forma binária / hexadecimal do ponto de código e ele implicitamente será convertido no valor inteiro correto.Usando a função acima, as duas consultas a seguir:
ambos retornam o seguinte:
ATUALIZAÇÃO 2: Uma atualização ainda melhor!
Eu adaptei o iTVF mostrado acima para retornar agora 188.657 pontos de código, para que você não precise ajustar nenhum valor específico. É claro que, sendo um TVF, você pode adicionar uma
WHERE
cláusula para filtrar um ponto de código específico, ou intervalo de pontos de código ou "caracteres semelhantes" etc. etc. E inclui colunas adicionais com seqüências de escape pré-formatadas para construir cada código ponto (BMP e caracteres suplementares) no estilo T-SQL, HTML e C (ou seja\xHHHH
). Leia tudo sobre isso aqui:Dica 3 do SSMS: acesse / pesquise facilmente todos os caracteres Unicode (sim, incluindo emojis)
fonte