ข้อแตกต่างระหว่าง char, nchar, varchar และ nvarchar ใน SQL Server คืออะไร?


622

ความหมายคือnvarcharอะไร

ความแตกต่างระหว่างคืออะไรchar, nchar, varcharและnvarcharใน SQL Server?

คำตอบ:


856

เพียงเพื่อล้าง ... หรือสรุป ...

  • ncharและnvarcharสามารถเก็บอักขระ Unicodeได้
  • charและไม่สามารถเก็บอักขระ Unicodeได้varchar
  • charและncharมีความยาวคงที่ซึ่งจะสำรองพื้นที่เก็บข้อมูลสำหรับจำนวนอักขระที่คุณระบุแม้ว่าคุณจะไม่ใช้พื้นที่ทั้งหมดจนหมด
  • varcharและnvarcharมีความยาวผันแปรได้ซึ่งจะใช้พื้นที่ว่างสำหรับอักขระที่คุณจัดเก็บเท่านั้น มันจะไม่จัดเก็บข้อมูลสำรองเหมือนcharncharหรือ

ncharและnvarcharจะใช้พื้นที่เก็บข้อมูลมากเป็นสองเท่าดังนั้นจึงควรใช้เฉพาะเมื่อคุณต้องการการสนับสนุนUnicode


15
char และ varchar ไม่ได้มีไว้สำหรับเก็บยูนิโค้ด แต่ด้วยเทคนิคการเข้ารหัสเพิ่มเติมและตรรกะพิเศษคุณสามารถใช้ฟิลด์ [var] char สำหรับการเก็บข้อมูลแบบ unicode ได้
Wim ten Brink

10
มันเป็นเรียงขึ้นหรือไม่ว่าn...รุ่นใช้เวลาถึงสองเท่าของพื้นที่จัดเก็บมากเป็นคำตอบที่แสดงของฉัน
มาร์ตินสมิ ธ

7
ข้อดีของการจองพื้นที่เก็บข้อมูลคืออะไร
mlissner

4
ในจุดสุดท้าย: การใช้ Unicode nchar และ nvarchar ยังดีกว่าในกรณีส่วนใหญ่การเรียงหน้าที่ดีกว่าความยืดหยุ่นสำหรับผู้ใช้ลบปัญหาความเข้ากันได้ในอนาคต และด้วยวิธีการที่พื้นที่เก็บข้อมูลไม่เป็นปัญหาสำหรับกรณีนี้เนื่องจากการใช้ collation ที่ไม่มี Unicode นั้นเป็นเรื่องยุ่งยากและอัตราความจำจะลดลงในอนาคต
Jaison Varghese

6
@ BenCaine ถ่าน (20) จะใช้ 20 ไบต์ (สมมติว่าการเปรียบเทียบ 8 บิต); varchar (20) จะใช้ len (ข้อมูล) +2 ไบต์เช่น 22 สำหรับ 20 ไบต์ของข้อมูล แต่เพียง 12 สำหรับ 10 ไบต์ของข้อมูล สองไบต์พิเศษคือบันทึกความยาว หากข้อมูลของคุณมีความยาวเต็มรูปแบบอยู่เสมอให้ใช้ตัวถ่านเพราะจะช่วยประหยัดพื้นที่และอาจเร็วกว่า โปรดอย่าใช้ varchar (1) หรืออะไรก็ตามที่เล็กกว่า varchar (4) อักขระตัวเดียวในรูปแบบ varchar ใช้สามไบต์ดังนั้นอักขระ char (3) จะไม่ใช้พื้นที่มากกว่า varchar (3)
Richard Gadsden

95

คำตอบทั้งหมดระบุว่าvarcharเป็นไบต์เดียวnvarchar คือไบต์คู่ ส่วนแรกของเรื่องนี้ขึ้นอยู่กับการเปรียบเทียบดังที่แสดงด้านล่าง

DECLARE @T TABLE
(
C1 VARCHAR(20) COLLATE Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS,
C2 NVARCHAR(20)COLLATE  Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS
)

INSERT INTO @T 
    VALUES (N'中华人民共和国',N'中华人民共和国'),
           (N'abc',N'abc');

SELECT C1,
       C2,
       LEN(C1)        AS [LEN(C1)],
       DATALENGTH(C1) AS [DATALENGTH(C1)],
       LEN(C2)        AS [LEN(C2)],
       DATALENGTH(C2) AS [DATALENGTH(C2)]
FROM   @T  

ผลตอบแทน

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

โปรดทราบว่าและตัวละครก็ยังคงไม่ได้เป็นตัวแทนในรุ่นและถูกแทนที่ด้วยความเงียบVARCHAR?

จริงๆแล้วยังไม่มีตัวอักษรจีนที่สามารถพิมพ์ซ้ำได้ด้วยไบต์เดียวในการเปรียบเทียบ อักขระไบต์เดียวเท่านั้นคือชุด ASCII แบบตะวันตกทั่วไป

ด้วยเหตุนี้จึงเป็นไปได้สำหรับการแทรกจากnvarchar(X)คอลัมน์หนึ่งไปยังvarchar(X)คอลัมน์ที่จะล้มเหลวด้วยข้อผิดพลาดการตัด (ที่ X หมายถึงตัวเลขที่เหมือนกันในทั้งสองกรณี)

SQL Server 2012 เพิ่ม SC (เสริม Character) UTF-16เรียงว่าการสนับสนุน ในการเปรียบเทียบเหล่านี้nvarcharอักขระเดี่ยวอาจใช้เวลา 2 หรือ 4 ไบต์


4
คำตอบที่ฉันกำลังมองหา นอกจากนี้เพื่อประหยัดเวลาในการ
กดไลค์

34

nchar และ char ใช้งานได้ดีในลักษณะเดียวกันเหมือนกับ nvarchar และ varchar ข้อแตกต่างระหว่างพวกเขาเพียงอย่างเดียวคือตัวอักษร nchar / nvarchar store Unicode (จำเป็นถ้าคุณต้องการใช้ชุดอักขระเพิ่มเติม) ในขณะที่ varchar ไม่

เนื่องจากอักขระ Unicode ต้องการพื้นที่จัดเก็บเพิ่มเติมเขตข้อมูล nchar / nvarchar จึงใช้พื้นที่มากเป็นสองเท่า (เช่นใน SQL Server รุ่นก่อนหน้าขนาดสูงสุดของเขตข้อมูล nvarchar คือ 4000)

คำถามนี้เป็นคำถามซ้ำกับคนนี้


3
คุณลืมสิ่งหนึ่ง: nchar ใช้ความยาวคงที่ดังนั้น nchar (10) ต้องรับสิบตัวอักษรเสมอ และ varchar (10) เป็น Unicode แน่นอนและจะยอมรับจำนวนอักขระสูงสุด 10 ตัวอักษร ยังเห็นmsdn.microsoft.com/en-us/library/ms186939.aspx
Wim สิบปาก

33

เพียงเพิ่มบางสิ่งเพิ่มเติม: nchar - เพิ่มช่องว่างต่อท้ายไปยังข้อมูล nvarchar - ไม่เพิ่มช่องว่างต่อท้ายให้กับข้อมูล

ดังนั้นหากคุณจะกรองชุดข้อมูลของคุณด้วยฟิลด์ 'nchar' คุณอาจต้องการใช้ RTRIM เพื่อลบช่องว่าง เช่นเขตข้อมูล nchar (10) ที่ชื่อว่า BRAND เก็บคำว่า NIKE มันเพิ่ม 6 ช่องว่างทางด้านขวาของคำว่า ดังนั้นเมื่อทำการกรองนิพจน์ควรอ่านได้: RTRIM (Fields! BRAND.Value) = "NIKE"

หวังว่าสิ่งนี้จะช่วยให้ใครบางคนที่นั่นเพราะฉันกำลังดิ้นรนกับมันสักพักแล้ว!


24

ความพยายามของฉันที่จะสรุปและแก้ไขคำตอบที่มีอยู่:

ก่อนcharและncharจะใช้พื้นที่เก็บข้อมูลจำนวนคงที่เสมอแม้ว่าสตริงที่จะจัดเก็บจะมีขนาดเล็กกว่าพื้นที่ว่างในขณะที่varcharและnvarcharจะใช้พื้นที่เก็บข้อมูลเท่าที่จำเป็นในการจัดเก็บสตริงนั้น (บวกสองไบต์ของค่าใช้จ่าย) น่าจะเป็นที่เก็บความยาวสตริง) ดังนั้นโปรดจำไว้ว่า "var" หมายถึง "ตัวแปร" ดังเช่นในพื้นที่ตัวแปร

จุดที่สองที่สำคัญที่จะเข้าใจได้ว่าncharและnvarcharสตริงร้านใช้ว่าสองไบต์ต่อตัวละครในขณะที่charและvarcharใช้การเข้ารหัสที่กำหนดโดยการเปรียบเทียบหน้ารหัสซึ่งจะมักจะตรงหนึ่งไบต์ต่อตัวอักษร (แม้ว่าจะมีข้อยกเว้นดูด้านล่าง) ด้วยการใช้สองไบต์ต่อตัวอักษรสามารถจัดเก็บอักขระที่หลากหลายได้ดังนั้นสิ่งสำคัญที่ต้องจำที่นี่คือสิ่งนั้นncharและnvarcharมีแนวโน้มที่จะเป็นทางเลือกที่ดีกว่ามากเมื่อคุณต้องการการสนับสนุนที่เป็นสากล

ตอนนี้สำหรับบางคะแนนปลีกย่อย

ก่อนอื่นncharและnvarcharคอลัมน์จะเก็บข้อมูลโดยใช้ UCS-2 เสมอ ซึ่งหมายความว่าจะใช้สองไบต์ต่อตัวอักขระอย่างแน่นอนและอักขระ Unicode ใด ๆ ใน Basic Multilingual Plane (BMP) สามารถจัดเก็บโดยฟิลด์ncharหรือ nvarcharอย่างไรก็ตามไม่ใช่กรณีที่อักขระ Unicode ใด ๆสามารถจัดเก็บได้ ตัวอย่างเช่นตาม Wikipedia รหัสคะแนนสำหรับอักษรอียิปต์โบราณตกอยู่นอก BMP ดังนั้นจึงมีสตริง Unicode ที่สามารถแสดงใน UTF-8 และการเข้ารหัส Unicode จริงอื่น ๆ ที่ไม่สามารถเก็บไว้ใน SQL Server ncharหรือnvarcharเขตข้อมูลและสตริงที่เขียนด้วยอักษรอียิปต์โบราณจะอยู่ในหมู่พวกเขา โชคดีที่ผู้ใช้ของคุณอาจไม่ได้เขียนสคริปต์ แต่ก็เป็นสิ่งที่ควรคำนึงถึง!

อีกจุดที่น่าสับสน แต่น่าสนใจที่ผู้โพสต์คนอื่นได้เน้นไว้คือcharและvarcharฟิลด์อาจใช้สองไบต์ต่อตัวอักษรสำหรับอักขระบางตัวหากหน้ารหัสตรวจทานต้องการ (มาร์ตินสมิ ธ แสดงตัวอย่างที่ยอดเยี่ยมซึ่งเขาแสดงให้เห็นว่า Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS แสดงพฤติกรรมนี้อย่างไรลองดูสิ)

ปรับปรุง:ณ SQL Server 2012 มีหน้ารหัสสุดท้ายสำหรับ UTF-16ตัวอย่างเช่น Latin1_General_100_CI_AS_SC ซึ่งสามารถครอบคลุมช่วง Unicode ทั้งหมดอย่างแท้จริง


14
  • char: ข้อมูลตัวอักษรความยาวคงที่ที่มีความยาวสูงสุด 8000 ตัวอักษร
  • nchar: ข้อมูลยูนิโคดที่มีความยาวคงที่ที่มีความยาวสูงสุด 4,000 อักขระ
  • Char = ความยาว 8 บิต
  • NChar = ความยาว 16 บิต

charไม่สามารถมีความยาว 8 บิต ไม่จำเป็นต้องเก็บความยาวและความยาวคงที่สามารถมีได้สูงสุด 8000 ตัวอักษร
John B. Lambe

12

nchar[(n)] (ตัวละครประจำชาติ)

  • ข้อมูลสตริงUnicode ที่มีความยาวคงที่
  • n กำหนดความยาวสตริงและต้องเป็นค่าตั้งแต่ 1 ถึง 4,000
  • ขนาดหน่วยเก็บข้อมูลเป็นสองเท่าของnไบต์

nvarchar [(n | max)] (ตัวละครประจำชาติแตกต่างกันไป)

  • ข้อมูลสตริงUnicode ที่มีความยาวผันแปรได้
  • n กำหนดความยาวสตริงและสามารถเป็นค่าตั้งแต่ 1 ถึง 4,000
  • max ระบุว่าขนาดหน่วยเก็บข้อมูลสูงสุดคือ 2 ^ 31-1 ไบต์ (2 GB)
  • ขนาดหน่วยเก็บข้อมูลเป็นไบต์เป็นสองเท่าของความยาวจริงของข้อมูลที่ป้อน + 2 ไบต์

char [(n)] (ตัวอักษร)

  • non-Unicodeข้อมูลสตริงที่มีความยาวคงที่
  • n กำหนดความยาวสตริงและต้องเป็นค่าตั้งแต่ 1 ถึง 8,000
  • ขนาดการจัดเก็บข้อมูลเป็นnไบต์

varchar [(n | max)] (ตัวละครแตกต่างกันไป)

  • ข้อมูลสตริงที่มีความยาวผันแปรและไม่ใช่ Unicode
  • n กำหนดความยาวสตริงและสามารถเป็นค่าตั้งแต่ 1 ถึง 8,000
  • max ระบุว่าขนาดหน่วยเก็บข้อมูลสูงสุดคือ 2 ^ 31-1 ไบต์ (2 GB)
  • ขนาดการจัดเก็บข้อมูลเป็นความยาวจริงของข้อมูลที่ป้อน + 2 ไบต์

7

ความแตกต่างคือ:

  1. ถ่าน n [var] เก็บ unicode ในขณะที่ [var] ถ่านเพียงเก็บอักขระไบต์เดียว
  2. [n] char ต้องการจำนวนอักขระที่มีความยาวคงที่ในขณะที่ [n] varchar ยอมรับจำนวนตัวแปรของตัวอักษรจนถึงและรวมถึงความยาวที่กำหนดไว้

ความแตกต่างก็คือความยาว ทั้ง nchar และ nvarchar สามารถยาวได้สูงสุด 4,000 อักขระ และอักขระ char และ varchar มีความยาวสูงสุด 8000 อักขระ แต่สำหรับ SQL Server คุณสามารถใช้ [n] varchar (สูงสุด) ซึ่งสามารถจัดการได้สูงสุด 2,147,483,648 อักขระ (สองกิกะไบต์ซึ่งเป็นจำนวนเต็ม 4 ไบต์ที่ลงชื่อ)


7

nchar ต้องการพื้นที่มากกว่า nvarchar

เช่น,

nchar (100) จะเก็บ 100 ตัวอักษรเสมอแม้ว่าคุณจะใส่เพียง 5 ตัวอักษรที่เหลือ 95 ตัวอักษรจะเต็มไปด้วยช่องว่าง การจัดเก็บ 5 ตัวอักษรใน nvarchar (100) จะบันทึก 5 ตัวอักษร


6
ไม่จริงอย่างสมบูรณ์เนื่องจากคุณต้องกรอกอักขระ (100) ที่มีอักขระสูงสุด 100 ตัว คุณจะใช้สิ่งนี้เมื่อคุณเก็บหมายเลขโทรศัพท์ไว้ในฐานข้อมูลหรือหมายเลขคำสั่งซื้อที่มีความยาวคงที่ เนื่องจากความยาวของฟิลด์ได้รับการแก้ไขคุณไม่มีทางเลือกที่จะเติมให้เต็มจำนวนอักขระสูงสุด แต่เมื่อข้อมูลทั้งหมดของคุณคือ 100 ตัวอักษรต่อเรกคอร์ดตัวอักขระ (100) จะใช้พื้นที่เก็บข้อมูลน้อยกว่า varchar (100) เนื่องจากไม่จำเป็นต้องมีตัวบ่งชี้ความยาว: ทุกค่าจะเท่ากับตัวอักษร 100 ตัว
Wim ten Brink

5

nchar (10) เป็นสตริง Unicode ที่มีความยาวคงที่ที่มีความยาว 10 nvarchar (10) เป็นสตริง Unicode ที่มีความยาวผันแปรได้และมีความยาวสูงสุด 10 โดยทั่วไปคุณจะใช้ค่าเดิมหากค่าข้อมูลทั้งหมดคือ 10 ตัวอักษรและหลัง ถ้าความยาวแตกต่างกันไป


การเปรียบเทียบผิด - คำถามเกี่ยวข้องกับ nchar และ varchar ไม่ใช่ nchar และ nvarchar
ลุคเบ็นเน็ตต์

4
  • nchar มีความยาวคงที่และสามารถเก็บอักขระ Unicode ได้ มันใช้ที่เก็บข้อมูลสองไบต์ต่ออักขระ

  • varchar มีความยาวผันแปรได้และไม่สามารถถืออักขระ Unicode ได้ มันใช้หนึ่งหน่วยเก็บข้อมูลไบต์ต่อตัวละคร


ไม่ถูกต้อง. Unicode สามารถใช้ 1 ถึง 4 ไบต์ (โดยทั่วไป) สำหรับตัวละครทุกตัว นอกจากนี้ varchar สามารถเก็บยูนิโค้ดได้ แต่ไม่รู้จักเป็นยูนิโค้ด ดังนั้น varchar จึงถือว่าไม่น่าเชื่อถือสำหรับหน่วยเก็บข้อมูล unicode (โดยเฉพาะอย่างยิ่งเนื่องจากมีความเสี่ยงว่ารหัสที่เข้าถึงสนามจะแปลมันไม่ถูกต้อง.)
Wim สิบปาก

@Alex: ฉันคิดว่าคุณทำประเด็นของคุณ แต่ฉันยังไม่เห็นด้วยกับคุณ สิ่งที่คุณกำลังพูดคือ int สามารถเก็บไว้ได้นานหากความยาวเกิดขึ้นน้อยกว่า 2 ^ 32 สิ่งนี้ไม่เพียง 'ไม่น่าเชื่อถือ' เท่านั้น แต่เป็นข้อ จำกัด โดยธรรมชาติซึ่งทำให้ไม่สามารถครอบคลุมช่วงค่าทั้งหมดได้
มนู

4
@Workshop Alex: ผิด Unicode เข้ารหัสเป็นUCS-2(ที่เกิดขึ้นจะเข้ารหัสที่ใช้โดย SQL Server) เก็บทุกตัวอักษรในตรงไบต์ที่สองดูmsdn.microsoft.com/en-us/library/bb330962%28v=sql.90%29.aspxSQL Server stores Unicode in the UCS-2 encoding scheme... UCS-2 is a fixed-length encoding that represents all characters as a 16-bit value (2 bytes) : SQL Server 2008 สามารถใช้การบีบอัด SCSU แต่ยังคงการบีบอัดของสายอักขระ Unicode ที่เข้ารหัส UCS-2: msdn.microsoft.com/en-us/library/ee240835.aspx
Remus Rusanu

2

NVARCHARสามารถเก็บอักขระ Unicode และใช้เวลา 2 ไบต์ต่ออักขระ


1
ไม่ถูกต้อง! Unicode ใช้ระหว่าง 1 ถึง 4 ไบต์ต่อตัวละคร! หลายคนลืมสิ่งนี้! แม้การใช้ UTF-16 อาจส่งผลให้อักขระบางตัวมีขนาด 4 ไบต์แทนที่จะเป็น 2 แม้ว่าความยาวทั่วไปจะเป็น 2 ไบต์ รูปแบบย่อยอื่น ๆ ของ Unicode อาจใช้เวลามากกว่า 4 ไบต์!
Wim ten Brink

7
@WimtenBrink - คำถามเกี่ยวกับ SQL Server และnvarcharใช้เวลา 2 ไบต์ต่อตัวอักษรเสมอ
Martin Smith

@ ว่าคุณถูกต้องมีการเข้ารหัสหลายอย่างสำหรับ Unicode ที่สามารถสร้างจำนวนไบต์ที่แตกต่างกัน แต่ SQL Server ไม่ได้ให้คุณเลือกเกี่ยวกับการเข้ารหัส Unicode SQL Server ก่อนปี 2012 ใช้ UCS-2 กว้างสองไบต์เท่านั้นดังนั้น Martin จึงถูกต้องในเวลาที่เขาเขียนคำตอบ ดังที่ได้กล่าวไว้ข้างต้นขณะนี้ SQL Server 2012 มี UTF-16 ดังนั้นสองไบต์สำหรับอักขระจำนวนมาก (ใน Unicode Basic Multiliingual Plane) สองไบต์สำหรับสี่ไบต์
Concrete Gannet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.