Разница между VARCHAR2 (10 CHAR) и NVARCHAR2 (10)
Я установил Oracle Database 10g Express Edition (Universal) с настройками по умолчанию:
SELECT * FROM NLS_DATABASE_PARAMETERS;
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16
Учитывая, что типы данных CHAR
и NCHAR
, похоже, принимают многобайтовые строки, какова точная разница между этими двумя определениями столбцов?
VARCHAR2(10 CHAR)
NVARCHAR2(10)
Ответы
Ответ 1
NVARCHAR2 datatype был введен Oracle для баз данных, которые хотят использовать Unicode для некоторых столбцов, сохраняя при этом другой набор символов для остальной базы данных (который использует VARCHAR2). NVARCHAR2 является типом данных только для Unicode.
Одна из причин, по которой вы, возможно, захотите использовать NVARCHAR2, может заключаться в том, что ваша БД использует набор символов, отличных от Юникода, и вы все же хотите иметь возможность хранить данные Unicode для некоторых столбцов без изменения основного набора символов. Другая причина может заключаться в том, что вы хотите использовать два набора символов Unicode (AL32UTF8 для данных, которые поступают в основном из Западной Европы, AL16UTF16 для данных, которые поступают в основном из Азии, например), поскольку разные наборы символов не будут хранить одинаковые данные одинаково эффективно.
Оба столбца в вашем примере (Unicode VARCHAR2(10 CHAR)
и NVARCHAR2(10)
) смогут хранить одни и те же данные, однако хранилище байтов будет другим. Некоторые строки могут храниться более эффективно в одном или другом.
Обратите внимание, что некоторые функции не будут работать с NVARCHAR2, см. этот вопрос SO:
Ответ 2
-
NVARCHAR2
хранит символьные данные переменной длины. При создании таблицы со NVARCHAR2
максимальный размер всегда находится в семантике длины символа, которая также является семантикой длины по умолчанию и единственной длины для NVARCHAR2
данных NVARCHAR2
.
NVARCHAR2
данных NVARCHAR2
использует AL16UTF16
символов AL16UTF16
который кодирует данные Unicode в UTF-16
. AL16UTF16
использует 2 bytes
для хранения символа. Кроме того, максимальная длина байта NVARCHAR2
зависит от настроенного национального набора символов.
-
VARCHAR2
Максимальный размер VARCHAR2
может быть в байтах или символах. Его столбец может хранить только символы в наборе символов по умолчанию, в то время как NVARCHAR2
может хранить практически любые символы. Для одного символа может потребоваться до 4 bytes
.
Определив поле как:
-
VARCHAR2(10 CHAR)
вы говорите Oracle, что он может использовать достаточно места для хранения 10 символов, независимо от того, сколько байтов требуется для хранения каждого из них. Для одного символа может потребоваться до 4 bytes
. -
NVARCHAR2(10)
вы говорите Oracle, что он может хранить 10 символов по 2 bytes
на символ
В итоге:
-
VARCHAR2(10 CHAR)
может хранить максимум 10 characters
и максимум 40 bytes
(зависит от настроенного набора национальных символов).
-
NVARCHAR2(10)
может хранить максимум 10 characters
и максимум 20 bytes
(зависит от настроенного национального набора символов).
Примечание: набор символов может быть UTF-8
, UTF-16
,....
Пожалуйста, ознакомьтесь с этим руководством для более подробной информации.
Хорошего дня!
Ответ 3
Я не думаю, что ответ от Винсента Малграта является правильным. Когда NVARCHAR2
был представлен давным-давно, никто даже не говорил о Unicode.
Первоначально Oracle предоставил VARCHAR2
и NVARCHAR2
для поддержки локализации. Общие данные (включая PL/SQL) хранились в VARCHAR2
, скорее всего, US7ASCII
в наши дни. Затем вы можете подать заявку NLS_NCHAR_CHARACTERSET
индивидуально (например, WE8ISO8859P1
) для каждого из ваших клиентов в любой стране, не затрагивая общую часть вашего заявления.
В настоящее время набор символов AL32UTF8
по умолчанию полностью поддерживает Unicode. На мой взгляд, сегодня больше нет причин использовать NLS_NCHAR_CHARACTERSET
, то есть NVARCHAR2
, NCHAR2
, NCLOB
. Обратите внимание, что все больше и больше нативных функций Oracle не поддерживают NVARCHAR2, поэтому вам следует избегать этого. Возможно, единственная причина в том, что вы должны поддерживать в основном азиатские символы, где AL16UTF16
потребляет меньше памяти по сравнению с AL32UTF8
.
Ответ 4
nVarchar2 - это Unicode-хранилище.
Хотя оба типа данных являются строковыми типами переменной длины, вы можете заметить разницу в том, как они хранят значения.
Каждый символ хранится в байтах. Как известно, не все языки имеют алфавиты одинаковой длины, например, английский алфавит нуждается в 1 байт за символ, однако для хранения символов персонажам, например, японскому или китайскому, требуется более 1 байт.
Когда вы указываете varchar2 (10), вы сообщаете БД, что будут сохранены только 10 байт данных. Но, когда вы говорите nVarchar2 (10), это означает, что будет сохранено 10 символов. В этом случае вам не нужно беспокоиться о количестве байтов, которые принимает каждый символ.
Ответ 5
Интересно, действуют ли NVARCHAR2 (1) и VARCHAR2 (1) по-другому относительно значения null/empty?
От тестирования, похоже, похоже.
Можно получить некоторые сюрпризы
то есть. сравнение пустой строки в!= 'Y' не вернет пустые строки строк.
т.е. пустая строка не имеет и не равна "Y"...
нужна функция обертки nvl
например
и nvl (верхний (WP. "OW_IS_MISRUN" ), 'N')!= 'Y'
выберите кол-(*)
из "DATA_HUB". "OW_WELL_PERFORATION" WP
где WP.UWI = 17038046
7
выберите count (*)
из "DATA_HUB". "OW_WELL_PERFORATION" WP
где WP.UWI = 17038046 и верхний (WP. "OW_IS_MISRUN" )!= 'Y'
1
выберите count (*)
из "DATA_HUB". "OW_WELL_PERFORATION" WP
где WP.UWI = 17038046 и верхний (WP. "OW_IS_MISRUN" ) = 'Y'
2
выберите count (*)
из "DATA_HUB". "OW_WELL_PERFORATION" WP
где WP.UWI = 17038046 и nvl (верхний (WP. "OW_IS_MISRUN" ), 'N')!= 'Y'
5