В чем разница между varchar и nvarchar?

1355

Это просто nvarcharподдерживает многобайтовые символы? Если это так, есть ли смысл в использовании, кроме проблем хранения varchars?

stimms
источник
6
Мне нравится точка зрения Инкомудро, именно это привело меня к размышлениям о разнице между varchar & nvarchar в первую очередь. Наше Java-приложение против базы данных SQL Server использует myBatis, который, по-видимому, отправляет строки как nvarchar по умолчанию (все еще не уверен, каким образом (или если) это можно переопределить). Простой запрос показался огромной проблемой производительности, потому что я определил столбец, для которого он выбирал, varchar, а не nvarchar, и он игнорировал индекс столбца.
Шон Рид,

Ответы:

1653

nvarcharСтолбец может хранить любые данные Unicode. varcharКолонка ограничена 8-битной кодовой страницы. Некоторые люди думают, что это varcharследует использовать, потому что это занимает меньше места. Я считаю, что это не правильный ответ. Несовместимость кодовых страниц - это боль, а Unicode - лекарство от проблем с кодовыми страницами. В наше время с дешевыми дисками и памятью, на самом деле больше нет причин тратить время на копирование кодовых страниц.

Все современные операционные системы и платформы разработки используют Unicode для внутреннего использования. Используя nvarcharвместо varchar, вы можете избежать преобразования кодировки каждый раз, когда читаете или записываете в базу данных. Преобразования занимают время и подвержены ошибкам. А восстановление после ошибок конвертации - нетривиальная проблема.

Если вы взаимодействуете с приложением, которое использует только ASCII, я все равно рекомендую использовать Unicode в базе данных. Алгоритмы сопоставления ОС и базы данных будут лучше работать с Unicode. Unicode позволяет избежать проблем конвертации при взаимодействии с другими системами. И вы будете готовиться к будущему. И вы всегда можете проверить, что ваши данные ограничены 7-битным ASCII для любой устаревшей системы, которую вы должны поддерживать, даже при этом наслаждаясь некоторыми преимуществами полного хранения Unicode.

Джеффри Л Уитледж
источник
8
Это отличная информация, чтобы иметь. Итак, правильно ли я понимаю это, если сделаю вывод, что выбор в конечном итоге становится одним из - какой ресурс дешевле: процессор + накладные расходы на разработку или хранилище?
Мэтт Кашатт
141
@MatthewPatrickCashatt - Вы можете видеть это таким образом. Но если вы представляете великолепный мир, в котором все текстовые данные находятся в Юникоде, и разработчикам просто не нужно думать о том, в чем заключается кодировка чего-либо, а целый класс ошибок просто никогда не возникает, то вы можете увидеть, что существует на самом деле нет выбора вообще.
Джеффри Л Уитледж
8
@Martin Smith - В этих случаях крошечное преимущество, которое предоставляет varchar (компактное хранилище), исчезает. Я думаю, VARCHAR даже хуже, чем я думал!
Джеффри Л Уитледж
9
@PeterAllenWebb - Вы можете «хранить» любые данные Unicode, потому что суррогатные пары в UTF-16 могут храниться в UCS-2, как если бы они были символами. Это будет работать прозрачно для хранения и поиска данных. Теперь то, что вы не можете сделать, это получить надежные преобразования и сравнения случаев за пределами BMP, но я не претендовал на это. Поэтому, если у вас есть много текста десерта, который вы хотите обработать, было бы лучше сделать это вне базы данных. Но это просто хорошо для хранения там. (Конечно, varchar вам там тоже не поможет!)
Джеффри Л. Уитледж
260

varchar : переменная длина, не символьные данные Unicode. Сортировка базы данных определяет, на какой кодовой странице хранятся данные.

nvarchar : данные символов Unicode переменной длины. В зависимости от сопоставления базы данных для сравнения.

Вооружившись этими знаниями, используйте тот, который соответствует вашим входным данным (ASCII v. Unicode).

user7116
источник
5
Есть ли ограничение, что varchar не может хранить данные Unicode? Это все 1 и 0. Я могу сохранить китайский контент как VARCHAR просто отлично в моей БД. Я только указываю его UTF-8, хотя. Как это работает тогда?
Nishant
3
@ Хороший поздний ответ : конечно, вы можете хранить UTF-8 в varchar, но это нарушит строковые функции SQL Server. Если вы выполняете все поиски / преобразования в вашем приложении, тогда да, вы можете сделать это (но в чем выгода?). Только кодировка Unicode, поддерживаемая SS, является UCS-2 (да, не UTF-16 до SS2k16), и его строковые функции работают только с этой кодировкой. Кстати, как насчет индексов? Если вы хотите хранить произвольные данные, лучше использовать двоичный файл.
Адриано Репетти
Да, это просто нарушает функции поиска строк.
Nishant
8
Итак, вы знаете ... это не "работает". Это все равно, что записывать floatв intи отправлять: «Ну, конечно, десятичные дроби пропадают». Просто не надо.
user7116
70

Я всегда использую nvarchar, поскольку он позволяет всему, что я собираю, выдерживать практически любые данные, которые я к нему добавляю. Моя система CMS делает китайский случайно, потому что я использовал nvarchar. В наши дни любые новые приложения не должны беспокоиться о количестве необходимого места.

tags2k
источник
25
Идея о том, что новые приложения не должны касаться ограничений пространства, несколько недальновидна, и любой, кто имел дело с базами данных на уровне среднего и крупного предприятия, будет рад вам сказать, совершенно неверно.
Брат
60
Чтобы взять на себя смелость положить слова в рот tags2k, я думаю, что более точное утверждение может быть «все более маловероятно, что какие-либо новые приложения должны быть более обеспокоены требуемым пространством, чем они должны быть о интернационализации и других проблемах набора символов».
Коуэн
1
«В наши дни любые новые приложения не должны беспокоиться о количестве необходимого места». - Если только вы не используете бесплатное облачное хранилище, где платный план - БЫСТРЫЙ скачок в $ (см. Общие планы AppHarbor SQL Server).
Гандерс
3
@Ganders Вой! Вы здесь Обобщенные утверждения в лучшем случае только временно корректны. Вычислительная игра определенно является игрой на каруселях. Я определенно обеспокоен тем, сколько места я использую в Windows Azure CCP. Тем не менее, я бы "никогда" не использовал varchar вместо nvarchar. Ооо, я просто противоречил сам себе?
Ризм
1
@Rism, я полагаю, вы устранили любой риск противоречия с использованием цитат "never", по крайней мере, технически.
Smandoli
30

Это зависит от того, как был установлен Oracle. В процессе установки устанавливается опция NLS_CHARACTERSET. Вы можете найти его с помощью запроса SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'.

Если ваш NLS_CHARACTERSET является кодировкой Unicode, такой как UTF8, отлично. Использование VARCHAR и NVARCHAR практически одинаково. Хватит читать сейчас, просто сделай это. В противном случае, или если у вас нет контроля над набором символов Oracle, читайте дальше.

VARCHAR - Данные хранятся в кодировке NLS_CHARACTERSET. Если на том же сервере есть другие экземпляры базы данных, они могут быть для вас ограничены; и наоборот, так как вы должны поделиться настройкой. Такое поле может хранить любые данные, которые могут быть закодированы с использованием этого набора символов, и ничего больше . Например, если набор символов MS-1252, вы можете хранить только такие символы, как английские буквы, несколько букв с акцентом и некоторые другие (например, € и -). Ваше приложение будет полезно только для нескольких регионов, которые не могут работать нигде в мире. По этой причине это считается плохой идеей.

NVARCHAR - данные хранятся в кодировке Unicode. Каждый язык поддерживается. Хорошая идея.

Как насчет места для хранения? VARCHAR, как правило, эффективен, поскольку набор символов / кодировка были специально разработаны для конкретной локали. Поля NVARCHAR хранятся либо в кодировке UTF-8, либо в кодировке UTF-16, иронически основываются на настройке NLS. UTF-8 очень эффективен для "западных" языков, но при этом поддерживает азиатские языки. UTF-16 очень эффективен для азиатских языков, но при этом поддерживает «западные» языки. Если вас беспокоит объем памяти, выберите параметр NLS, чтобы Oracle использовал UTF-8 или UTF-16 в зависимости от ситуации.

Как насчет скорости обработки? Большинство новых платформ кодирования используют Unicode изначально (Java, .NET, даже C ++ std :: wstring много лет назад!), Поэтому, если поле базы данных VARCHAR, это заставляет Oracle конвертировать между наборами символов при каждом чтении или записи, что не очень хорошо. Использование NVARCHAR позволяет избежать преобразования.

Итог: используйте NVARCHAR! Это позволяет избежать ограничений и зависимостей, отлично подходит для хранения и, как правило, лучше всего подходит для производительности.

Джереми Фрэнк
источник
42
Это действительно хороший ответ, за исключением того, что вопрос о sql-сервере.
стимулирует
21

nvarchar хранит данные как Unicode, поэтому, если вы собираетесь хранить многоязычные данные (более одного языка) в столбце данных, вам нужен вариант N.

albertein
источник
16

Мои два цента

  1. Индексы могут давать сбой, если не используются правильные типы данных:
    В SQL Server: если у вас есть индекс по столбцу VARCHAR и вы указываете его в виде строки Unicode, SQL Server не использует этот индекс. То же самое происходит, когда вы представляете BigInt для индексированного столбца, содержащего SmallInt. Даже если BigInt достаточно мал, чтобы быть SmallInt, SQL Server не может использовать индекс. С другой стороны, у вас нет этой проблемы (при предоставлении SmallInt или Ansi-Code для индексированного столбца BigInt или NVARCHAR).

  2. Типы данных могут различаться в разных СУБД (Система управления
    базами данных): Знайте, что каждая база данных имеет немного разные типы данных, и VARCHAR не означает, что везде одинаково. В то время как SQL Server имеет VARCHAR и NVARCHAR, база данных Apache / Derby имеет только VARCHAR, и там VARCHAR находится в Unicode.

incomudro
источник
Но, безусловно, если вы пишете свой код правильно (то есть с помощью параметризованных запросов и т. Д.), То пункт 1 представляет меньший риск.
Пол
14

В основном nvarchar хранит символы Unicode, а varchar хранит символы не Unicode.

«Unicodes» означает 16-битную схему кодирования символов, позволяющую кодировать символы из множества других языков, таких как арабский, иврит, китайский, японский, в одном наборе символов.

Это означает, что unicodes использует 2 байта на символ для хранения, а nonunico использует только один байт на символ для хранения. Это означает, что для хранения юникодов требуется двойная емкость по сравнению с не-юникодами.

Ранджит Павар
источник
10

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

Майк Спросс
источник
10

Я бы сказал, это зависит.

Если вы разрабатываете настольное приложение, в котором ОС работает в Unicode (как и во всех современных системах Windows), а язык поддерживает Unicode (по умолчанию используются Unicode, как в Java или C #), тогда переходите к nvarchar.

Если вы разрабатываете веб-приложение, в котором строки представлены как UTF-8, а язык - это PHP, который все еще не поддерживает Unicode (в версиях 5.x), тогда varchar, вероятно, будет лучшим выбором.

sleepy012
источник
9

Несмотря на то, что NVARCHARхранит Unicode, вы должны рассмотреть с помощью сопоставления также вы можете использовать VARCHARи сохранять свои данные на местных языках.

Просто представьте следующий сценарий.

Сортировка вашей базы данных - персидская, и вы сохраняете значение типа «علی» (персидское письмо Али) в VARCHAR(10)типе данных. Проблем нет, и СУБД использует для хранения только три байта.

Однако, если вы хотите перенести свои данные в другую базу данных и увидеть правильный результат, ваша база данных назначения должна иметь такое же сопоставление, что и цель, которая в данном примере является персидской.

Если ваша целевая сортировка отличается, вы видите некоторые знаки вопроса (?) В целевой базе данных.

Наконец, помните, что если вы используете огромную базу данных, предназначенную для использования вашего местного языка, я бы рекомендовал использовать местоположение вместо использования слишком большого количества пробелов.

Я считаю, что дизайн может быть другим. Это зависит от среды, в которой вы работаете.

Али Элми
источник
8

Я взглянул на ответы, и многие, кажется, рекомендуют использовать их nvarcharзаново varchar, потому что пространство больше не является проблемой, поэтому нет ничего плохого в том, чтобы включить Unicode для небольшого дополнительного хранилища. Ну, это не всегда так, когда вы хотите применить индекс к вашему столбцу. SQL Server имеет ограничение в 900 байтов на размер поля, которое вы можете индексировать. Так что если у вас есть, varchar(900)вы можете индексировать его, но нет varchar(901). С nvarcharпомощью количество символов уменьшается вдвое, так что вы можете индексировать до nvarchar(450). Так что, если вы уверены, что вам не нужно nvarchar, я не рекомендую использовать его.

В целом, в базах данных я рекомендую придерживаться нужного размера, потому что вы всегда можете расширить. Например, коллега по работе однажды подумал, что использование nvarchar(max)столбца не вредно, поскольку у нас вообще нет проблем с хранилищем. Позже, когда мы попытались применить индекс к этому столбцу, SQL Server отклонил это. Однако, если бы он начал с четного varchar(5), мы могли бы позже просто расширить его до того, что нам нужно, без такой проблемы, которая потребует от нас составления плана миграции на месте, чтобы решить эту проблему.

Рафид
источник
7

nVarchar поможет вам хранить символы Unicode. Это путь, если вы хотите хранить локализованные данные.

Виджеш В.П.
источник
7

Если для хранения символа используется один байт, существует 256 возможных комбинаций, и, таким образом, вы можете сохранить 256 различных символов. Сортировка - это шаблон, который определяет символы и правила, по которым они сравниваются и сортируются.

1252, который является Latin1 (ANSI), является наиболее распространенным. Однобайтовые наборы символов также не подходят для хранения всех символов, используемых многими языками. Например, некоторые азиатские языки имеют тысячи символов, поэтому они должны использовать два байта на символ.

Стандарт Юникод

Когда в сети используются системы, использующие несколько кодовых страниц, становится сложно управлять связью. Чтобы стандартизировать вещи, консорциум ISO и Unicode представил Unicode . Unicode использует два байта для хранения каждого символа. Таким образом, можно определить 65 536 различных символов, поэтому почти все символы могут быть покрыты Unicode. Если два компьютера используют Unicode, каждый символ будет представлен одинаково и преобразование не требуется - это идея Unicode.

SQL Server имеет две категории типов символьных данных:

  • не Unicode (char, varchar и текст)
  • Юникод (nchar, nvarchar и ntext)

Если нам нужно сохранить символьные данные из нескольких стран, всегда используйте Unicode.

Джитин Шаджи
источник
6

Я должен сказать здесь (я понимаю, что я, вероятно, собираюсь открыть себя для планки!), Но, безусловно, единственный раз, когда NVARCHARна самом деле более полезен (заметьте, что больше !), Чем VARCHARкогда все сопоставления на всех зависимых систем и внутри самой базы данных одинаковы ...? Если нет, то преобразование сопоставления должно произойти в любом случае и делает его таким VARCHARже жизнеспособным, как и NVARCHAR.

Чтобы добавить к этому, некоторые системы баз данных, такие как SQL Server (до 2012 года), имеют размер страницы ок. 8K. Таким образом, если вы хотите хранить данные для поиска, которые не хранятся в чем-то подобном поле TEXTили, NTEXTто вам VARCHARпредоставляется пространство NVARCHARв 8 Кбайт, тогда как только 4 Кбайт (удваивает байты, удваивает пробел).

Подводя итог, я полагаю, что использование любого из них зависит от:

  • Проект или контекст
  • инфраструктура
  • Система баз данных
Павел
источник
6

Следуйте разнице между Sql Server VARCHAR и типом данных NVARCHAR . Здесь вы можете увидеть очень наглядно.

В общем случае nvarchar хранит данные как Unicode, поэтому, если вы собираетесь хранить многоязычные данные (более одного языка) в столбце данных, вам нужен вариант N.

Прадип Кешарвани
источник
Это очень полезная ссылка, но ваш ответ не намного важнее: ссылка.
RubberDuck
ckuhn203, я не собираюсь рассказывать вам об этом
Прадип Кешарвани,
6

Основное различие между Varchar(n)и nvarchar(n)является: введите описание изображения здесь

VarcharРазмер данных переменной длины, отличных от символов Юникода, составляет до 8000. 1. Это тип данных переменной длины

  1. Используется для хранения не-Unicode символов

  2. Занимает 1 байт пространства для каждого символа

введите описание изображения здесь

Nvarchar: Символьные данные Unicode переменной длины.

1. Это тип данных переменной длины

2. Используется для хранения символов Юникода.

  1. Данные хранятся в кодировке Unicode. Каждый язык поддерживается. (например, языки арабский, немецкий, хинди и т. д. и т. д.)
Дебендра Дэш
источник
6

Джеффри Л Уитледж с оценкой репутации ~ 47000 рекомендует использовать nvarchar

Соломон Рутцки с оценкой репутации ~ 33200 рекомендует: НЕ всегда использовать NVARCHAR. Это очень опасный и часто дорогостоящий подход / подход.

Каковы основные различия в производительности между типами данных SQL Server varchar и nvarchar?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

Оба человека с такой высокой репутацией, что выбирает обучающийся разработчик базы данных SQL Server?

В ответах и ​​комментариях содержится много предупреждений о проблемах производительности, если вы не согласны с выбором.

Есть комментарии pro / con nvarchar для производительности.

Есть комментарии pro / con varchar для производительности.

У меня есть особые требования к таблице со многими сотнями столбцов, что само по себе, вероятно, необычно?

Я выбираю varchar, чтобы не приближаться к пределу размера записи таблицы в 8060 байт в SQL * server 2012.

Использование nvarchar для меня превышает ограничение в 8060 байт.

Я также думаю, что я должен сопоставить типы данных связанных кодовых таблиц с типами данных первичной центральной таблицы.

Я видел использование столбца varchar на этом рабочем месте, правительство Южной Австралии, предыдущими опытными разработчиками баз данных, где число строк таблицы будет составлять несколько миллионов или более (и очень мало столбцов nvarchar, если таковые имеются, в этих очень больших таблицы), поэтому, возможно, ожидаемые объемы строк данных становятся частью этого решения.

Аллан Ф
источник
1

nvarcharбезопасен в использовании по сравнению с varcharтем, чтобы сделать наш код без ошибок (несоответствие типов), потому что nvarcharдопускает также символы Юникода. Когда мы используем whereусловие в запросе к SQL Server и если мы используем =оператор, он несколько раз выдаст ошибку. Вероятная причина этого заключается в том, что наш столбец отображения будет отличаться varchar. Если бы мы определили это в nvarcharэтой проблеме, то моей не случилось бы. Тем не менее, мы придерживаемся varcharэтой проблемы и избегаем ее, поэтому лучше использовать LIKEключевое слово, чем =.

Риной Ашокан
источник