Давайте разберемся сначала с настройками клиентского компьютера. В настройках клиентской конфигурации есть два параметра NLS_TERRITORY и NLS_LANGUAGE.
NLS_LANGUAGE - задает язык, на котором будут выводиться серверные сообщения, названия месяцев, порядок сортировки для символьных данных и т.д.
NLS_TERRITORY - задает правила преобразования для ввода чисел, дат.
В системе Windows параметр надо смотреть в реестре.
Ветка:
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0
Параметр:
NLS_LANG
Значение (например, у меня):
american_america.CL8MSWIN1251
Если вы хотите все настроить по-русски, то установите параметр:
russian_cis
NLS_LANGUAGE=russian NLS_TERRITORY=cisФормат даты будет "DD.MM.YY".
Помимо пользовательских настроек хранения формата существуют также и серверные. Посмотреть их можно следующим запросом:
Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 Connected as scott SQL> select * from nls_database_parameters; PARAMETER VALUE ------------------------------ ---------------------------------------- NLS_LANGUAGE AMERICAN NLS_TERRITORY AMERICA NLS_CURRENCY $ NLS_ISO_CURRENCY AMERICA NLS_NUMERIC_CHARACTERS ., NLS_CHARACTERSET CL8MSWIN1251 NLS_CALENDAR GREGORIAN NLS_DATE_FORMAT DD-MON-RR NLS_DATE_LANGUAGE AMERICAN NLS_SORT BINARY NLS_TIME_FORMAT HH.MI.SSXFF AM NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR NLS_DUAL_CURRENCY $ NLS_COMP BINARY NLS_LENGTH_SEMANTICS BYTE NLS_NCHAR_CONV_EXCP FALSE NLS_NCHAR_CHARACTERSET AL16UTF16 NLS_RDBMS_VERSION 11.1.0.6.0 20 rows selected SQL>
Обратите внимание на параметр NLS_DATE_FORMAT. Он выставляется в зависимости от параметра NLS_TERRITORY. Изменяя значение NLS_TERRITORY, вы тем самым меняете NLS_DATE_FORMAT. А вот обратное не верно.
Параметр NLS_DATE_LANGUAGE зависит от NLS_LANGUAGE и их зависимости аналогичны представленным выше.
Вы, наверное, уже понимаете, что формат даты на сервере может отличаться от настроек на вашем клиентском рабочем месте. В этом случае некорректно написанная процедура, запущенная в клиентской сессии может обрабатывать даты без ошибок, а при запуске на сервере с помощью механизма оракловых заданий может выдавать ошибки.
Иногда полезно сравнить настройки базы с параметрами вашей сессии:
Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 Connected as scott SQL> select * from nls_session_parameters; PARAMETER VALUE ------------------------------ ---------------------------------------- NLS_LANGUAGE RUSSIAN NLS_TERRITORY RUSSIA NLS_CURRENCY р. NLS_ISO_CURRENCY RUSSIA NLS_NUMERIC_CHARACTERS , NLS_CALENDAR GREGORIAN NLS_DATE_FORMAT DD.MM.RR NLS_DATE_LANGUAGE RUSSIAN NLS_SORT RUSSIAN NLS_TIME_FORMAT HH24:MI:SSXFF NLS_TIMESTAMP_FORMAT DD.MM.RR HH24:MI:SSXFF NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR NLS_TIMESTAMP_TZ_FORMAT DD.MM.RR HH24:MI:SSXFF TZR NLS_DUAL_CURRENCY р. NLS_COMP BINARY NLS_LENGTH_SEMANTICS BYTE NLS_NCHAR_CONV_EXCP FALSE 17 rows selected SQL>
Как избежать ошибок, связанных с настройками формата даты?
Существуют несколько способов избежать ошибок, возникающих из-за различий в настройках формата даты пользователя и самой базы данных.
Во-первых вы можете использовать неявное преобразование.
Контролируйте (требуйте) правильной конфигурации сервера и рабочих мест. Пропишите нужные вам настройки в руководстве администратора и подобных ему документах.
Если вы решили использовать этот метод, то можете подстелить себе соломку. В начале каждой сессии выполняйте команду:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY';
Или сразу устанавливайте параметр NLS_TERRITORY:
ALTER SESSION SET NLS_TERRITORY = cis;
Для несерьезных приложений и маленьких систем этот метод вполне подходит, но он имеет недостатки. Например, не всем пользователям может понравиться ващ формат ввода дат, особенно если он отличается от настроек в операционной системы. А пользователи обычно "бузят", когда им неудобно.
Следующий способ - использовать функцию явного преобразования символьной строки в значение типа DATE. Формат ее очень прост: TO_DATE(строка с датой, строка с форматом).
Пользоваться функцией очень просто. Вставляйте её во всех местах, где вам нужно использовать константу с датой.
Строка с форматом допускает использование порядка 24 масок. Их полный перечень и подробное описание можно найти в документации. В приложении к этой статье есть памятка с наиболее ходовыми масками.
Через некоторое время вы изучите и запомните все основные форматы. И ещё...
...вы обнаружите некоторые недостатки "безудержного" применения TO_DATE.
Один из недостатков: неудобно использовать громоздкую запись. Другой: из-за череды механических преобразований запросы теряют свою лаконичность.
Кроме того, учтите - вставляя функцию TO_DATE в запросы и явно указывая в ней формат, вы либо осознанно жестко зашиваете строку с форматом в код приложения, либо вы готовы написать дополнительный код по выбору нужного формата в зависимости от каких-то условий.
Оба подхода имеют право на существование. Не будет рассуждать, какой из них лучше. Давайте рассмотрим третий способ преобразования.
Для того чтобы подставить значение даты в нужное место запроса, можно использовать механизм BIND-переменных.
BIND-переменные используютсядля подстановки значений в нужные места запроса. Обычно, для обозначения мест применяются маркеры с символом двоеточия. Например:
INSERT INTO invoice (doc_nd, doc_dd, cnt) VALUES( :1, :2, :3);
При использовании BIND-переменных за преобразование строк с датами в значение DATE отвечает приложение. Вернее сказать, инструментальное средство. Вся суета с преобразование и ответственность за его результат перекладывается с программиста на инструментальное средство.
Хотите узнать подробности? Сейчас расскажу, но прежде давайте представим, что для написание клиентской части вы выбрали какое-нибудь высокоуровневое средство разработки. Пусть это средство поддерживает язык программирования. Язык позволяет работать с данными разных типов. Для работы с датами в нем предусмотрен свой тип. Машинное представление дат в этом средстве разработки будет отличаться от ораклового. Правила обработки тоже будут другими.
А теперь смотрите, что происходит. Вы объявляете в программе для работы с датой переменную нужного типа. Присваиваете ей значение, константу или строку, которую ввел пользователь. Затем передаете значение переменной в запрос с помощью BIND-переменной.
Расскажу подробнее. Первый этап: вы в программе присваиваете переменной значение. По сути это операция преборазования строки с датой в значение нужного типа. У средства разработки клиентских приложений есть большой арсенал сделать эту операцию легко и без проблем.
Иногда даже само присваивание происходит неявно. Вы создаете экранную форму с полем ввода даты, пользователь вводит строку с датой, а вы затем считываете в переменную не строку, а значение, уже преобразованное в нужный тип.
Второй этап: передача значения переменной в запрос.
Как видите, программист не работает напрямую с оракловым типом DATE. Все хлопоты по передаче даты в запрос переложены на систему разработки.
Источник
Комментариев нет:
Отправить комментарий