ปัญหาการเข้ารหัสกับคอลัมน์ SQL Server VARCHAR ที่ดึงมาใน Python


10

เมื่อเร็ว ๆ นี้เรามีปัญหาเกี่ยวกับการเข้ารหัสที่เกี่ยวข้องกับเขตข้อมูลที่ถูกเก็บเป็น varchar (120) ใน SQL Server ใน SSMS, varchar จะปรากฏเป็น:

"ใครฆ่า JonBen‚t"

อย่างไรก็ตามเมื่อมันถูกนำเข้าสู่ไพ ธ อนมันจะปรากฏเป็น:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันค้นคว้าจากด้าน Python แล้วไม่มีอะไรแปลก ๆ เกิดขึ้น ทฤษฎีของฉันคือ varchar ใน SQL Server ยอมรับอักขระ UTF-8 ซึ่งแสดงใน python แตกต่างจาก SSMS ฉันไม่คุ้นเคยกับการเข้ารหัสใน SQL Server มาก ใครช่วยได้โปรดแจ้งให้เราทราบต่อไปนี้:

  • มีวิธีใน SSMS เพื่อดูการเข้ารหัสของ varchar หรือไม่? ตัวอย่างเช่นดู \ x82 แทนที่จะแสดงเครื่องหมายจุลภาคเนื่องจากมาจาก SSMS หรือไม่
  • เรากำลังใช้ SQL Server 2008 มีวิธีใดในการเปลี่ยนการเข้ารหัสอักขระ UTF-8 ให้เป็นอักขระ ASCII โดยไม่ต้องใช้เครื่องมือนำเข้า / ส่งออกหรือทิ้งเป็นไฟล์แฟลตหรือไม่? คือฉันสามารถแปลงนี้ผ่านการสืบค้นได้ไหม
  • มีวิธีใดบ้างในการระบุเร็กคอร์ดที่มีปัญหาผ่านทางโปรแกรม (มีปัญหาถูกกำหนดเป็นอักขระ UTF-8 ที่ไม่สนับสนุนผ่าน ASCII)?

ขอบคุณล่วงหน้า!

ใช้sp_help N'table_name';ฉันพบว่าการเปรียบเทียบจากนี้คอลัมน์:VARCHARSQL_Latin1_General_CP1_CI_AS


VARCHARคอลัมน์นั้นใช้การจัดเรียงแบบใด
โซโลมอน Rutzky

@SolomonRutzky คุณตรวจสอบการจัดเรียงอย่างไร ฉันไม่แน่ใจว่ามันหมายถึงอะไร
Eric

วิธีคิดที่เร็วที่สุดคือ: sp_help N'table_name';. ดูคอลัมน์ตาม "ชื่อ" แล้วดูที่คอลัมน์ "collation_name"
โซโลมอน Rutzky

@SolomonRutzky การเปรียบเทียบสำหรับฟิลด์นั้นคือ 'SQL_Latin1_General_CP1_CI_AS'
Eric

คำตอบ:


17

SQL Server จะไม่เก็บ UTF-8 ไม่ว่าในกรณีใด ๆ คุณได้รับ UTF-16 Little Endian (LE) ผ่านNVARCHAR(รวมถึงNCHARและNTEXTแต่ไม่เคยใช้NTEXT) และXMLหรือการเข้ารหัส 8 บิตตามรหัสหน้าผ่านVARCHAR(รวมถึงCHARและTEXTแต่ไม่เคยใช้TEXT) .

ปัญหาที่นี่คือรหัสของคุณแปลผิดว่าตัวอักษร 0x82 คิดว่าเป็น UTF-8 แต่ไม่ใช่ ไม่มีตัวอักษร UTF-8 "ที่มีค่า 0x82 ซึ่งเป็นสาเหตุที่คุณได้รับสัญลักษณ์" ไม่ทราบ "/ การแทนที่" " โปรดดูตาราง UTF-8 ต่อไปนี้ซึ่งแสดงว่าไม่มีอักขระสำหรับไบต์เดียวขนาด 0x82:

ตารางการเข้ารหัส UTF-8

ดังกล่าวโดย OP การเปรียบเทียบของคอลัมน์ในคำถามคือSQL_Latin1_General_CP1_CI_ASซึ่งหมายความว่าการเข้ารหัส 8 บิตจะใช้หน้ารหัส 1252 ซึ่งเป็นของ Windows ละติน 1 (ANSI) และตรวจสอบแผนภูมินั้น (เลื่อนลงไปที่แผนภูมิด้านล่างเนื่องจากมีชื่อตัวอักษร) ค่า 0x82 (มองหา "82" ในคอลัมน์ "รหัสจุด") ในความเป็นจริงแล้วเครื่องหมายใบเสนอราคาต่ำเดี่ยว -9ที่คุณเห็นใน SSMS ตัวละครที่ใน UTF-8 เป็นลำดับที่ 3 E2 80 9Aไบต์:

ความหมายทั้งหมดนี้คืออะไร: รหัส Python ของคุณต้องตั้งค่าการเข้ารหัสไคลเอ็นต์สำหรับการเชื่อมต่อ SQL Server เป็นรหัสหน้า 1252 หรือคุณต้องเปลี่ยน / แปลงการเข้ารหัสของสตริงที่ส่งคืนจากรหัสหน้า 1252 เป็น UTF-8

แน่นอนหากมีการแสดงผลบนหน้าเว็บคุณสามารถเปลี่ยนชุดอักขระที่ประกาศไว้ของหน้าเป็นWindows-1252แต่อาจรบกวนตัวอักษรอื่น ๆ ในหน้าหากมี UTF-8 อักขระอยู่แล้ว


เยี่ยมมากนี่เป็นประโยชน์มากขอบคุณโซโลมอน โปรดแจ้งให้เราทราบเกี่ยวกับการแปลผิด นี่เป็นปัญหาที่ค่อนข้างยุ่งยากและฉันไม่แน่ใจด้วยซ้ำว่าจะเริ่มจากตรงไหน
Eric

ว้าวรายละเอียดที่น่าอัศจรรย์ @ โซโลมอน! ฉันลงจอดที่นี่เพื่อค้นหาปัญหา Python + MS SQL อื่น แต่อ่านต่อไปเพราะฉันเรียนรู้มากมาย :-P
Mike Williamson

1
@ MikeWilliamson ขอบคุณสำหรับการแบ่งปันคำชมนั้น :) นอกจากนี้คุณอาจจะสนใจในการดังต่อไปนี้: TSQL md5 กัญชาที่แตกต่างกันกับ C # .NET md5 (ในดังนั้น) วิธีการเปลื้องผ้าฮีบรูสำเนียง Marks (ที่นี่ใน DBA.SE) และCollations.Info สนุก!
โซโลมอน Rutzky

ขอบคุณ! ฉันทุกคนผู้ต้องสงสัยการทำงานกับภาษาที่ไม่ใช่ภาษาละตินตามรู้สิ่งนี้ไกลดีกว่าใด ๆ ของเราสุขสันต์ทำงานในสหรัฐฯ / อังกฤษ :)
Mike Williamson

1
เพียงทราบ: MS SQL Server 2019 แนะนำการสนับสนุนเนทีฟสำหรับ UTF-8 ในประเภทข้อมูล VARCHAR / CHAR
เกรกอรี่ Arenius
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.