ทำไมเราต้องใส่ N ก่อนสตริงใน Microsoft SQL Server


34

ฉันเรียนรู้ T-SQL จากตัวอย่างที่ฉันเห็นการแทรกข้อความในvarchar()เซลล์ฉันสามารถเขียนเฉพาะสตริงที่จะแทรก แต่สำหรับnvarchar()เซลล์ตัวอย่างทุก ๆ คำนำหน้าสตริงด้วยตัวอักษร N

ฉันลองใช้แบบสอบถามต่อไปนี้บนตารางที่มีnvarchar()แถวและทำงานได้ดีดังนั้นคำนำหน้า N จึงไม่จำเป็น:

insert into [TableName] values ('Hello', 'World')

เหตุใดสตริงจึงถูกนำหน้าด้วย N ในทุกตัวอย่างที่ฉันเห็น

ข้อดีหรือข้อเสียของการใช้คำนำหน้านี้คืออะไร


N ไม่จำเป็นสำหรับสายอักขระตามตัวอักษรเท่านั้นหรือ
Wayne In Yak

โปแลนด์เป็นภาษาที่ไม่ใช่ภาษาละติน ????
Heckflosse_230

2
Nหมายถึง National เช่นเดียวกับใน "National Varying Character" โปรดดูชนิดข้อมูล ANSI SQL ที่เทียบเท่ากัน
ErikE

ฉันเห็นด้วยกับคำถามนี้และไม่มีใครตอบได้ AFAICT บางทีมันอาจจะปรับปรุงใหม่ว่า“ทำไมมันไม่ดีที่จะให้ SQL โดยปริยายแปลงของฉันVARCHARไปNVARCHARเมื่อตัวอักษรสตริงของฉันคือ ASCII?”
binki

คำถามนี้ถูกถามและตอบแล้วที่นี่: ความแตกต่างระหว่าง varchar และ nvarchar คืออะไร?

คำตอบ:


27

NVarchar ใช้สำหรับ Unicode หากฐานข้อมูลของคุณไม่ได้จัดเก็บข้อมูลหลายภาษาคุณสามารถใช้ Varchar ต่อไปได้ ตัวอย่างเช่น: N'abc'เพียงแปลงสตริงของคุณเป็นยูนิโค้ด


2
ทำไมคุณไม่ต้องขึ้นต้นด้วย U แทน N ในตอนนั้น?
อัตติลาคุน

คุณอาจสับสนสำหรับผู้ที่ไม่ได้ลงนามเพื่อคาดเดา
JB King

U&'abc'เป็นวิธีที่ถูกต้องในการระบุสตริง Unicode ดูSQL 2003 BNF
ceving

2
ตัว N หมายถึงชุดของ "National Language Character"
Mike Bovenlander

23

โดยเซิร์ฟเวอร์ SQL เริ่มต้นใช้งาน Windows 1252รหัสตัวอักษรสำหรับvarchar มันมีตัวละครส่วนใหญ่สำหรับภาษาที่ใช้ภาษาละติน (อังกฤษ, เยอรมัน, ฝรั่งเศส, ฯลฯ ) แต่ไม่มีตัวอักษรสำหรับภาษาที่ไม่ใช่ละติน (โปแลนด์, รัสเซีย, ฯลฯ ) ตามที่ระบุโดย @Pieter B จะใช้ nvarchar เพื่อแก้ไขปัญหานั้นเพราะใช้สำหรับUnicodeซึ่งมีอักขระที่หายไป สิ่งนี้มาพร้อมกับค่าใช้จ่ายมันใช้พื้นที่ในการจัดเก็บ nvarchar มากกว่า varchar สองเท่า

การใส่ N ด้านหน้าสตริงของคุณจะทำให้แน่ใจว่าอักขระถูกแปลงเป็น Unicode ก่อนที่จะถูกวางลงในคอลัมน์ nvarchar เวลาส่วนใหญ่คุณจะโอเคที่จะออกจาก N แต่ฉันจะไม่แนะนำ มันดีกว่าที่จะปลอดภัยกว่าขออภัย


3
เพียงชี้แจง: "โดยค่าเริ่มต้น" เซิร์ฟเวอร์ SQL ใช้การเข้ารหัสที่สอดคล้องกับการเปรียบเทียบของเขตข้อมูล Varchar ซึ่ง overridable ในเวลาที่สร้างสนามโดยทั่วไปขึ้นอยู่กับการเปรียบเทียบเริ่มต้นสำหรับอินสแตนซ์ของคุณ การเปรียบเทียบค่าเริ่มต้นสำหรับอินสแตนซ์ของคุณสามารถตั้งค่าได้ในเวลาติดตั้ง แต่โดยทั่วไปจะสอดคล้องกับ CP_ACP ของโลแคลเริ่มต้นของระบบ นั่นจะเป็น Windows 1252 บนเครื่อง US-English แต่ 932 บนเครื่องที่มีระบบภาษาญี่ปุ่น 1251 บนเครื่องรัสเซีย ฯลฯ คุณธรรมของเรื่องราวหรือไม่ ใช้ NVarchar :)
JasonTrue

1
จนถึงตอนนี้เป็นคำตอบเดียวที่ตอบคำถามตามที่ถาม "เหตุใดจึงใช้คำนำหน้า N บนสตริงตัวอักษรเนื่องจาก SQL จะแปลงรหัสโดยปริยาย?" คำตอบอื่น ๆ ทั้งหมดสำหรับคำถามที่แตกต่าง "อะไรคือความแตกต่างระหว่าง nvarchar กับ varchar?"
Timbo

18

เนื่องจาก MS SQL Server รองรับ UTF-8 ได้ไม่ดีเมื่อเทียบกับ RDBMS อื่น

MS SQL Server เป็นไปตามข้อตกลงที่ใช้ภายใน Windows เองสตริง "แคบ" ( charใน C ++ CHARหรือVARCHARใน SQL) จะถูกเข้ารหัสในแบบดั้งเดิม "รหัสหน้า" ปัญหาของโค้ดเพจคือมีจำนวนอักขระ จำกัด (ส่วนใหญ่เป็นการเข้ารหัสแบบไบต์เดียวซึ่ง จำกัด จำนวนรายงานที่ 256 ตัวอักษร) และได้รับการออกแบบรอบ ๆ ภาษาเดียว (หรือกลุ่มของภาษาที่มีตัวอักษรที่คล้ายกัน) ทำให้การจัดเก็บข้อมูลหลายภาษาเป็นเรื่องยาก ตัวอย่างเช่นคุณไม่สามารถเก็บข้อมูลทั้งรัสเซียและภาษาฮิบรูเพราะหน้ารหัสใช้รัสเซีย1251และภาษาฮิบรูใช้รหัสหน้า1255

Unicodeแก้ปัญหานี้โดยการใช้ชุดอักขระที่มีรหัสขนาดยักษ์ตัวเดียวพร้อมห้องมากกว่าหนึ่งล้านตัวอักษรเพียงพอที่จะเป็นตัวแทนของทุกภาษาในโลก มีหลายรูปแบบการเข้ารหัส Unicode; ไมโครซอฟท์ชอบที่จะใช้UTF-16สำหรับเหตุผลทางประวัติศาสตร์ เนื่องจาก UTF-16 แสดงถึงสตริงเป็นลำดับของหน่วยรหัส 16 บิตแทน 8 บิตแบบดั้งเดิมจึงจำเป็นต้องใช้ประเภทอักขระแยกต่างหาก ใน MSVC ++ wchar_tนี้เป็น และใน MS SQL มันหรือNCHAR ย่อมาจาก "แห่งชาติ"ซึ่งดูเหมือนว่าข้างหลังกับผมเพราะเป็นเรื่องเกี่ยวกับ Unicode ระหว่าง -nationalization แต่ที่คำศัพท์มาตรฐาน ISONVARCHARN

การใช้ SQL อื่น ๆ ช่วยให้คุณเก็บข้อความUTF-8ไว้ในVARCHARคอลัมน์ UTF-8 คือการเข้ารหัสความยาวผันแปร (1-4 ไบต์ต่อตัวอักษร) ที่ปรับให้เหมาะกับกรณีเมื่อข้อมูลของคุณส่วนใหญ่อยู่ในช่วง Basic Latin (ซึ่งแสดงเป็น 1 ไบต์ต่ออักขระเหมือน ASCII) แต่สามารถแทนได้ อักขระ Unicode ใด ๆ ดังนั้นคุณจะหลีกเลี่ยงปัญหา "พื้นที่สองเท่า" ที่กล่าวถึงโดย bwalk2895

น่าเสียดายที่ MS SQL Server ไม่รองรับ UTF-8VARCHARดังนั้นคุณต้องใช้ UTF-16 แทน (และเปลืองเนื้อที่สำหรับข้อความ ASCII) ใช้หน้ารหัสที่ไม่ใช่ Unicode (และสูญเสียความสามารถในการแสดงอักขระต่างประเทศ) หรือเก็บ UTF-8 ในBINARYคอลัมน์ (และจัดการกับความไม่สะดวกเช่นฟังก์ชั่นสตริง SQL ทำงานไม่ถูกต้องหรือต้องดูข้อมูลในรูปแบบฐานสิบหกใน GUI DB manager ของคุณ)


1
ในรุ่นก่อนหน้านี้แล้ว SQL Server 2012 พวกเขาใช้การเข้ารหัส UCS-2 ซึ่งเป็น 2byte อย่างเคร่งครัด ในรุ่นที่ใหม่กว่าพวกเขาใช้ UTF-16 ซึ่งเป็นการแมปความยาวผันแปรได้ถึง 4bytes ต่อตัวอักษร (คล้ายกับ UTF-8 แต่เริ่มต้นที่ 2 ไบต์)
j123b567
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.