В чем разница между char, nchar, varchar и nvarchar в SQL Server?

626

Что подразумевается под nvarchar?

В чем разница между char, nchar, varcharи nvarcharв SQL Server?

MrDatabase
источник

Ответы:

859

Просто чтобы прояснить ... или подвести итог ...

  • ncharи nvarcharможет хранить символы Unicode .
  • charи не может хранить символы Юникода .varchar
  • charи ncharимеют фиксированную длину, которая зарезервирует пространство для хранения указанного вами количества символов, даже если вы не занимаете все это пространство.
  • varcharи nvarcharимеют переменную длину, которая будет использовать только пробелы для символов, которые вы храните. Это не зарезервирует хранилище как charилиnchar .

ncharи nvarcharзаймет в два раза больше места для хранения, поэтому разумно использовать их, только если вам нужна поддержка Unicode .

Брайан Ким
источник
15
char и varchar не предназначены для хранения юникода, но с некоторыми дополнительными приемами кодирования и дополнительной логикой вы все равно можете неправильно использовать поле [var] char для хранения юникода.
Вим тен Бринк
10
Это зависит от параметров сортировки, n...занимают ли версии вдвое больше места для хранения, чем показывает мой ответ
Мартин Смит
7
В чем преимущество резервирования хранилища?
mlissner
4
Последнее замечание: использование Unicode nchar и nvarchar по-прежнему лучше в большинстве случаев, лучшая сортировка, гибкость для пользователей, устраняет проблемы совместимости в будущем. И, кстати, пространство для хранения не является проблемой для этого случая, так как использование сортировки без Unicode очень хлопотно, и в будущем скорость памяти будет продолжать снижаться
Jaison Varghese
6
@BenCaine char (20) будет использовать 20 байтов (при условии 8-битной сортировки); varchar (20) будет использовать len (data) +2 байта, то есть 22 для 20 байтов данных, но только 12 для 10 байтов данных. Два дополнительных байта являются записями длины. Если ваши данные всегда будут полной длины, используйте символ, так как это экономит место и может быть быстрее. Пожалуйста, никогда не используйте varchar (1) или что-то меньшее, чем varchar (4). Один символ в формате varchar использует три байта, поэтому char (3) никогда не будет использовать больше места, чем varchar (3).
Ричард Гадсден
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 (дополнительных символов), которые поддерживают UTF-16. В этих сопоставлениях один nvarcharсимвол может занимать 2 или 4 байта.

Мартин Смит
источник
4
Такой ответ я искал. Также, чтобы сэкономить время таким, как я, - неанглийский текст переводится как «Китайская Народная Республика» translate.google.com/#auto/en/…
Igand
34

nchar и char в значительной степени работают точно так же, как nvarchar и varchar. Единственная разница между ними заключается в том, что nchar / nvarchar хранит символы Unicode (важно, если вам требуется использование расширенных наборов символов), а varchar - нет.

Поскольку для символов Юникода требуется больше памяти, поля nchar / nvarchar занимают вдвое больше места (например, в более ранних версиях SQL Server максимальный размер поля nvarchar составляет 4000).

Этот вопрос является дубликатом этого .

Люк Беннетт
источник
3
Вы забываете одну вещь: nchar использует фиксированную длину, поэтому nchar (10) всегда должен получать десять символов. И varchar (10) действительно является Unicode и может принимать любое количество символов, до 10 символов. Также см. Msdn.microsoft.com/en-us/library/ms186939.aspx
Вим тен Бринк,
33

Просто добавьте что-то еще: nchar - добавляет завершающие пробелы в данные. nvarchar - не добавляет завершающие пробелы к данным.

Итак, если вы собираетесь фильтровать ваш набор данных по полю 'nchar', вы можете использовать RTRIM для удаления пробелов. Например, поле nchar (10) под названием BRAND хранит слово NIKE. Это добавляет 6 пробелов справа от слова. Таким образом, при фильтрации выражение должно иметь вид: RTRIM (Fields! BRAND.Value) = "NIKE"

Надеюсь, это кому-то поможет, потому что я боролся с этим только сейчас!

Dimuthu
источник
24

Моя попытка обобщить и исправить существующие ответы:

Во-первых, charи ncharвсегда будет использовать фиксированный объем пространства хранения, даже когда строка, которая должна быть сохранена, меньше доступного пространства, тогда как varcharи nvarcharбудет использовать столько места, сколько необходимо для хранения этой строки (плюс два байта служебных данных, предположительно для хранения длины строки). Помните, что «var» означает «переменная», как в переменном пространстве.

Вторым важным моментом, который нужно понять, является то, что ncharи nvarcharхранить строки, используя ровно два байта на символ, тогда как charи varcharиспользовать кодировку, определенную кодовой страницей сопоставления, которая обычно будет ровно один байт на символ (хотя есть исключения, см. Ниже). Используя два байта на символ, очень широкий диапазон символов может быть сохранен, так что основная вещь , чтобы помнить, что ncharи , как nvarcharправило, гораздо лучший выбор , если вы хотите поддержку интернационализации, который вы , вероятно , сделать.

Теперь о некоторых более тонких моментах.

Во- первых, ncharи nvarcharстолбцы всегда хранить данные с использованием UCS-2. Это означает, что будет использоваться ровно два байта на символ, и любой символ Unicode в базовой многоязычной плоскости (BMP) может быть сохранен полем ncharили nvarchar. Однако это не тот случай, когда любой символ Unicode может быть сохранен. Например, согласно Википедии, кодовые точки для египетских иероглифов выходят за пределы 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.

PeterAllenWebb
источник
14
  • char: символьные данные фиксированной длины с максимальной длиной 8000 символов.
  • nchar: данные Юникода фиксированной длины с максимальной длиной 4000 символов.
  • Char = Длина 8 бит
  • NChar Длина = 16 бит
песчаники
источник
charне может иметь 8-битную длину. Он не должен хранить длину, а фиксированная длина может быть до 8000 символов.
Джон Б. Ламб,
12

nchar[(n)] (национальный характер)

  • Строковые данные Unicode фиксированной длины .
  • n определяет длину строки и должен быть значением от 1 до 4000.
  • Размер хранилища составляет два nбайта.

nvarchar [(n | max)] (национальный характер меняется.)

  • Строковые данные Unicode переменной длины .
  • n определяет длину строки и может принимать значение от 1 до 4000.
  • max указывает, что максимальный размер хранилища составляет 2 ^ 31-1 байт (2 ГБ).
  • Размер хранилища в байтах в два раза превышает фактическую длину введенных данных + 2 байта

char [(n)] (персонаж)

  • non-UnicodeСтроковые данные фиксированной длины .
  • n определяет длину строки и должен быть значением от 1 до 8000.
  • Размер хранилища - nбайты.

varchar [(n | max)] (характер меняется)

  • Строковые данные переменной длины, отличные от Unicode .
  • n определяет длину строки и может принимать значение от 1 до 8000.
  • max указывает, что максимальный размер хранилища составляет 2 ^ 31-1 байт (2 ГБ).
  • Размер хранилища - это фактическая длина введенных данных + 2 байта.
Rasel
источник
7

Различия :

  1. n [var] char хранит Unicode, тогда как [var] char просто хранит однобайтовые символы.
  2. [n] char требует фиксированного количества символов точной длины, в то время как [n] varchar принимает переменное количество символов вплоть до определенной длины.

Другое отличие - длина. И nchar, и nvarchar могут содержать до 4000 символов. И char и varchar могут быть длиной до 8000 символов. Но для SQL Server вы также можете использовать [n] varchar (max), который может обрабатывать до 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 символов.
Вим тен Бринк
5

nchar (10) является строкой Unicode фиксированной длины длиной 10. nvarchar (10) является строкой Unicode переменной длины с максимальной длиной 10. Как правило, вы должны использовать первое, если все значения данных состоят из 10 символов, а второе если длина варьируется.

Джейсон Кресоваты
источник
Неверное сравнение - вопрос касается nchar и varchar, а не nchar и nvarchar.
Люк Беннетт
4
  • nchar имеет фиксированную длину и может содержать символы Юникода. он использует два байта памяти на символ.

  • varchar имеет переменную длину и не может содержать символы Юникода. он использует одну байтовую память на символ.

Manu
источник
Неправильно. Unicode может использовать от 1 до 4 байтов (в общем) для каждого символа. Кроме того, varchar может содержать Unicode, но он не распознается как Unicode. В результате varchar считается ненадежным для хранения Unicode. (Тем более, что есть риск, что код, который обращается к полю, будет переводить его неправильно.)
Вим тен Бринк
@ Алекс: Я думаю, что вы сделали свою точку зрения, но я все еще не согласен с вами. Вы говорите, что int МОЖЕТ держать long, если long меньше 2 ^ 32. Это не только «ненадежно», это неотъемлемое ограничение, которое делает невозможным охватить весь диапазон значений.
Ману
4
@Workshop Алекс: Неверно. Unicode, закодированный как UCS-2(который является кодировкой, используемой SQL Server) сохраняет каждый символ точно два байта, см msdn.microsoft.com/en-us/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 может использовать сжатие SCSU, но все еще является сжатием строк Unicode в кодировке UCS-2: msdn.microsoft.com/en-us/library/ee240835.aspx
Remus Rusanu
2

NVARCHAR может хранить символы Unicode и занимает 2 байта на символ.

Густаво Рубио
источник
1
НЕПРАВИЛЬНО! Юникод использует от 1 до 4 байтов на символ! Многие забывают об этом! Даже использование UTF-16 может привести к тому, что некоторые символы будут брать 4 байта вместо 2, хотя общая длина будет 2 байта. Некоторые другие подформаты Unicode могут занимать даже больше 4 байтов!
Вим тен Бринк
7
@WimtenBrink - вопрос касается SQL Server и nvarcharвсегда занимает 2 байта на символ.
Мартин Смит
@Wim, вы правы, есть несколько кодировок для Unicode, которые могут производить различное количество байтов. Но SQL Server не дает вам выбора в отношении кодировки Unicode. SQL Server до 2012 года использовал только UCS-2, шириной два байта, поэтому Мартин был прав, когда писал ответ. Как уже говорилось в других ответах, SQL Server 2012 теперь предоставляет UTF-16, поэтому два байта для многих символов (те, что в базовой многоязыковой плоскости Unicode), четыре байта для других.
Бетонные олуша