Tại sao chúng ta cần đặt N trước các chuỗi trong Microsoft SQL Server?


34

Tôi đang học T-SQL. Từ các ví dụ tôi đã thấy, để chèn văn bản vào một varchar()ô, tôi chỉ có thể viết chuỗi cần chèn, nhưng đối với nvarchar()các ô, mọi ví dụ đều có tiền tố các chuỗi có chữ N.

Tôi đã thử truy vấn sau đây trên một bảng có nvarchar()các hàng và nó hoạt động tốt, vì vậy không cần tiền tố N:

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

Tại sao các chuỗi có tiền tố N trong mọi ví dụ tôi đã thấy?

Những ưu và nhược điểm của việc sử dụng tiền tố này là gì?


Không phải N chỉ cần cho chuỗi ký tự?
Wayne In Yak

Tiếng Ba Lan là một ngôn ngữ không phải là tiếng Latin ????
Heckflosse_230

2
Ncó nghĩa là Quốc gia, như trong "Ký tự thay đổi quốc gia", xem Các kiểu dữ liệu SQL ANSI tương đương .
ErikE

Tôi đồng ý với câu hỏi này và cho đến nay chưa có ai trả lời nó, AFAICT. Có lẽ nó có thể được trình bày lại như là tại sao lại tệ khi để SQL chuyển đổi hoàn toàn VARCHARthành NVARCHARchuỗi của tôi khi chuỗi ký tự của tôi là ASCII?
binki

Câu hỏi này đã được hỏi và trả lời ở đây: sự khác biệt giữa varchar và nvarchar là gì?

Câu trả lời:


27

NVarchar được sử dụng cho Unicode. Nếu cơ sở dữ liệu của bạn không lưu trữ dữ liệu đa ngôn ngữ, bạn có thể tiếp tục sử dụng Varchar. Như một ví dụ: N'abc'chỉ cần chuyển đổi chuỗi của bạn thành unicode.


2
Tại sao bạn không phải tiền tố với U thay vì N sau đó?
Attila Kun

Bạn có thể bị nhầm lẫn vì không dấu như một phỏng đoán
JB King

U&'abc'là cách đúng để xác định chuỗi Unicode. Xem SQL 2003 BNF
ceving

2
Chữ N thực sự là viết tắt của bộ "Nhân vật ngôn ngữ quốc gia".
Mike Bovenlander

23

Theo mặc định, máy chủ SQL sử dụng mã ký tự Windows-1252 cho varchar . Nó chứa hầu hết các ký tự cho các ngôn ngữ gốc Latinh (tiếng Anh, tiếng Đức, tiếng Pháp, v.v.) Nhưng nó không chứa các ký tự cho các ngôn ngữ không phải là tiếng Latin (tiếng Ba Lan, tiếng Nga, v.v.). Như đã nêu bởi @Pieter B, nvarchar được sử dụng để khắc phục vấn đề đó bởi vì nó dành cho Unicode chứa các ký tự bị thiếu đó. Điều này đi kèm với chi phí, phải mất gấp đôi không gian để lưu trữ nvarchar so với varchar.

Đặt N trước chuỗi của bạn để đảm bảo các ký tự được chuyển đổi thành Unicode trước khi được đặt vào cột nvarchar. Hầu hết thời gian bạn sẽ ổn khi rời khỏi N, nhưng tôi không khuyên bạn nên làm điều đó. An toàn hơn là xin lỗi.


3
Chỉ cần làm rõ: Máy chủ SQL "Theo mặc định" sử dụng mã hóa tương ứng với đối chiếu của trường Varchar, có thể ghi đè tại thời điểm tạo trường, thường dựa trên đối chiếu mặc định cho ví dụ của bạn. Đối chiếu mặc định cho phiên bản của bạn có thể được đặt khi cài đặt, nhưng thường tương ứng với CP_ACP của ngôn ngữ mặc định hệ thống. Đó sẽ là Windows 1252 trên máy US-English, nhưng 932 trên máy có ngôn ngữ hệ thống Nhật Bản, 1251 trên máy Nga, v.v. Đạo đức của câu chuyện? Sử dụng NVarchar :)
JasonTrue

1
Cho đến nay, đây là câu trả lời duy nhất giải quyết câu hỏi như đã hỏi "Tại sao sử dụng tiền tố N trên chuỗi ký tự vì SQL sẽ chuyển mã ngầm?". Các câu trả lời khác là tất cả cho một câu hỏi khác nhau "Sự khác biệt giữa nvarchar so với varchar là gì?"
Timbo

18

Bởi vì MS SQL Server hỗ trợ UTF-8 kém so với các RDBMS khác.

MS SQL Server tuân theo quy ước, được sử dụng trong chính Windows, rằng các chuỗi "hẹp" ( chartrong C ++ CHARhoặc VARCHARtrong SQL) được mã hóa trong một "trang mã" kế thừa. Vấn đề với các trang mã là chúng có số lượng ký tự hạn chế (hầu hết là mã hóa một byte, giới hạn báo cáo là 256 ký tự) và được thiết kế xung quanh một ngôn ngữ (hoặc nhóm ngôn ngữ có bảng chữ cái tương tự). Điều này làm cho nó khó khăn để lưu trữ dữ liệu đa ngôn ngữ. Ví dụ: bạn không thể lưu trữ cả dữ liệu tiếng Nga và tiếng Do Thái vì tiếng Nga sử dụng trang mã 1251 và tiếng Do Thái sử dụng trang mã 1255 .

Unicode giải quyết vấn đề này bằng cách sử dụng một bộ ký tự mã hóa khổng lồ duy nhất có chỗ cho hơn một triệu ký tự, đủ để đại diện cho mọi ngôn ngữ trên thế giới. Có một số sơ đồ mã hóa Unicode; Microsoft thích sử dụng UTF-16 , vì những lý do lịch sử . Vì UTF-16 biểu thị các chuỗi dưới dạng một chuỗi các đơn vị mã 16 bit thay vì 8 bit truyền thống, nên cần một loại ký tự riêng. Trong MSVC ++, đây là wchar_t. Và trong MS SQL, nó NCHARhay NVARCHAR. Chữ Nviết tắt của "quốc gia" , có vẻ ngược với tôi vì Unicode là về quốc tế hóa , nhưng đó là thuật ngữ ISO.

Các triển khai SQL khác cho phép bạn lưu trữ văn bản UTF-8 trong một VARCHARcột. UTF-8 là mã hóa có độ dài thay đổi (1-4 byte cho mỗi ký tự) được tối ưu hóa cho trường hợp khi dữ liệu của bạn chủ yếu nằm trong phạm vi Latin cơ bản (được biểu thị dưới cùng 1 byte cho mỗi ký tự như ASCII), nhưng có thể biểu thị bất kỳ ký tự Unicode nào. Do đó, bạn sẽ tránh được vấn đề "gấp đôi không gian" được đề cập bởi bwalk2895.

Thật không may, MS SQL Server không hỗ trợ UTF-8VARCHAR , vì vậy thay vào đó bạn phải sử dụng UTF-16 thay vào đó (và lãng phí không gian cho văn bản ASCII), sử dụng trang mã không Unicode (và mất khả năng thể hiện các ký tự nước ngoài), hoặc lưu trữ UTF-8 trong một BINARYcột (và xử lý các sự bất tiện như các hàm chuỗi SQL không hoạt động đúng hoặc phải xem dữ liệu dưới dạng kết xuất hex trong trình quản lý GUI DB của bạn).


1
Trong các phiên bản trước đó là SQL Server 2012, họ lưu trữ bằng cách sử dụng mã hóa UCS-2, tức là 2byte. Trong các phiên bản mới hơn, họ đang sử dụng UTF-16, ánh xạ có độ dài thay đổi thành 4byte cho mỗi ký tự (tương tự UTF-8 nhưng bắt đầu từ 2 byte).
j123b567
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.