Sự khác biệt giữa char, nchar, varchar và nvarchar trong SQL Server là gì?


Câu trả lời:


857

Chỉ cần dọn dẹp ... hoặc tổng hợp ...

  • ncharnvarcharcó thể lưu trữ các tự Unicode .
  • charkhông thể lưu trữ các ký tự Unicode .varchar
  • charncharđộ dài cố định sẽ dành không gian lưu trữ cho số lượng ký tự bạn chỉ định ngay cả khi bạn không sử dụng hết dung lượng đó.
  • varcharnvarcharđộ dài thay đổi sẽ chỉ sử dụng hết khoảng trắng cho các ký tự bạn lưu trữ. Nó sẽ không dự trữ lưu trữ như charhoặcnchar .

ncharnvarcharsẽ chiếm gấp đôi dung lượng lưu trữ, vì vậy có thể là khôn ngoan khi chỉ sử dụng chúng nếu bạn cần hỗ trợ Unicode .


15
char và varchar không có nghĩa là lưu trữ unicode, nhưng với một số thủ thuật mã hóa bổ sung và logic bổ sung, bạn vẫn có thể sử dụng sai trường [var] để lưu trữ unicode.
Wim ten Brink

10
Việc đối chiếu phụ thuộc vào việc các n...phiên bản có chiếm gấp đôi dung lượng lưu trữ như câu trả lời của tôi hay không
Martin Smith

7
Lợi thế để lưu trữ lưu trữ là gì?
mlissner

4
Ở điểm cuối cùng: Sử dụng Unicode nchar và nvarchar vẫn tốt hơn trong hầu hết các trường hợp, đối chiếu tốt hơn, linh hoạt hơn cho người dùng, loại bỏ các vấn đề tương thích trong tương lai. Và nhân tiện, không gian lưu trữ không phải là vấn đề trong trường hợp này, vì sử dụng đối chiếu mà không có Unicode rất nhiều rắc rối và tốc độ bộ nhớ sẽ tiếp tục giảm trong tương lai
Jaison Varghese

6
@BenCaine char (20) sẽ sử dụng 20 byte (giả sử đối chiếu 8 bit); varchar (20) sẽ sử dụng len (dữ liệu) +2 byte, tức là 22 cho 20 byte dữ liệu, nhưng chỉ 12 cho 10 byte dữ liệu. Hai byte thêm là các bản ghi độ dài. Nếu dữ liệu của bạn sẽ luôn có chiều dài đầy đủ, thì hãy sử dụng char, vì nó tiết kiệm không gian và có thể nhanh hơn. Xin đừng bao giờ sử dụng varchar (1), hoặc thực sự là bất cứ thứ gì nhỏ hơn varchar (4). Một ký tự đơn ở định dạng varchar sử dụng ba byte, do đó, char (3) sẽ không bao giờ sử dụng nhiều không gian hơn varchar (3).
Richard Gadsden

95

Tất cả các câu trả lời cho đến nay varcharlà byte đơn, nvarchar là byte kép. Phần đầu tiên của điều này thực sự phụ thuộc vào đối chiếu như minh họa dưới đây.

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  

Trả về

nhập mô tả hình ảnh ở đây

Lưu ý rằng các ký tự ký tự vẫn không được thể hiện trong VARCHARphiên bản và được âm thầm thay thế bằng ?.

Thực tế vẫn không có ký tự tiếng Hoa nào có thể được lặp lại bởi một byte trong đối chiếu đó. Các ký tự byte đơn duy nhất là tập ASCII phương tây điển hình.

Do đó, việc chèn từ nvarchar(X)cột này sang varchar(X)cột khác có thể bị lỗi cắt ngắn (trong đó X biểu thị một số giống nhau trong cả hai trường hợp).

SQL Server 2012 bổ sung các đối chiếu SC (Ký tự bổ sung) hỗ trợ UTF-16. Trong các đối chiếu này, một nvarcharký tự đơn có thể mất 2 hoặc 4 byte.


4
Loại câu trả lời tôi đang tìm kiếm. Ngoài ra để tiết kiệm thời gian cho những người như tôi - những văn bản không phải tiếng anh dịch ra là "Cộng hòa Nhân dân Trung Hoa" translate.google.com/#auto/en/...
Igand

34

nchar và char hoạt động khá giống nhau theo cách tương tự như nhau, cũng như nvarchar và varchar. Sự khác biệt duy nhất giữa chúng là nchar / nvarchar lưu trữ các ký tự Unicode (cần thiết nếu bạn yêu cầu sử dụng các bộ ký tự mở rộng) trong khi varchar thì không.

Vì các ký tự Unicode yêu cầu lưu trữ nhiều hơn, các trường nchar / nvarchar chiếm không gian gấp đôi (ví dụ: trong các phiên bản trước của SQL Server, kích thước tối đa của trường nvarchar là 4000).

Câu hỏi này là một bản sao của câu hỏi này .


3
Bạn quên một điều: nchar sử dụng độ dài cố định nên nchar (10) luôn cần nhận mười ký tự. Và varchar (10) thực sự là Unicode và sẽ chấp nhận bất kỳ số lượng ký tự nào, tối đa 10 ký tự. Đồng thời xem msDN.microsoft.com/en-us/l Library / ms186939.aspx
Wim ten Brink

33

Chỉ cần thêm một cái gì đó nữa: nchar - thêm dấu cách vào dữ liệu. nvarchar - không thêm dấu cách vào dữ liệu.

Vì vậy, nếu bạn định lọc tập dữ liệu của mình theo trường 'nchar', bạn có thể muốn sử dụng RTRIM để xóa khoảng trắng. Ví dụ: trường nchar (10) được gọi là THƯƠNG HIỆU lưu trữ từ NIKE. Nó thêm 6 khoảng trắng ở bên phải của từ. Vì vậy, khi lọc, biểu thức nên đọc: RTRIM (Trường! BRAND.Value) = "NIKE"

Hy vọng điều này sẽ giúp được ai đó ngoài kia vì tôi đã phải vật lộn với nó một chút!


24

Cố gắng của tôi để tóm tắt và sửa các câu trả lời hiện có:

Đầu tiên, charncharsẽ luôn sử dụng một lượng không gian lưu trữ cố định, ngay cả khi chuỗi được lưu trữ nhỏ hơn không gian có sẵn, trong khi đó varcharnvarcharsẽ chỉ sử dụng nhiều dung lượng lưu trữ cần thiết để lưu trữ chuỗi đó (cộng với hai byte trên không, có lẽ để lưu trữ độ dài chuỗi). Vì vậy, hãy nhớ, "var" có nghĩa là "biến", như trong không gian biến.

Điểm chính thứ hai cần hiểu là, ncharnvarcharlưu trữ các chuỗi sử dụng chính xác hai byte cho mỗi ký tự, trong khi đó charvarcharsử dụng mã hóa được xác định bởi trang mã đối chiếu, thường sẽ chính xác một byte cho mỗi ký tự (mặc dù có trường hợp ngoại lệ, xem bên dưới). Bằng cách sử dụng hai byte cho mỗi ký tự, có thể lưu trữ rất nhiều ký tự, vì vậy điều cơ bản cần nhớ ở đây là ncharnvarcharcó xu hướng là lựa chọn tốt hơn nhiều khi bạn muốn hỗ trợ quốc tế hóa, điều mà bạn có thể làm.

Bây giờ cho một số điểm tốt hơn.

Đầu tiên ncharnvarcharcác cột luôn lưu trữ dữ liệu bằng UCS-2. Điều này có nghĩa là chính xác hai byte cho mỗi ký tự sẽ được sử dụng và bất kỳ ký tự Unicode nào trong Mặt phẳng đa ngôn ngữ cơ bản (BMP) có thể được lưu trữ bởi một ncharhoặc nvarchartrường. Tuy nhiên, không phải trường hợp nào cũng có thể lưu trữ bất kỳ ký tự Unicode nào . Ví dụ, theo Wikipedia, các điểm mã cho chữ tượng hình Ai Cập nằm ngoài BMP. Do đó, có các chuỗi Unicode có thể được biểu thị bằng UTF-8 và các bảng mã Unicode thực sự khác không thể được lưu trữ trong SQL Server ncharhoặc nvarchartrường và các chuỗi được viết bằng chữ tượng hình Ai Cập sẽ nằm trong số đó. May mắn là người dùng của bạn có thể không viết theo kịch bản đó, nhưng đó là điều cần lưu ý!

Một điểm khó hiểu nhưng thú vị khác mà các áp phích khác đã nhấn mạnh là charvarcharcác trường có thể sử dụng hai byte cho mỗi ký tự cho một số ký tự nhất định nếu trang mã đối chiếu yêu cầu nó. (Martin Smith đưa ra một ví dụ tuyệt vời, trong đó anh ấy cho thấy cách Trung Quốc_Traditable_Stroke_Order_100_CS_AS_KS_WS thể hiện hành vi này. Hãy xem thử.)

CẬP NHẬT: Kể từ SQL Server 2012, cuối cùng cũng có các trang mã cho UTF-16 , ví dụ Latin1_General_100_CI_AS_SC, có thể thực sự bao trùm toàn bộ phạm vi Unicode.


14
  • char: dữ liệu ký tự có độ dài cố định với độ dài tối đa 8000 ký tự.
  • nchar: dữ liệu unicode có độ dài cố định với độ dài tối đa 4000 ký tự.
  • Char = Độ dài 8 bit
  • NChar = Độ dài 16 bit

charkhông thể có độ dài 8 bit. Nó không phải lưu trữ độ dài và độ dài cố định có thể lên tới 8000 ký tự.
John B. Lambe

12

nchar[(n)] (nhân vật quốc gia)

  • Dữ liệu chuỗi Unicode có độ dài cố định .
  • n xác định độ dài chuỗi và phải là giá trị từ 1 đến 4.000.
  • Kích thước lưu trữ là hai lần nbyte.

nvarchar [(n | max)] (tính cách dân tộc khác nhau.)

  • Dữ liệu chuỗi Unicode có độ dài thay đổi .
  • n xác định độ dài chuỗi và có thể là giá trị từ 1 đến 4.000.
  • max chỉ ra rằng kích thước lưu trữ tối đa là 2 ^ 31-1 byte (2 GB).
  • Kích thước lưu trữ, tính bằng byte, gấp hai lần chiều dài thực của dữ liệu được nhập + 2 byte

char [(n)] (tính cách)

  • Độ dài cố định, non-Unicodedữ liệu chuỗi.
  • n xác định độ dài chuỗi và phải là giá trị từ 1 đến 8.000.
  • Kích thước lưu trữ là nbyte.

varchar [(n | max)] (nhân vật khác nhau)

  • Dữ liệu chuỗi có độ dài thay đổi, không Unicode .
  • n xác định độ dài chuỗi và có thể là giá trị từ 1 đến 8.000.
  • max chỉ ra rằng kích thước lưu trữ tối đa là 2 ^ 31-1 byte (2 GB).
  • Kích thước lưu trữ là chiều dài thực tế của dữ liệu được nhập + 2 byte.

7

Sự khác biệt là:

  1. n [var] char lưu trữ unicode trong khi [var] char chỉ lưu các ký tự byte đơn.
  2. [n] char yêu cầu một số ký tự cố định có độ dài chính xác trong khi [n] varchar chấp nhận số lượng ký tự thay đổi lên đến và bao gồm cả độ dài được xác định.

Một sự khác biệt khác là chiều dài. Cả nchar và nvarchar có thể dài tới 4.000 ký tự. Và char và varchar có thể dài tới 8000 ký tự. Nhưng đối với SQL Server, bạn cũng có thể sử dụng [n] varchar (max) có thể xử lý tối đa 2.147.483.648 ký tự. (Hai gigabyte, số nguyên 4 byte đã ký.)


7

nchar đòi hỏi nhiều không gian hơn nvarchar.

ví dụ,

Một nchar (100) sẽ luôn lưu trữ 100 ký tự ngay cả khi bạn chỉ nhập 5, 95 ký tự còn lại sẽ được đệm bằng khoảng trắng. Lưu trữ 5 ký tự trong một nvarchar (100) sẽ lưu 5 ký tự.


6
Không hoàn toàn đúng, vì bạn bắt buộc phải điền một char (100) với tối đa 100 ký tự. Bạn sẽ sử dụng điều này khi bạn ví dụ lưu trữ số điện thoại trong cơ sở dữ liệu của mình hoặc đặt hàng số có độ dài cố định. Vì độ dài trường là cố định, bạn không có lựa chọn nào để điền nó tới số ký tự tối đa. Nhưng khi tất cả dữ liệu của bạn là 100 ký tự trên mỗi bản ghi, một char (100) sẽ chiếm ít dung lượng hơn so với varchar (100) vì nó không cần chỉ thị độ dài: mỗi giá trị sẽ chính xác là 100 ký tự.
Wim ten Brink

5

nchar (10) là một chuỗi Unicode có độ dài cố định có độ dài 10. nvarchar (10) là một chuỗi Unicode có độ dài thay đổi với độ dài tối đa là 10. Thông thường, bạn sẽ sử dụng chuỗi trước nếu tất cả các giá trị dữ liệu là 10 ký tự và sau nếu độ dài khác nhau.


So sánh sai - câu hỏi liên quan đến nchar và varchar, không phải nchar và nvarchar.
Luke Bennett

4
  • nchar có độ dài cố định và có thể chứa các ký tự unicode. nó sử dụng hai byte lưu trữ cho mỗi ký tự.

  • varchar có độ dài thay đổi và không thể giữ các ký tự unicode. nó sử dụng lưu trữ một byte cho mỗi ký tự.


Sai lầm. Unicode có thể sử dụng 1 đến 4 byte (nói chung) cho mỗi ký tự. Ngoài ra, một varchar có thể giữ unicode, nhưng nó không được công nhận là unicode. Kết quả là, một varchar được coi là không đáng tin cậy cho việc lưu trữ unicode. (Đặc biệt vì có nguy cơ mã truy cập vào trường sẽ dịch sai mã.)
Wim ten Brink

@Alex: Tôi nghĩ bạn đã đưa ra quan điểm của mình nhưng tôi vẫn không đồng ý với bạn. Những gì bạn đang nói là một int CÓ THỂ giữ được lâu nếu độ dài xảy ra nhỏ hơn 2 ^ 32. Đây không chỉ là "không đáng tin cậy", nó là một giới hạn cố hữu khiến nó không thể bao quát toàn bộ phạm vi giá trị.
Manu

4
@Workshop Alex: Sai. Unicode được mã hóa dưới dạng UCS-2(mà tình cờ là mã hóa được sử dụng bởi SQL Server) lưu trữ mọi ký tự trong chính xác hai byte, xem msdn.microsoft.com/en-us/l Library / bb330962% 28v = sql.90% 29.aspx : SQL 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 có thể sử dụng nén SCSU, nhưng vẫn nén các chuỗi Unicode được mã hóa UCS-2: msdn.microsoft.com/en-us/l Library / ee240835.aspx
Remus Rusanu

2

NVARCHAR có thể lưu trữ các ký tự Unicode và mất 2 byte cho mỗi ký tự.


1
SAI LẦM! Unicode sử dụng từ 1 đến 4 byte cho mỗi ký tự! Nhiều người quên điều này! Ngay cả việc sử dụng UTF-16 cũng có thể dẫn đến một số ký tự lấy 4 byte thay vì 2, mặc dù độ dài phổ biến sẽ là 2 byte. Một số biểu mẫu con khác của Unicode có thể mất hơn 4 byte!
Wim ten Brink

7
@WimtenBrink - Câu hỏi là về SQL Server và nvarcharluôn mất 2 byte cho mỗi ký tự.
Martin Smith

@Wim, bạn đúng là có một số mã hóa cho Unicode có thể tạo ra một số byte khác nhau. Nhưng SQL Server không cho bạn lựa chọn về mã hóa Unicode. SQL Server trước năm 2012 chỉ sử dụng UCS-2, rộng hai byte, vì vậy Martin đã đúng vào thời điểm anh viết câu trả lời. Như các câu trả lời khác đã nói ở trên, SQL Server 2012 hiện cung cấp UTF-16, do đó, hai byte cho nhiều ký tự (những ký tự trong Mặt phẳng đa biến Unicode Basic), bốn byte cho các loại khác.
Bê tông Gannet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.