Terjemahan Otomatis ketika Mengubah Unicode menjadi non-Unicode / NVARCHAR ke VARCHAR

8

Titik kode Unicode 9619 adalah karakter yang disebut "Naungan gelap": ( http://unicode-table.com/en/search/?q=9619 ).

Menggunakan SQL_Latin1_General_CP1_CI_AShalaman kode collation dan 1252, saya akan berharap bahwa casting / konversi karakter Unicode ke tipe data non-Unicode akan menghasilkan tanda tanya ( ?) karena kode halaman 1252 tampaknya tidak mengandung karakter ini dan ini tampaknya SQL Server perilaku saat konversi tidak dapat dilakukan.

Jadi pertanyaan saya adalah: mengapa SQL Server mengubah karakter ini menjadi kode ASCII 166 yang merupakan "Pipa, Rusak batang vertikal" ¦:?

SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))
Henry Lee
sumber
3
SQL Server menggunakan apa yang makalah ini sebut sebagai transformasi homoglyphic dan seringkali mengonversi karakter yang tidak dapat direpresentasikan menjadi hampir setara. Seperti kehilangan aksen pada karakter atau mengubah kutipan pintar menjadi kutipan sederhana. Saya setuju itu tidak terlihat terlalu dekat! Saya tidak yakin apakah atau di mana transformasi ini didokumentasikan.
Martin Smith
Wow, tidak tahu ... ya ampun, sepertinya tidak benar ... itu bukan karakter yang sama. Mengapa tidak hanya "... oops, tidak ada karakter seperti itu ditemukan di halaman kode ini ..." dan gagal konversi?
Henry Lee
1
Cukup baca halaman ini dan ingat ini. Tidak yakin apakah SQL Server menggunakan algoritma "paling cocok" yang sama persis.
Martin Smith
1
@ MartinSmith mengenai tidak yakin pemetaan "paling cocok" untuk SQL Server, silakan lihat jawaban saya di bawah ini ketika saya menemukan pemetaan itu :-).
Solomon Rutzky

Jawaban:

8

Mengapa SQL mengubah Unicode 9619 ke kode ASCII 166?

SQL Server tidak menggunakan logika khusus khusus di sini; itu menggunakan layanan sistem operasi standar untuk melakukan konversi.

Secara khusus, SQL Server jenis dan layanan ekspresi ( sqlTsEs) panggilan ke rutinitas OS WideCharToMultiBytedi kernel32.dll. SQL Server mengatur parameter input WideCharToMultiBytesedemikian rupa sehingga rutin melakukan 'terjemahan cepat'. Ini lebih cepat daripada meminta karakter default tertentu digunakan ketika tidak ada terjemahan langsung.

Terjemahan cepat bergantung pada halaman kode target untuk melakukan pemetaan paling cocok untuk setiap karakter yang tidak cocok, seperti yang disebutkan dalam tautan Martin Smith yang disediakan dalam komentar untuk pertanyaan:

Strategi paling cocok bervariasi untuk halaman kode yang berbeda, dan mereka tidak didokumentasikan secara rinci.

Ketika parameter input ditetapkan untuk terjemahan cepat, WideCharToMultiBytepanggil layanan OS GetMBNoDefault( sumber ). Memeriksa tumpukan panggilan SQL Server ketika melakukan konversi yang ditentukan dalam pertanyaan mengkonfirmasi ini:

Jejak tumpukan SQL Server

Paul White 9
sumber
7

Konversi dari data Unicode ke Halaman Kode tertentu menggunakan apa yang dikenal sebagai strategi "Paling Cocok" (seperti yang tercantum dalam jawaban @ Paul dan di tautan yang dicatat oleh @Martin dalam komentar pada Pertanyaan). Menurut halaman MSDN untuk Pengodean Karakter di .NET Framework :

Pemetaan paling cocok adalah perilaku default untuk objek Pengkodean yang menyandikan data Unicode ke dalam data halaman kode ...

Tapi apa sebenarnya pemetaan ini? Halaman MSDN yang digunakan untuk menyatakan sebagai berikut:

Strategi paling cocok bervariasi untuk halaman kode yang berbeda, dan mereka tidak didokumentasikan secara rinci.

Namun, itu tidak sepenuhnya benar. Mungkin "strategi" untuk menentukan pemetaan tidak terdokumentasi dengan tepat. Baik. Tapi, pemetaan sendiri yang didokumentasikan, hanya saja tidak dalam termudah tempat untuk menemukan.

Jadi, berkat Microsoft memindahkan dokumentasi ke GitHub, halaman itu sekarang menyatakan yang berikut (karena saya memperbaruinya 😸):

Strategi terbaik tidak didokumentasikan secara rinci. Namun, beberapa halaman kode didokumentasikan di situs web Konsorsium Unicode . Harap tinjau file readme.txt di folder itu untuk deskripsi cara menafsirkan file pemetaan.

Jika Anda membuka URL berikut, Anda akan melihat daftar beberapa file, masing-masing diberi nama untuk Halaman Kode yang memetakan karakter Unicode ke:

ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/

Sebagian besar file terakhir diperbarui (atau setidaknya ditempatkan di sana) pada 2006-10-04, dan salah satunya diperbarui pada 2012-03-14. Bagian pertama dari file-file tersebut memetakan kode ASCII ke dalam Unicode Code Point yang setara. Tetapi bagian kedua dari setiap file memetakan karakter Unicode ke "padanan" ASCII mereka.

Saya menulis skrip pengujian yang menggunakan pemetaan Kode untuk memeriksa apakah SQL Server benar-benar menggunakan pemetaan tersebut. Itu dapat ditentukan dengan menjawab dua pertanyaan ini:

  1. Untuk semua Poin Kode yang dipetakan, apakah SQL Server mengubahnya menjadi pemetaan yang ditentukan?
  2. Untuk semua Poin Kode yang belum dipetakan, apakah SQL Server mengonversinya menjadi karakter bukan " ?"?

Script tes terlalu panjang untuk ditempatkan di sini, jadi saya mempostingnya di Pastebin di:

Pemetaan Unicode ke Halaman Kode di SQL Server

Menjalankan skrip akan menunjukkan bahwa jawaban untuk pertanyaan pertama di atas adalah "Ya" (artinya semua pemetaan yang disediakan dipatuhi). Ini juga akan menunjukkan bahwa jawaban untuk pertanyaan kedua adalah "Tidak" (artinya, tidak ada Poin Kode yang tidak dipetakan yang dikonversi menjadi apa pun selain karakter untuk "tidak dikenal"). Karenanya, file pemetaan itu sangat akurat :-).

Solomon Rutzky
sumber