Oracle nls параметры как посмотреть
I знать , как набор символов базы данных ( NLS_CHARACTERSET в select * from v$nls_parameters; ) и набор символов клиента (настройка клиентской среды NLS_LANG ).
Однако я не могу узнать, как или если я могу определить для установленного сеанса , что Oracle считает, что текущий набор символов клиента.
Возможно ли это вообще?
Примечание: SELECT * FROM NLS_SESSION_PARAMETERS; not включает набор символов (на 10g2).
Чтобы полностью понять, чего я хотел бы сделать:
- NLS_LANG устанавливается в клиентской среде на произвольное значение (например, GERMAN_GERMANY.WE8MSWIN1252 )
- Приложение базы данных [*] запускает и устанавливает соединение /сеанс с базой данных Oracle.
- Приложение базы данных [*] хочет «спросить» Oracle (а не его ОС), что предполагает набор символов клиента Oracle.
[*]: Если приложение db является sqlplus, пример будет выглядеть следующим образом:
Примечание Джека в его ответе поднимает два важных момента:
- С Oracle, кто выполняет перевод символов. Это код клиентской библиотеки или выполняется на стороне сервера?
- Как представляется, клиенту, client нужно будет разоблачить этот параметр - то, что клиентский lib /tool предполагает этот параметр. Есть ли какие-либо из клиентских библиотек /инструментов Oracle (sqlplus, OCI /OCCI, Pro * C, . ), которые могут быть запрошены для того, что он считает этим параметром?
2 ответа
Я немного сомневаюсь, что это именно то, что вы ищете, но
показывает клиентскую переменную среды nls_lang на клиенте.
Я не думаю, что будет SQL-запрос, который вы можете запустить, чтобы дать «текущий» параметр, потому что AFAIK сервер не знает, какой перевод сделан на стороне клиента, поэтому любая команда для отображения текущей настройки будет иметь быть родным для клиента - я использовал SQL Developer для указанной выше команды, но я предполагаю, что она будет работать одинаково в SQL * Plus
только клиент знает свой набор символов - он недоступен "в база данных "
набор символов описывает, что хранится в базе данных.
клиент делает свой желаемый перевод знака знака [sic] в базу данных через NLS_LANG settting.
Если вы были на 11.1+, у вас может быть радость с v $ session_connect_info, потому что:
Эта информация выводится OCI на сервер при входе в систему.
Но я обнаружил, что все равно будет зависеть от того, как вы подключаетесь, например, из Тонкого драйвера JDBC вы не используете OCI, и поэтому информация не нажата
Итак, многие путаются в подарке с кодировками, особенно жертвы маркетинга Билла Гейтса.
NLS_LANG - параметр клиентской части . Т.е. он используется для подключения клиента. Сопоставлять этот параметр на сервере и клиенте нет смысла. На сервере он только для клиентской части, подключающейся локально.
NLS_LANG может выставляться через переменные окружения и через реестр Windows. Приоритетным считается выставление переменных окружения. Именно через них я и предпочитаю выставлять NLS_LANG, собственно, рекомендую. С реестром много нюансов, начиная с того, что там идет дробление по HOME и заканчивая тем, что винда иногда ветку не может прочитать.
В настоящий момент на территории России в ходу следующие варианты префиксов:
AMERICAN_AMERICA
RUSSIAN_CIS
RUSSIAN_RUSSIA
собственно, RUSSIAN_CIS устарела достаточно давно, однако, старые клиенты все еще используют этот префикс. Мне кажется, что RUSSIAN_CIS используют клиенты до 11 версии, могу ошибаться - поправьте, пожалуйста. Главное - помнить об этом моменте.
О кодировках. В России, соответственно, чаще всего используются:
AL32UTF8 - UTF-8, это Linux
CL8MSWIN1251 - Windows-1251
RU8PC866 - Windows в консоли
CL8ISO8859P5 - кодировка, например, используемая ЦФТ на Solaris
Если вы ошибетесь в написании параметра или его значения, он будет проигнорирован. В некоторых случаях sqlplus будет ругаться.
В общем и целом могу порекомендовать на сервере использовать префикс AMERICAN_AMERICA, кодировку, совпадающую с кодировкой базы, выставляя это глобальной переменной.
Например, для Супермага это
На клиенте все немного сложнее, поскольку клиент может стоять не один, с репортсами и прочим. Вообще по умолчанию клиентская часть и так нормально работает. Если же нет - лучше смотреть в каждом конкретном случае.
По умолчанию Oracle выводит даты в формате DD-MON-YY, где YY - две последние цифры года:
select sysdate from dual;
При вставке в таблицу значений типа date, по умолчанию можно использовать литерал в формате
DD-MON-YYYY
(две цифры номера дня, три буквы месяца и четыре цифры года)
или использовать ключевое слово DATE для передачи в базу литерала типа data в формате ANSI
YYYY-MM-DD
(четыре цифры года, две цифры месяца, две цифры номера дня)
insert into t1 (d) values ( DATE '1971-04-28');
Конвертация даты в строку:
select to_char(sysdate) from dual;
select to_char(sysdate, 'DD') from dual; -- день
select to_char(sysdate, 'MONTH') from dual; --месяц
select to_char(sysdate, 'YYYY') from dual; -- год
select to_char(sysdate, 'HH24:MI:SS') from dual; -- часы, минуты, секунды
select to_char(sysdate, 'DD MONTH YYYY HH24:MI:SS') from dual; -- комбинация параметров формата
02 ИЮЛЬ 2014 17:00:51
select to_char(sysdate, 'CC') from dual; -- двузначное столетие (век)
select to_char(sysdate - 1000000, 'SCC') from dual; -- двузначное столетие (век), со знаком минус до нашей эры
select to_char(sysdate, 'Q') from dual; -- однозначный квартал года
Немного о стандарте ISO.
В стандарте ISO, год, относящийся к номеру недели ISO, может отличаться от календарного года.
1 января 1988 года попадает на 53-ю неделю ISO для 1987 года.
Неделя всегда начинается с понедельника и заканчивается воскресеньем.
Как связан год с номером недели по стандарту ISO:
Если 1 января падает на пятницу, субботу или воскресенье, то неделя, включающая 1 января,
считается последней неделей предыдущего года, потому что большинство дней этой недели
принадлежат предыдущему году.
Если 1 января падает на понедельник, вторник, среду или четверг, то эта неделя считается
первой неделей нового года, потому что большинство дней этой недели принадлежат новому году.
1 января 1991 падает на вторник, поэтому неделя с понедельника, 31 декабря 1990 по воскресенье, 6 января 1991 считается неделей 1.
Чтобы получить номер недели ISO, используйте маску формата 'IW' для номера недели и одну из масок вида 'IY' для года.
select to_char( DATE '1991-01-01', 'YYYY WW') from dual; -- в обычном календарном формате
select to_char( DATE '1991-01-01', 'IYYY IW') from dual; -- в формате по ISO
в данном случае результаты совпадают.
Попробуем с другой датой:
Как видим результаты разные.
При вставке в таблицу даты, рекомендуется указывать все четыре цифры года.
Если указать только две последние цифры года, то две первые цифры (столетие)
Oracle будет интерпретировать в зависимости от того, какой формат был использован при вводе.
Если использовать формат YY, то в качестве столетия будет использовано текущее столетие,
которое в настоящее время установлено на сервере.
Неважно какой год мы указали, столетие всегда будет текущее (т.е. 20)
Если использовать формат YYYY но при этом указать только две последние цифры года
то в качестве столетия Oracle подставит нули (т.е. 00)
Если использовать формат RR и указать только две последние цифры года, то две первые цифры (столетие)
Oracle будет вычислять по следующим правилам:
Если указанный год находится в интервале от 00 до 49 и текущий год тоже попадает в этот интервал,
то столетие будет текущим, но если при этом текуший год будет находится в интервале от 50 до 99,
то столетие при этом будет увеличено на 1 (текущее столетие + 1).
Если указанный год находится в интервале от 50 до 99 и текущий год тоже попадает в этот интервал,
то столетие будет текущим, но если при этом текуший год будет находится в интервале от 00 до 49,
то столетие при этом будет уменьшено на 1 (текущее столетие - 1).
Вобщем запомнить легко, если указанный год, больше текущего диапазона, значит столетие уменьшаем
и наоборот если указанный год, меньше текущего диапазона, значит столетие увеличиваем.
Интересно, а что будет если использовать формат RRRR, но при этом указать только две последние цифры года:
В качестве столетия Oracle не подставил нули, вывод аналогичен формату RR.
Для выделения первой цифры столетия в формате года можно использовать запятую:
select to_char(sysdate, 'Y,YYY') from dual; -- год с разделителем
Допустимые форматы года:
select to_char(sysdate, 'YYYY IYYY RRRR SYYYY Y,YYY YYY IYY YY IY RR Y I') from dual; -- год в различных форматах
2014 2014 2014 2014 2 014 014 014 14 14 14 4 4
А также год прописью:
select to_char(sysdate, 'YEAR') from dual; -- в верхнем регистре
select to_char(sysdate, 'Year') from dual; -- каждое слово с большой буквы
Форматы месяца:
select to_char(sysdate, 'MM') from dual; -- двузначный номер месяца
select to_char(sysdate, 'MONTH') from dual; -- полное название в верхнем регистре
select to_char(sysdate, 'Month') from dual; -- полное название с большой буквы
select to_char(sysdate, 'MON') from dual; -- три первые буквы в верхнем регистре
select to_char(sysdate, 'Mon') from dual; -- три первые буквы с большой буквы
select to_char(sysdate, 'RM') from dual; -- римскими цифрами
Форматы недели:
select to_char(sysdate, 'WW') from dual; -- двузначный номер недели года
select to_char(sysdate, 'IW') from dual; -- двузначный номер недели года по ISO
select to_char(sysdate, 'W') from dual; -- однозначный номер недели месяца
Форматы дня:
select to_char(sysdate, 'DDD') from dual; -- трехзначный номер дня года
select to_char(sysdate, 'DD') from dual; -- двузначный номер дня месяца
select to_char(sysdate, 'D') from dual; -- однозначный номер дня недели
select to_char(sysdate, 'DAY') from dual; -- полное название дня в верхнем регистре
select to_char(sysdate, 'Day') from dual; -- полное название дня с заглавной буквы
select to_char(sysdate, 'DY') from dual; -- первые две буквы названия в верхнем регистре
select to_char(sysdate, 'Dy') from dual; -- первые две буквы названия с заглавной буквы
select to_char(sysdate, 'J') from dual; -- Юлианский день - число дней, прошедшее с 1 января 4713 г. до нашей эры
Формат часов:
select to_char(sysdate, 'HH24') from dual; -- двузначный номер часа в 24 часовом формате
select to_char(sysdate, 'HH24 PM') from dual; -- с суффиксом
select to_char(sysdate, 'HH') from dual; -- двузначный номер часа в 12 часовом формате
select to_char(sysdate, 'HH PM') from dual; -- с суффиксом
select to_char(sysdate, 'HH A.M.') from dual; -- с суффиксом
Форматы минут:
select to_char(sysdate, 'MI') from dual; -- двузначное количество минут
Форматы секунд:
select to_char(sysdate, 'SS') from dual; -- двузначное количество секунд
Существует тип TIMESTAMP, который может хранить дробную часть секунд.
Необязательную точность представления секунд можно определить параметром FF[1..9]
Значение этого параметра по умолчанию равно 6 (справа от десятичной точки секунд можно поместить до 6 цифр)
При попытке поместить большее количество цифр в дробную часть секунд, значение дробной части будет округлено.
SELECT TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI.SS.FF') FROM dual; -- шесть цифр после десятичной точки (по умолчанию)
2014-10-18 08:55.42.050000
SELECT TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI.SS.FF3') FROM dual; -- три цифры после десятичной точки
2014-10-18 08:56.23.606
SELECT TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI.SS.FF9') FROM dual; -- девять цифр после десятичной точки
2014-10-18 08:56.55.526000000
select to_char(sysdate, 'SSSSS') from dual; -- число секунд отсчитываемое от полуночи
В отчетах statspack применяются следующие обозначения долей секунд:
second (s)
centisecond (cs) - 100th of a second
millisecond (ms) - 1,000th of a second
microsecond (us) - 1,000,000th of a second
Символы, позволяющие разделять аспекты дат и времени.
- / , . ; : или любой текст в кавычках "текст"
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI.SS') FROM dual;
2014-10-18 14:30.43
SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD;HH24 "часов" MI "минут" SS "секунд"') FROM dual;
2014/10/18;14 часов 31 минут 18 секунд
AM или PM (A.M. или P.M.)
00:00 (полночь) 12:00 a.m.* (полночь)
12:00 (полдень) 12:00 p.m.* (полдень)
Проблемы в обозначениях полудня и полуночи:
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI.SS AM') FROM dual;
2014-10-18 14:53.58 PM
AD или BC (A.D. или B.C.)
BC - до нашей эры
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI.SS BC') FROM dual;
2014-10-18 15:00.25 Н.З.
TH - суффикс для чисел
SELECT TO_CHAR(SYSDATE, 'DDTH') FROM dual;
SELECT TO_CHAR(SYSDATE, 'ddTH') FROM dual;
SELECT TO_CHAR(SYSDATE, 'mmTH') FROM dual;
SELECT TO_CHAR(SYSDATE, 'YYYYTH') FROM dual;
SELECT TO_CHAR(SYSDATE, 'yyyyTH-MMTH-DDTH HH24TH:miTH.SSTH BC') FROM dual;
2014th-10TH-18TH 17TH:56th.52ND Н.З.
SP - числовые значения записываются словами
SELECT TO_CHAR(SYSDATE, 'DDSP') FROM dual;
SELECT TO_CHAR(SYSDATE, 'ddSP') FROM dual;
SELECT TO_CHAR(SYSDATE, 'mmTHSP') FROM dual;
SELECT TO_CHAR(SYSDATE, 'mmSP') FROM dual;
SELECT TO_CHAR(SYSDATE, 'YYYYTHSP') FROM dual;
TWO THOUSAND FOURTEENTH
SELECT TO_CHAR(SYSDATE, 'YYYYSP') FROM dual;
TWO THOUSAND FOURTEEN
EE - Полное название эпохи для японского календаря, календаря КНР и буддийского календаря.
E - Сокращенное название эпохи
select TO_DATE('H19-01-01' , 'EYY-MM-DD' , 'NLS_CALENDAR=''JAPANESE IMPERIAL''') e_date
from dual;
select TO_DATE('平成19-01-01' , 'EEYY-MM-DD' , 'NLS_CALENDAR=''JAPANESE IMPERIAL''') ee_date
from dual;
Часовые пояса:
В Oracle с версии 9i появилась возможность использовать различные часовые пояса.
Часовой пояс - это смещение от времени по Гринвичу(GMT).
Но теперь оно называется Всемирное скоординированное время(UTC).
Часовой пояс определяется либо как смещение относительно UTC, либо по имени региона (названию часового пояса).
Получить названия часовых поясов можно так:
select * from v$timezone_names;
Africa/Abidjan LMT
Africa/Abidjan GMT
Africa/Accra LMT
Africa/Accra GMT
Africa/Accra GHST
Africa/Addis_Ababa LMT
Africa/Addis_Ababa ADMT
Africa/Addis_Ababa EAT
Africa/Algiers LMT
Africa/Algiers PMT
Africa/Algiers WET
.
При определении смещения используется формат HH:MI с префиксом в виде знака + или -
+/- HH:MI
Посмотрим какое смещение относительно UTC установлено в нашей БД:
select dbtimezone from dual;
(меняется параметром time_zone в spfile.ora)
Часовой пояс сеанса можно определить так:
select sessiontimezone from dual;
Europe/Moscow
Его легко можно поменять на время сеанса:
alter session set time_zone = 'PST';
select sessiontimezone from dual;
Стандартное Тихоокеанское время PST отстает от UTC на восемь часов.
Восточное стандартное время EST отстает от UTC на пять часов.
Текущую дату для сеанса в локальном часовом поясе можно определить так:
select current_date from dual;
select to_char(current_date, 'YYYY-MM-DD HH24:MI.SS' ) from dual;
sysdate() - возвращает значение даты и времени, установленных в ОС компьютера, на котором размещена БД.
current_date() - возвращает значение даты и времени для часового пояса вашего сеанса.
Для любого часового пояса можно найти величину смещения с помощью функции tz_offset().
select tz_offset('PST') from dual;
select tz_offset('Europe/Moscow') from dual;
TZH - время в часах часового пояса
TZM - минуты часового пояса
TZR - регион часового пояса
TZD - часовой пояс с информацией о переходе на летнее время
Tип TIMESTAMP, в отличие от типа DATE, может хранить информацию о часовых поясах.
select to_char(SYSTIMESTAMP, 'TZH:TZM') from dual;
select to_char(SYSTIMESTAMP, 'TZR') from dual;
select to_char(SYSTIMESTAMP, 'TZD') from dual;
select to_char(SYSTIMESTAMP, 'HH:MI:SS.FFTZH:TZM') from dual;
select to_char(SYSTIMESTAMP, 'YYYY-MM-DD HH:MI:SS TZH:TZM') from dual;
2014-10-18 10:52:19 +04:00
select to_char(SYSTIMESTAMP, 'YYYY-MM-DD HH:MI:SS.FF AM TZH:TZM TZR TZD') from dual;
2014-10-18 10:52:31.802000 PM +04:00 +04:00
Чтобы конвертировать дату-время из одного часового пояса к другому,
можно воспользоваться функцией NEW_TIME().
Конвертация строки в тип дата-время.
Функцию TO_DATE(x [, формат])
можно использовать для конвертирования строки x в тип дата-время.
Если строка формата опущена, то дата должна быть представлена в формате по умолчанию:
DD-MON-YYYY или DD-MON-YY
(Вообще формат даты по умолчанию определяет параметр БД NLS_DATE_FORMAT)
alter session set NLS_DATE_LANGUAGE = 'AMERICAN' ;
alter session set NLS_DATE_FORMAT = 'SYYYY-MM-DD' ;
alter session set NLS_TIMESTAMP_FORMAT = 'SYYYY-MM-DD HH24:MI:SS' ;
alter session set NLS_TIMESTAMP_TZ_FORMAT = 'SYYYY-MM-DD HH24:MI:SS TZH:TZM' ;
Можно и явно задать формат
select to_date('April 28, 1971' , 'MONTH DD, YYYY') from dual;
Совместное использование to_date() и to_char()
Формат даты по умолчанию, можно использовать и при вставке строк в таблицу:
alter session set NLS_DATE_FORMAT = 'DD-MON-YYYY';
NLS - параметры:
National language_support (До Oracle9i)
Globalisation support (Начиная с Oracle9i)
Кодировка устанавливается только в переменных окружения!
Язык - RUSSIAN, AMERICAN
SELECT * FROM v$nls_valid_values
WHERE parameter = 'LANGUAGE'
ORDER BY value
CIS - СНГ
1. первый день недели
2. символ национальной валюты
(Если явно не задан параметр NLS_CURRENCY)
3. Десятичный и групповой разделители чисел
SELECT * FROM v$nls_valid_values
WHERE parameter = 'TERRITORY'
ORDER BY value
SELECT * FROM v$nls_valid_values
WHERE parameter = 'CHARACTERSET'
-- Русский язык, Кириллица
AND (value LIKE 'CL%'
OR
value LIKE 'RU%')
ORDER BY value
WE8ISO8859P1 - Западная Европа
Какие есть параметры NLS?
SELECT * FROM nls_session_parameters
PARAMETER VALUE
================ ==========
NLS_LANGUAGE=AMERICAN
NLS_TERRITORY=CIS
-- Символ нац. валюты
NLS_CURRENCY='р.'
-- Символ нац. валюты по стандарту ISO
NLS_ISO_CURRENCY='CIS'
-- Десятичный разделитель и разделитель групп
NLS_NUMERIC_CHARACTERS=', '
-- Календарь
NLS_CALENDAR=GREGORIAN
-- Формат ввода и вывода даты по-умолчанию
NLS_DATE_FORMAT='DD.MM.RR'
-- Язык для вывода названий месяцев и дней недели
NLS_DATE_LANGUAGE='AMERICAN'
-- Тип Сортировки
NLS_SORT=BINARY
-- . (нет описания)
NLS_TIME_FORMAT='HH24:MI:SSXFF'
-- Формат ввода и вывода даты типа TIMESTAMP по-умолчанию
NLS_TIMESTAMP_FORMAT='DD.MM.RR HH24:MI:SSXFF'
-- . (нет описания)
NLS_TIME_TZ_FORMAT='HH24:MI:SSXFF TZR'
-- Формат ввода и вывода даты типа TIMESTAMP с временнОй зоной по-умолчанию
NLS_TIMESTAMP_TZ_FORMAT='DD.MM.RR HH24:MI:SSXFF TZR'
-- Замещает символ нац. валюты, установленный по умолчанию параметром NLS_TERRITORY
NLS_DUAL_CURRENCY='р.'
-- Как сравнивать строки BINARY или ASCII (по правилам нац. алфавита)
NLS_COMP=BINARY
-- CHAR по умолчанию в байтах или в символах
NLS_LENGTH_SEMANTICS=BYTE
-- NLS_NCHAR_CONV_EXCP determines whether an error is reported when there is
-- data loss during an implicit OR explicit CHARACTER TYPE conversion.
-- The DEFAULT value results IN no error being reported.
NLS_NCHAR_CONV_EXCP=FALSE
Как можно устанавливать значения параметров NLS?
1. В системном реестре Windows
2. Установить переменные окружения
Для Windows (в bat-файле)
SET NLS_DATE_LANGUAGE=RUSSIAN
SET NLS_LANG=AMERICAN_CIS.CL8MSWIN1251
sqlplus .
3. ALTER SESSION SET
NLS_DATE_LANGUAGE=RUSSIAN
NLS_DATE_FORMAT='DD.MM.YYYY';
SELECT TO_CHAR(SYSDATE, 'Month day')
FROM dual
Посмотреть nls-параметры сессии, базы данных и инстанса можно так:
select * from
(select 'SESSION' SCOPE,s.* from nls_session_parameters s
union
select 'DATABASE' SCOPE,d.* from nls_database_parameters d
union
select 'INSTANCE' SCOPE,i.* from nls_instance_parameters i
) a
pivot (LISTAGG(VALUE) WITHIN GROUP (ORDER BY SCOPE)
FOR SCOPE
in ('SESSION' as "SESSION",'DATABASE' as "DATABASE",'INSTANCE' as "INSTANCE"));
Функции для работы с типом data.
ADD_MONTHS(data, n)
Позволяет добавить к дате целое количество месяцев (или отнять, если n отрицательное)
SELECT ADD_MONTHS('28.04.1971' , 13) FROM DUAL; -- Добавить 13 месяцев
SELECT ADD_MONTHS('28.04.1971' , -12) FROM DUAL; -- Отнять 12 месяцев
До разработки стандарта Юникод существовало множество схем кодировки, которые обладали ограниченными возможностями, а порой и конфликтовали друг с другом. Разработка глобальных приложений по единым правилам была практически невозможна, потому что ни одна кодировка не поддерживала все символы.
Стандарт Юникод решает все эти проблемы. Он разрабатывается и сопровождается Консорциумом Юникода. Содержимое каждой версии определяется Стандартом Юникода и Базой данных символов Юникода, или USD (Unicode Character Database).
Набор символов Юникода позволяет хранить и извлекать данные в более чем 200 различных отдельных наборах. Использование набора символов Юникода обеспечивает поддержку всех этих наборов без внесения архитектурных изменений в приложение.
- Oracle11g Release 2 поддерживает Юникод версии 5.0. Этот стандарт, впервые опубликованный в 2006 году, обеспечивает кодирование более одного миллиона символов. Этого достаточно для поддержки всех современных символов, а также многих древних или малораспространенных алфавитов. Oracle Database 12c включает поддержку Юникода 6.1 (стандарт опубликован в январе 2012 г.) и вводит несколько новых лингвистических порядков сопоставления, соответствующих правилам UCA (Unicode Conation Algorithm).
- Наборы символов Юникода в Oracle11g включают кодировки UTF-8 и UTF-16 . В UTF-8 для представления символа используется 1, 2 или 3 байта в зависимости от символа. В UTF-16 символ всегда представляется двумя байтами. В обеих схемах поддерживаются дополнительные символы, использующие 4-байтовое представление независимо от выбранного набора символов Юникода.
- Наборы символов Юникода в Oracle Database 11g и 12c включают кодировки UTF-8 и UTF-16 . В UTF-8 символы представляются 1, 2 или 3 байтами в зависимости от символа. В UTF-16 все символы представляются 2 байтами. Дополнительные символы поддерживаются обеими кодировками и представляются 4 байтами на символ независимо от выбранной кодировки.
Каждая база данных Oracle имеет два набора символов. Первичный набор символов используется для большинства функций приложений, а отдельный набор символов NLS — для типов данных и функций, специфических для NLS . Для определения используемых наборов символов используется следующий запрос:
В данном случае параметр NLS_CHARACTERSET (первичный набор символов базы данных) имеет значение AL32UTF8 . В этот 32-разрядный набор символов Юникода UTF-8 входит большинство самых распространенных символов в мире. Параметр NLS_NCHAR_ CHARACTERSET , используемый прежде всего для столбцов NCHAR и NVARCHAR2 , представляет собой 16-разрядный набор символов UTF-16 .
Структура имен, присваиваемых наборам символов в Oracle , содержит полезную информацию. Например, US7ASCII поддерживает символы английского языка для США. Набор символов AL32UTF8 поддерживает любые языки. Вторая часть строки определяет количество битов на символ. В US7ASCII символ представляется 7 битами, а AL32UTF8 использует до 32 бит на символ. Оставшаяся часть строки содержит «официальное» название набора символов. Структура имени представлена на рис. 1.
Рис. 1. Структура имени набора символов в Oracle
За дополнительной информацией о Юникоде обращайтесь на сайт Стандарта Юникод по адресу.
Типы данных и национальные наборы символов
Типы данных Globalization Support nclob , nchar и nvarchar2 используют набор символов, определяемый параметром nls_nchar_characterset , — вместо набора символов по умолчанию, устанавливаемого для базы данных в параметре nls_characterset . Эти типы данных поддерживают только многобайтовые символы Юникода, поэтому даже при работе с базой данных, в которой по умолчанию вместо Юникода используется другая кодировка, они будут хранить символы в национальном наборе символов. А так как национальный набор символов поддерживает только кодировки UTF-8 и UTF- 16 , NCLOB , NCHAR и NVARCHAR2 гарантированно будут хранить данные в многобайтовом Юникоде.
Прежде это создавало проблемы при сравнении столбцов nclob/nchar/nvarchar2 со столбцами clob/char/varchar2 . Во всех версиях, поддерживаемых в настоящее время, Oracle выполняет автоматическое преобразование, благодаря которому становится возможным корректное сравнение.
Кодировка символов
Выбор набора символов во время создания базы данных определяет тип кодировки символов. Каждому символу ставится в соответствие код, уникальный для данного символа (кодовая точка). Это значение является частью таблицы отображения символов Юникода, содержимое которой находится под контролем Консорциума Юникода.
Кодовые точки состоят из префикса U+ (или обратной косой черты \ ), за которым следует шестнадцатеричный код символа с диапазоном допустимых значений от U+0000 до U+10FFFF16 . Комбинированные символы (например, А ) могут разбиваться на компоненты (A с умляутом), а затем снова восстанавливаться в своем исходном состоянии. Скажем, декомпозиция А состоит из кодовых точек U+0041 (A) и U+0308 (умляут). В следующем разделе будут рассмотрены некоторые функции Oracle для работы с кодовыми точками.
Кодовой единицей ( code unit ) называется размер в байтах типа данных, используемого для хранения символов. Размер кодовой единицы зависит от используемого набора символов. В некоторых обстоятельствах кодовая точка слишком велика для одной кодовой единицы, и для ее представления требуется несколько кодовых единиц.
Конечно, пользователи воспринимают символы, а не кодовые точки или кодовые единицы. «Слово» \0053\0074\0065\0076\0065\006E вряд ли будет понятно среднему пользователю, который распознает символы на своем родном языке. Не забывайте, что глиф (изображение символа, непосредственно отображаемое на экране) является всего лишь представлением кодового пункта. Даже если на вашем компьютере не установлены необходимые шрифты или он по другим причинам не может вывести символы на экран, это вовсе не означает, что в Oracle соответствующая кодовая точка хранится некорректно.
Параметры Globalization Support (NLS)
Поведение Oracle по умолчанию определяется параметрами Globalization Support (NLS) . Значения параметров, задаваемые при создании базы данных, определяют многие аспекты ее работы — от наборов символов до используемых по умолчанию денежных единиц. В табл. 1 перечислены параметры, которые вы можете изменить в ходе сеанса, с примерами значений и пояснениями. За текущими значениями параметров в вашей системе обращайтесь к представлению NLS_SESSI0N_PARAMETERS .
Таблица 1. Сеансовые параметры NLS
Функции юникода
Поддержка Юникода в PL/SQL начинается с простейших строковых функций. Впрочем, в табл. 2 видны небольшие отличия этих функций от их хорошо известных аналогов.
К именам функций INSTR , LENGTH и SUBSTR добавляется суффикс B, C, 2 или 4; он означает, что функция работает с байтами, символами, кодовыми единицами или кодовыми точками соответственно.
Функции INSTR , LENGTH и SUBSTR используют семантику длины, связанную с типом данных столбца или переменной. Эти базовые функции и версии с суффиксом C часто возвращают одинаковые значения — до тех пор, пока вы не начнете работать со значениями NCHAR или NVARCHAR . Поскольку NLS_NCHAR_ CHARACTERSET и NLS_CHARACTERSET могут различаться, результат вызова INSTR , LENGTH и SUBSTR может отличаться (в зависимости от типа данных) от результата их символьных аналогов.
Таблица 2. Функции Юникода
Рассмотрим эти функции подробнее.
ASCIISTR
ASCIISTR пытается преобразовать полученную строку в ASCII -символы. Если строка содержит символы, отсутствующие в наборе ASCII , они представляются в формате \xxxx . Как будет показано ниже при описании функции DECOMPOSE , такое форматирование иногда оказывается очень удобным.
COMPOSE
Некоторые символы могут иметь несколько вариантов представления кодовых пунктов. Это создает проблемы при сравнении двух значений. Символ А может быть представлен как одним кодовым пунктом U+00C4 , так и двумя кодовыми пунктами U+0041 (буква A) и U+0308. При сравнении PL/SQL считает, что эти два варианта представления не равны.
Однако после использования функции COMPOSE эти две версии равны:
На этот раз сравнение дает другой результат:
DECOMPOSE
Как нетрудно догадаться, функция DECOMPOSE является обратной по отношению к COMPOSE : она разбивает составные символы на отдельные кодовые точки или элементы:
INSTR/INSTRB/INSTRC/INSTR2/INSTR4
Все функции INSTR возвращают позицию подстроки внутри строки и различаются лишь по способу определения позиции. Для демонстрации мы воспользуемся таблицей publication из схемы g11n .
Позиция символа У отличается только для INSTRB . Одна из полезных особенностей INSTR2 и INSTR4 заключается в том, что они могут использоваться для поиска кодовых точек, не представляющих полные символы. Возвращаясь к примеру с символом А, умляут можно включить как подстроку для выполнения поиска.
LENGTH/LENGTHB/LENGTHC/LENGTH2/LENGTH4
Функции LENGTH возвращают длину строки в разных единицах:
LENGTH — возвращает длину строки в символах;
LENGTHB — возвращает длину строки в байтах;
LENGTHC — возвращает длину строки в символах Юникода;
LENGTH2 — возвращает количество кодовых единиц в строке;
LENGTH4 — возвращает количество кодовых точек в строке.
Если строка состоит из композиционных символов, функция LENGTH эквивалентна LENGTHC .
В данном примере только функция LENGTHB дает другой результат. Как и ожидалось, LENGTH и LENGTHC вернули одинаковые результаты. Впрочем, при работе с декомпозиционными символами ситуация меняется. Пример:
Функции возвращают следующие значения длины:
Функция LENGTH возвращает количество символов, но считает A и умляут разными символами. LENGTHC возвращает длину в символах Юникода и видит только один символ.
SUBSTR/SUBSTRB/SUBSTRC/SUBSTR2/SUBSTR4
Разные версии SUBSTR определяются по тому же принципу, что и их аналоги у функций INSTR с LENGTH . SUBSTR возвращает часть строки заданной длины начиная с заданной позиции. Функции этого семейства работают следующим образом:
SUBSTR — определяет позицию и длину по символу;
SUBSTRB — определяет позицию и длину в байтах;
SUBSTRC — определяет позицию и длину в символах Юникода;
SUBSTR2 — использует кодовые единицы;
SUBSTR4 — использует кодовые точки.
Использование этих функций продемонстрировано в следующем примере:
Обратите внимание на отличие SUBSTRB от других функций в результатах выполнения сценария:
UNISTR
Функция UNISTR преобразует строку в Юникод. Эта функция использовалась в ряде предыдущих примеров для вывода символов строки, подвергнутой декомпозиции. В разделе «Кодировка символов» в качестве примера была приведена строка, состоящая из кодовых пунктов. Чтобы привести ее к понятному виду, можно воспользоваться функцией UNISTR :
Читайте также: