Eu quero definir uma variável de string 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 SQL Server 2008 R2 tem um agrupamento de SQL_Latin1_General_CP1_CI_AS
.
De acordo com a documentação do NCHAR da Microsoft , a NCHAR
função recebe um inteiro da seguinte forma:
expressão_inteiro
Quando o agrupamento do banco de dados não contém o sinalizador de caractere suplementar (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 Collation and Unicode Support.
Quando o agrupamento do banco de dados oferece suporte ao sinalizador de caractere suplementar (SC), esse é um número inteiro positivo de 0 a 1114111 (0 a 0x10FFFF). Se for especificado um valor fora desse intervalo, será retornado NULL.
Então este código:
SELECT NCHAR(128512);
Retorna NULL
neste banco de dados.
Eu gostaria que ele retornasse o mesmo que isso:
SELECT N'?';
Como posso definir uma variável de string Unicode (por exemplo, nvarchar) para um emoji usando código (sem usar o caractere emoji real) em um banco de dados onde o agrupamento "não contém o sinalizador de caractere suplementar (SC)"?
Lista completa de pontos de código Unicode emoji
(Em última análise, quero que qualquer personagem funcione. Apenas escolhi emoji para facilitar a referência.)
(Embora o servidor seja o SQL Server 2008 R2, também estou curioso sobre as soluções para versões posteriores.)
Supondo que não há como, eu poderia fazer referência a uma função definida pelo usuário em linha em outro banco de dados que tivesse um agrupamento apropriado?
Como faço para encontrar um agrupamento que tenha o sinalizador "caractere suplementar"?
Isso não retorna nenhum registro em nosso servidor:
SELECT * FROM sys.fn_helpcollations()
WHERE name LIKE 'SQL%[_]SC';
Parece que o SQL Server 2012 foi introduzido Latin1_General_100_CI_AS_SC
, o 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 de agrupamento de caracteres suplementares da Microsoft
- Lista de agrupamentos do SQL Server 2008 R2 da Microsoft
Existe uma explicação de por que, independentemente do agrupamento, o SQL Server pode entender e lidar com os caracteres estendidos, exceto da perspectiva de NCHAR
?
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 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 ela estava disponível e o UTF-16 ainda não havia sido finalizado. Felizmente, no entanto, houve planejamento suficiente nos projetos de UCS-2 e UTF-16 para que os mapeamentos UCS-2 sejam um subconjunto completo dos mapeamentos UTF-16 (ou seja: o intervalo 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 é UCS-2). E, o intervalo 65536 - 1114111 (0x10000 - 0x10FFFF) de 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 essa finalidade e, de outra forma, não têm significado. Essa combinação de dois Pontos de Código é conhecida como Par Surrogate, e os Pares Surrogate representam caracteres além do intervalo UCS-2 que são conhecidos como Caracteres Suplementares.
Todas essas informações explicam dois aspectos dos
NVARCHAR
dados / Unicode no SQL Server:NCHAR()
) não lidam com Pares substitutos / caracteres suplementares quando não estão usando um agrupamento com reconhecimento de caractere suplementar (SCA; ou seja, um com_SC
, ou_140_
mas não_BIN*
no nome) porque os agrupamentos não SCA (especialmente oSQL_
Collations) foram originalmente implementados antes da conclusão do UTF-16 (em algum momento de 2000, acredito). Os nãoSQL_
-Agrupamentos que possuem_90_
ou_100_
em seus nomes, mas não_SC
possuem suporte mínimo para Caracteres Suplementares em termos de comparação e classificação.NVARCHAR
/NCHAR
/XML
/NTEXT
porque UCS-2 e UTF-16 são exatamente as mesmas sequências de bytes. A única diferença é que o UTF-16 usa 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 para as funções internas como dois caracteres desconhecidos.Com essas informações básicas em mente, agora podemos passar pelas perguntas específicas:
Isso só pode acontecer se o banco de dados atual — onde a consulta está sendo executada — tiver um Collation padrão com reconhecimento de caracteres suplementares e aqueles que foram introduzidos no SQL Server 2012. Funções internas que possuem parâmetros de entrada de string podem ter o Collation fornecido inline através da
COLLATE
cláusula (ieLEN(N'string' COLLATE Some_Collation_SC)
) e não precisa ser executado dentro de um Banco de Dados que tenha um Collation padrão 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 (e é por isso queNCHAR()
suporta apenas caracteres suplementares quando o banco de dados atual tem um agrupamento padrão que reconhece caracteres complementares; mas isso é desnecessário inconveniente que pode ser alterado, então vote na minha sugestão:A função NCHAR() deve sempre retornar Caractere Suplementar para 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
NCHAR
é a única função interna que tem problemas com caracteres suplementares (quando não está 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ê for para o segundo link postado na pergunta (ou seja, "Informações de agrupamento de caracteres suplementares 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, a partir do SQL Server 2012, você pode usar a seguinte consulta:
Sua consulta foi fechada, mas o padrão iniciado com
SQL
e os agrupamentos do SQL Server (ou seja, aqueles que começam comSQL_
) foram preteridos por um tempo em favor dos agrupamentos do Windows (aqueles que não iniciam comSQL_
). 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 explica isso, além de pegar os_UTF8
agrupamentos adicionados no SQL Server 2019).Não, você não pode instalar Collations em uma versão anterior do SQL Server.
Quando não estiver usando um agrupamento SCA, você pode 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 caracteres suplementares/pares substitutos funcionarão mesmo se o agrupamento efetivo for compatível com caracteres suplementares e deve funcionar da mesma forma em todas as versões do SQL Server, pelo menos até 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 Code Point entre 65536 - 1114111 (0x010000 - 0x10FFFF). E, enquanto o parâmetro de entrada é do tipoINT
, você pode passar no formato binário / hexadecimal do Code Point e ele será convertido implicitamente 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 agora retornar 188.657 pontos de código para que você não precise ajustar nenhum valor específico. Claro, 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. E inclui colunas adicionais com sequências de escape pré-formatadas para construir cada código point (tanto BMP quanto caracteres suplementares) em T-SQL (sem exigir um agrupamento "_SC
" ou "_140_
"), HTML (e XML), o estilo comum a muitas linguagens de aplicativos ("\uHHHH" ; usado para C++ / C# / F# / Java / JavaScript / Julia / etc), e finalmente o um pouco mais novo, outro estilo comum que lida com todos os pontos de código, não apenas BMP ("\UHHHHHHHH" ; usado para C / C++ / C# / F# / Julia / etc).Leia tudo sobre isso aqui:
Dica 3 do SSMS: acesse/pesquise facilmente TODOS os caracteres Unicode (sim, incluindo emojis ?)