Problema de codificação com a coluna VARCHAR do SQL Server recuperada em Python

10

Recentemente, tivemos um problema com a codificação relacionada a um campo que está sendo armazenado como um varchar (120) no SQL Server. No SSMS, o varchar aparece como:

"Quem matou JonBen?"

No entanto, quando é trazido para python, ele aparece como:

insira a descrição da imagem aqui

Eu pesquisei isso do lado do Python, e nada de estranho está acontecendo. Minha teoria é que o varchar no SQL Server está aceitando caracteres UTF-8 que são exibidos de maneira diferente em python e SSMS. Não estou muito familiarizado com a codificação no SQL Server. Alguém pode me informar o seguinte:

  • Existe uma maneira no SSMS para exibir a codificação do varchar? Por exemplo, consulte \ x82 em vez de exibir a vírgula como atualmente é do SSMS?
  • Estamos usando o SQL Server 2008. Existe alguma maneira de alterar a codificação de caracteres UTF-8 para caracteres ASCII sem usar ferramentas de importação / exportação ou despejar em um arquivo simples? Ou seja, posso fazer essa conversão através de uma consulta?
  • Existe alguma maneira de identificar programaticamente registros problemáticos por meio de uma consulta (problema problemático sendo definido como caracteres UTF-8 que não são suportados pelo ASCII)?

Agradeço antecipadamente!

Usando sp_help N'table_name';descobri que o Agrupamento desta VARCHARcoluna é: SQL_Latin1_General_CP1_CI_AS.

Eric
fonte
Que agrupamento essa VARCHARcoluna está usando?
Solomon Rutzky 4/17/17
@SolomonRutzky como você verifica o agrupamento. Eu não tenho certeza o que isso significa mesmo
Eric
A maneira mais rápida eu acho que é: sp_help N'table_name';. Olhe para a coluna com base em "nome" e, em seguida, olhe para a coluna "collation_name".
Solomon Rutzky
@SolomonRutzky o agrupamento para esse campo é 'SQL_Latin1_General_CP1_CI_AS'
Eric

Respostas:

17

O SQL Server não armazena UTF-8 em nenhuma circunstância. Você obtém UTF-16 Little Endian (LE) via NVARCHAR(incluindo NCHARe NTEXT, mas nunca usa NTEXT) e XML, ou alguma codificação de 8 bits, com base em uma Página de Código, via VARCHAR(incluindo CHARe TEXT, mas nunca usa TEXT) .

O problema aqui é que seu código está traduzindo incorretamente esse caractere 0x82, pensando que é UTF-8, mas não é. Não existe um "caractere" UTF-8 com um valor de 0x82, e é por isso que você obtém o símbolo "desconhecido" / substituição de " ". Consulte a seguinte tabela UTF-8, que mostra que não há caracteres para um byte único de 0x82:

Tabela de codificação UTF-8

Conforme declarado pelo OP, o agrupamento da coluna em questão é SQL_Latin1_General_CP1_CI_AS, o que significa que a codificação de 8 bits está usando o Code Page 1252, que é o Windows Latin 1 (ANSI) . E verificar se o valor do gráfico (role para baixo até o gráfico inferior, pois possui os nomes dos caracteres) 0x82 (procure "82" na coluna "Ponto do código") é, de fato, o único ponto baixo-9 entre aspas que você vê no SSMS. Esse personagem, em UTF-8, é uma seqüência de 3 bytes: E2 80 9A.

O que tudo isso significa é: seu código Python precisa definir a codificação do cliente para a conexão do SQL Server com a Code Page 1252 ou você precisa alterar / converter a codificação da string retornada do Code Page 1252 para UTF-8.

Obviamente, se isso estiver sendo exibido em uma página da web, você poderá alterar o conjunto de caracteres declarado da página Windows-1252, mas isso poderá interferir com outros caracteres da página, se já houver caracteres UTF-8.

Solomon Rutzky
fonte
Bom, isso é muito útil, obrigado Salomão. Por favor, deixe-me saber sobre a tradução incorreta. Esta é uma questão bastante complicada e nem sei por onde começar.
Eric
Uau, detalhes incríveis, @Solomon! Cheguei aqui procurando um problema diferente em Python + MS SQL, mas continuei lendo porque estava aprendendo muito. :-P
Mike Williamson
11
@ MikeWilliamson Obrigado por compartilhar esse elogio :). Você pode também estar interessado no seguinte: TSQL md5 hash diferente de C # .NET md5 (no SO), Como remover marcas de acento hebraicas (aqui no DBA.SE) e Collations.Info . Desfrutar!
Solomon Rutzky
Obrigado! Suspeito que qualquer pessoa que trabalhe com um idioma que não seja em latim conhece essas coisas muito melhor do que qualquer um de nós trabalhando alegremente nos EUA / Reino Unido. :)
Mike Williamson
11
Apenas uma observação: o MS SQL Server 2019 apresenta suporte nativo para UTF-8 nos tipos de dados VARCHAR / CHAR.
Gregory Arenius