Masalah pengodean dengan SQL Server VARCHAR kolom diambil dalam Python

10

Kami baru-baru ini memiliki masalah dengan pengkodean yang terkait dengan bidang yang disimpan sebagai varchar (120) di SQL Server. Dalam SSMS, varchar muncul sebagai:

"Siapa yang membunuh JonBen‚t?"

Namun, ketika dibawa ke python, muncul sebagai:

masukkan deskripsi gambar di sini

Saya telah meneliti ini dari sisi Python, dan tidak ada yang aneh terjadi. Teori saya adalah bahwa varchar di SQL Server menerima karakter UTF-8 yang menampilkan berbeda dalam python daripada SSMS. Saya tidak terlalu terbiasa dengan pengkodean dalam SQL Server. Dapatkah seseorang tolong beri tahu saya hal berikut:

  • Apakah ada cara di SSMS untuk melihat pengkodean varchar? Misalnya, lihat \ x82 alih-alih menampilkan koma seperti saat ini dari SSMS?
  • Kami menggunakan SQL Server 2008. Apakah ada cara untuk mengubah pengkodean untuk karakter UTF-8 menjadi karakter ASCII tanpa menggunakan alat impor / ekspor atau membuang ke file datar? Yaitu bisakah saya melakukan konversi ini melalui kueri?
  • Apakah ada cara untuk secara sistematis mengidentifikasi catatan yang bermasalah melalui kueri (bermasalah didefinisikan sebagai karakter UTF-8 yang tidak didukung melalui ASCII)?

Terima kasih sebelumnya!

Menggunakan sp_help N'table_name';saya menemukan bahwa Terbit ini VARCHARkolom adalah: SQL_Latin1_General_CP1_CI_AS.

Eric
sumber
Apa Collation yang VARCHARdigunakan kolom itu?
Solomon Rutzky
@ SolomonRutzky bagaimana Anda memeriksa pemeriksaan. Saya tidak yakin apa artinya itu
Eric
Cara tercepat saya pikir adalah: sp_help N'table_name';. Lihat kolom berdasarkan "nama" dan kemudian lihat kolom "collation_name".
Solomon Rutzky
@SolomonRutzky susunan untuk bidang itu adalah 'SQL_Latin1_General_CP1_CI_AS'
Eric

Jawaban:

17

SQL Server tidak menyimpan UTF-8 dalam kondisi apa pun. Anda mendapatkan UTF-16 Little Endian (LE) melalui NVARCHAR(termasuk NCHARdan NTEXT, tetapi jangan pernah menggunakan NTEXT) dan XML, atau penyandian 8-bit, berdasarkan pada Halaman Kode, melalui VARCHAR(termasuk CHARdan TEXT, tetapi jangan pernah menggunakan TEXT) .

Masalahnya di sini adalah bahwa kode Anda salah menerjemahkan karakter 0x82 itu, berpikir bahwa itu adalah UTF-8, tetapi sebenarnya tidak. Tidak ada "karakter" UTF-8 yang memiliki nilai 0x82, itulah sebabnya Anda mendapatkan simbol "tidak dikenal" / pengganti " ". Silakan lihat tabel UTF-8 berikut ini yang menunjukkan bahwa tidak ada karakter untuk byte tunggal 0x82:

Tabel pengkodean UTF-8

Sebagaimana dinyatakan oleh OP, Collation dari kolom yang dimaksud adalah SQL_Latin1_General_CP1_CI_AS, yang berarti bahwa pengkodean 8-bit menggunakan Kode 1252, yang merupakan Windows Latin 1 (ANSI) . Dan memeriksa bagan itu (gulir ke bawah ke bagan bawah karena memiliki nama karakter) nilai 0x82 (cari "82" di kolom "Kode Titik") sebenarnya adalah Tanda Kutip Rendah-9 Tunggal yang Anda lihat di SSMS. Karakter yang, dalam UTF-8, merupakan urutan 3 byte: E2 80 9A.

Apa artinya semua ini: kode Python Anda perlu mengatur pengkodean klien untuk koneksi SQL Server ke Kode Page 1252, atau Anda perlu mengubah / mengubah pengkodean string yang dikembalikan dari Kode Page 1252 ke UTF-8.

Tentu saja, jika ini sedang ditampilkan pada halaman web, maka Anda dapat mengubah charset yang dideklarasikan dari halaman menjadi Windows-1252, tetapi itu mungkin mengganggu dengan karakter lain pada halaman jika ada karakter UTF-8 sudah ada di sana.

Solomon Rutzky
sumber
Bagus, ini sangat membantu, terima kasih Solomon. Tolong beri tahu saya tentang kesalahan penerjemahan. Ini adalah masalah yang cukup rumit dan saya bahkan tidak yakin harus mulai dari mana.
Eric
Wow, detail luar biasa, @Solomon! Saya mendarat di sini mencari masalah Python + MS SQL yang berbeda, tetapi terus membaca karena saya belajar banyak. :-P
Mike Williamson
1
@MikeWilliamson Terima kasih telah berbagi pujian itu :). Anda mungkin juga tertarik pada yang berikut ini: hash TSQL md5 berbeda dengan C # .NET md5 (di SO), Cara Melucuti Tanda Aksen Bahasa Ibrani (di sini di DBA.SE), dan Collations.Info . Nikmati!
Solomon Rutzky
Terima kasih! Saya menduga siapa pun yang bekerja dengan bahasa non-Latin tahu hal ini jauh lebih baik daripada kita yang bekerja di AS / Inggris. :)
Mike Williamson
1
Sekedar catatan: MS SQL Server 2019 memperkenalkan dukungan asli untuk UTF-8 dalam tipe data VARCHAR / CHAR.
Gregory Arenius