web-dev-qa-db-fra.com

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

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:

enter image description here

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 dans 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. Y a-t-il un moyen de changer l'encodage des caractères UTF-8 en ASCII caractères sans utiliser les outils d'importation/exportation ou de vidage dans un fichier plat? Ie puis-je 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!

En utilisant sp_help N'table_name'; J'ai trouvé que le classement de cette colonne VARCHAR est: SQL_Latin1_General_CP1_CI_AS.

10
Eric

SQL Server ne stocke en aucun cas UTF-8. Vous obtenez soit UTF-16 Little Endian (LE) via NVARCHAR (y compris NCHAR et NTEXT, mais n'utilisez jamais NTEXT) et XML, ou un codage 8 bits, basé sur une page de codes, via VARCHAR (y compris CHAR et 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 seul octet de 0x82:

table de codage UTF-8

Comme indiqué par l'O.P., 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 du bas car il a les noms de caractères) valeur 0x82 (recherchez "82" dans la colonne "Point de code") est en fait le Single Low-9 Quotation Mark = que vous voyez dans SSMS. Ce caractère, en UTF-8, est une séquence de 3 octets: E2 80 9A.

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

Bien sûr, si cela est affiché sur une page Web, vous pouvez changer le jeu de caractères déclaré de la page pour qu'il soit 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.

17
Solomon Rutzky