Problème de codage avec la colonne SQL Server VARCHAR récupéré en Python


10

Nous avons récemment rencontré un problème avec l'encodage lié à un champ qui est stocké en tant que varchar (120) dans SQL Server. Dans SSMS, le varchar apparaît comme:

"Qui a tué JonBen‚t?"

Cependant, quand il est introduit en python, il apparaît comme:

entrez la description de l'image ici

J'ai fait des recherches sur le côté Python, et rien d'étrange ne se passe. Ma théorie est que le varchar dans SQL Server accepte les caractères UTF-8 qui s'affichent différemment en python que SSMS. Je ne suis pas très familier avec l'encodage dans SQL Server. Quelqu'un peut-il me faire savoir ce qui suit:

  • Existe-t-il un moyen dans SSMS de visualiser l'encodage du varchar? Par exemple, voyez \ x82 au lieu d'afficher la virgule telle qu'elle est actuellement issue de SSMS?
  • Nous utilisons SQL Server 2008. Existe-t-il un moyen de changer l'encodage de n'importe quel caractère UTF-8 en caractères ASCII sans utiliser d'outils d'importation / exportation ou de vidage dans un fichier plat? Est-ce que je peux faire cette conversion via une requête?
  • Existe-t-il un moyen d'identifier par programme les enregistrements problématiques via une requête (le problème étant défini comme des caractères UTF-8 qui ne sont pas pris en charge via ASCII)?

Merci d'avance!

L' utilisation sp_help N'table_name';je trouve que la Collation de cette VARCHARcolonne est: SQL_Latin1_General_CP1_CI_AS.


Quel classement cette VARCHARcolonne utilise-t-elle?
Solomon Rutzky

@SolomonRutzky comment vérifiez-vous le classement. Je ne sais pas ce que cela signifie même
Eric

Le moyen le plus rapide que je pense est: sp_help N'table_name';. Regardez la colonne basée sur "nom", puis regardez la colonne "nom_classement".
Solomon Rutzky

@SolomonRutzky le classement pour ce champ est 'SQL_Latin1_General_CP1_CI_AS'
Eric

Réponses:


17

SQL Server ne stocke en aucun cas UTF-8. Vous obtenez soit UTF-16 Little Endian (LE) via NVARCHAR(y compris NCHARet NTEXT, mais n'utilisez jamais NTEXT) et XML, ou un encodage 8 bits, basé sur une page de codes, via VARCHAR(y compris CHARet TEXT, mais n'utilisez jamais TEXT) .

Le problème ici est que votre code traduit mal ce caractère 0x82, pensant que c'est UTF-8, mais ce n'est pas le cas. Il n'y a pas de "caractère" UTF-8 ayant une valeur de 0x82, c'est pourquoi vous obtenez le symbole "inconnu" / remplacement de " ". Veuillez consulter le tableau UTF-8 suivant qui montre qu'il n'y a pas de caractère pour un octet unique de 0x82:

Table de codage UTF-8

Comme indiqué par l'OP, le classement de la colonne en question est SQL_Latin1_General_CP1_CI_AS, ce qui signifie que le codage 8 bits utilise la page de codes 1252, qui est Windows Latin 1 (ANSI) . Et la vérification de ce graphique (faites défiler jusqu'au graphique inférieur car il a les noms de caractères) valeur 0x82 (recherchez "82" dans la colonne "Point de code") est en fait le guillemet simple à faible 9 que vous voyez dans SSMS. Ce caractère, en UTF-8, est une séquence de 3 octets: E2 80 9A.

Cela signifie: votre code Python doit définir l'encodage client pour la connexion SQL Server à la page de codes 1252, ou vous devez modifier / convertir l'encodage de la chaîne renvoyée de la page de codes 1252 à UTF-8.

Bien sûr, si cela est affiché sur une page Web, vous pouvez modifier le jeu de caractères déclaré de la page Windows-1252, mais cela pourrait interférer avec d'autres caractères de la page s'il y a déjà des caractères UTF-8.


Bien, c'est très utile, merci Salomon. Veuillez me faire part de la mauvaise traduction. C'est un problème assez délicat et je ne sais même pas par où commencer.
Eric

Wow, détail incroyable, @Solomon! J'ai atterri ici à la recherche d'un autre problème Python + MS SQL, mais j'ai continué à lire parce que j'apprenais tellement. :-P
Mike Williamson

1
@MikeWilliamson Merci d'avoir partagé ce compliment :). Vous pourriez également être intéressé par les éléments suivants: Hachage TSQL md5 différent de C # .NET md5 (sur SO), Comment supprimer les marques d'accent hébreu (ici sur DBA.SE) et Collations.Info . Prendre plaisir!
Solomon Rutzky

Merci! Je soupçonne que toute personne travaillant avec une langue non latine connaît ce truc bien mieux que n'importe lequel d'entre nous qui travaille béatement aux États-Unis et au Royaume-Uni. :)
Mike Williamson

1
Juste une note: MS SQL Server 2019 introduit la prise en charge native d'UTF-8 dans les types de données VARCHAR / CHAR.
Gregory Arenius
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.