Problema di codifica con la colonna VARCHAR di SQL Server recuperata in Python


10

Di recente abbiamo riscontrato un problema con la codifica correlata a un campo archiviato come varchar (120) in SQL Server. In SSMS, varchar appare come:

"Chi ha ucciso JonBen?"

Tuttavia, quando viene portato in Python, appare come:

inserisci qui la descrizione dell'immagine

Ho studiato questo dal lato Python e non sta succedendo niente di strano. La mia teoria è che varchar in SQL Server accetta caratteri UTF-8 che vengono visualizzati in modo diverso in Python rispetto a SSMS. Non ho molta familiarità con la codifica in SQL Server. Qualcuno può farmi sapere quanto segue:

  • Esiste un modo in SSMS per visualizzare la codifica del varchar? Ad esempio, vedi \ x82 invece di visualizzare la virgola come è attualmente da SSMS?
  • Stiamo utilizzando SQL Server 2008. Esiste un modo per modificare la codifica di caratteri UTF-8 in caratteri ASCII senza utilizzare strumenti di importazione / esportazione o scaricare in un file flat? Cioè posso fare questa conversione tramite una query?
  • Esiste un modo per identificare a livello di programmazione record problematici tramite una query (la problematica è definita come caratteri UTF-8 che non sono supportati tramite ASCII)?

Grazie in anticipo!

Utilizzando sp_help N'table_name';ho scoperto che il confronto di questa VARCHARcolonna è: SQL_Latin1_General_CP1_CI_AS.


Quale collation sta VARCHARusando quella colonna?
Solomon Rutzky,

@SolomonRutzky come si controlla il confronto. Non sono sicuro di cosa significhi
Eric

Il modo più veloce che penso è: sp_help N'table_name';. Guarda la colonna in base al "nome" e poi guarda la colonna "nome_collation".
Solomon Rutzky,

@SolomonRutzky le regole di confronto per quel campo sono "SQL_Latin1_General_CP1_CI_AS"
Eric

Risposte:


17

SQL Server non archivia UTF-8 in nessun caso. Puoi ottenere UTF-16 Little Endian (LE) tramite NVARCHAR(incluso NCHARe NTEXT, ma non usare mai NTEXT) e XML, o qualche codifica a 8 bit, basato su una pagina di codice, tramite VARCHAR(incluso CHARe TEXT, ma non usare mai TEXT) .

Il problema qui è che il tuo codice sta traducendo male quel carattere 0x82, pensando che sia UTF-8, ma non lo è. Non esiste un "carattere" UTF-8 con un valore di 0x82, motivo per cui viene visualizzato il simbolo "sconosciuto" / sostitutivo di " ". Vedere la seguente tabella UTF-8 che mostra che non esiste alcun carattere per un singolo byte di 0x82:

Tabella di codifica UTF-8

Come affermato dall'OP, il confronto della colonna in questione è SQL_Latin1_General_CP1_CI_AS, il che significa che la codifica a 8 bit utilizza il codice pagina 1252, che è Windows Latin 1 (ANSI) . E controllando quel grafico (scorrere verso il basso fino al grafico inferiore in quanto ha i nomi dei caratteri) il valore 0x82 (cercare "82" nella colonna "Punto codice") è in realtà il segno di virgolette Single-9 basso che vedi in SSMS. Quel carattere, in UTF-8, è una sequenza di 3 byte: E2 80 9A.

Ciò significa tutto ciò: il codice Python deve impostare la codifica client per la connessione SQL Server su Code Page 1252 oppure è necessario modificare / convertire la codifica della stringa restituita da Code Page 1252 a UTF-8.

Naturalmente, se questo viene visualizzato su una pagina Web, è possibile modificare il set di caratteri dichiarato della pagina in modo che sia Windows-1252, ma ciò potrebbe interferire con altri caratteri nella pagina se ci sono già caratteri UTF-8.


Bello, questo è molto utile, grazie Solomon. Per favore fatemi sapere sulla traduzione. Questo è un problema piuttosto complicato e non sono nemmeno sicuro da dove cominciare.
Eric

Caspita, dettaglio incredibile, @ Salomone! Sono atterrato qui alla ricerca di un diverso problema Python + MS SQL, ma ho continuato a leggere perché stavo imparando così tanto. :-P
Mike Williamson,

1
@MikeWilliamson Grazie per aver condiviso quel complimento :). Potresti anche essere interessato a quanto segue: Hash TSQL md5 diverso da C # .NET md5 (su SO), How To Strip Hebrew Accent Marks (qui su DBA.SE) e Collations.Info . Godere!
Solomon Rutzky,

Grazie! Sospetto che chiunque lavori con una lingua non latina conosca queste cose molto meglio di chiunque di noi lavori beato negli Stati Uniti / nel Regno Unito. :)
Mike Williamson,

1
Solo una nota: MS SQL Server 2019 introduce il supporto nativo per UTF-8 nei tipi di dati VARCHAR / CHAR.
Gregory Arenius,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.