Eu preciso inserir este caractere '●' em uma VARCHAR
coluna de um banco de dados MSSQL com agrupamento definido como SQL_Latin1_General_CP1_CI_AS
(ou pelo menos simular o que meu driver Python + Windows MSSQL pode ter feito). Eu tentei inserir isso do meu cliente, mas ele é inserido como ?
.
O valor hexadecimal verificado no Python \xe2\x97\x8f
é o binário 226, 151, 143.
A especificação de agrupamento diz que 226 está definido, mas 143 e 151 estão indefinidos. Então, o meu melhor seria inserir 226?
A razão pela qual estou fazendo este exercício é que nosso aplicativo estava inserindo esse caractere no banco de dados anteriormente. Neste ponto, não sei como entrou porque, mas passou por um aplicativo Python com Windows MSSQL Driver e nossa equipe de banco de dados escreveu um script para corrigi-lo e aparentemente foi substituído por "?".
Agora estou apenas tentando reproduzir esse cenário para perguntar por que ele está sendo substituído por "?" porque estamos substituindo-o como vazio no App. Como meu aplicativo já tem uma correção para esse problema (removemos qualquer coisa maior que 127), estou tentando zombar disso diretamente do back-end para provar que ele está sendo substituído por '?' que na verdade é minha reivindicação e acho que é feito porque diz "COLLATE" na consulta de atualização.
UPDATE pr_response
SET nur_respon =
REPLACE (nur_respon,
SUBSTRING(nur_respon, PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon), 1),
'')
WHERE PATINDEX('%[^ !-~]%' COLLATE Latin1_General_BIN, nur_respon) > 0
Este é um bom script para remover dados não ASCII > 127? Alguém pode explicar essa consulta em inglês simples?
Não, o aplicativo não estava inserindo esse caractere ( Black Circle U+25CF ) em uma
VARCHAR
coluna usando um[SQL_]Latin1_General...
Collation. Latin1_General Collations usam a página de código 1252 que não possui esse caractere, nem parece haver um mapeamento "melhor ajuste" para convertê-lo em algo semelhante.Esse caractere existe em algumas páginas de código, como as usadas pelos agrupamentos coreano e japonês, como mostram as consultas a seguir (ambos são conjuntos de caracteres de byte duplo, razão pela qual a conversão para
VARBINARY
mostra dois bytes em vez de um):É possível, no entanto, que o aplicativo estivesse inserindo '•' ( Bullet U+2022 ), que parece bastante semelhante, apenas um pouco menor. O caractere "Bullet" está disponível na página de código 1252 (dez 149 ou hexadecimal 0x95).
Bem, substituindo "●" por "?" não soa como consertá-lo ;-).
Independentemente dos aspectos técnicos, parece bastante óbvio que ambas as declarações não podem ser verdadeiras ao mesmo tempo: não podem ser substituídas por "?" e seja removido antes de atingir o SQL Server. Claramente o código do aplicativo não tem uma correção para isso e não está removendo tudo com um valor acima de 127. Ele está sendo convertido em "?" no SQL Server porque esse caractere está sendo inserido ainda não existe na página de código 1252.
Não, forçar um Collation binário através da
COLLATE
palavra-chave não está mudando este caractere para "?". Tanto o Collation ( ) da coluna quanto o Collation (SQL_Latin1_General_CP1_CI_AS
) explícitoLatin1_General_BIN
usam a página de código 1252, portanto, nenhum caractere pode ser alterado devido a isso.O caractere "●" está sendo substituído por "?" conforme ele está sendo inserido na
VARCHAR
coluna. E uma vez inserido como um ponto de interrogação, não há nada para limpar e nenhuma maneira de identificar esse ponto de interrogação como sendo originalmente de outra coisa, em oposição a um ponto de interrogação pretendido.Essa consulta encontra todas as ocorrências de caracteres com um valor ASCII maior que 127 (é isso que
PATINDEX
faz) e, em seguida, obtém qualquer caractere (é isso queSUBSTRING
faz) e substitui todas as ocorrências desse caractere na coluna por vazio string (isso é o que oREPLACE
faz). A consulta não faz nadaUPDATE
se nenhum caractere for encontrado com um valor ASCII acima de 127.Esta consulta só funciona em um caractere por vez. Portanto, se uma coluna tiver 2 ou mais caracteres com valores ASCII acima de 127 que não sejam o mesmo valor ASCII, o script precisará ser executado várias vezes.
Essa consulta não ajudará neste caso específico (ou seja, de substituir "●" por "?"), pois essa conversão está ocorrendo no caminho. Essa consulta lida apenas com caracteres com valores ASCII de 128 a 255, mas "●" não é um desses caracteres, pois nunca poderia estar nesta coluna em primeiro lugar.