Oracle to date формат

Обновлено: 06.07.2024

В предыдущей статье мы рассмотрели встроенные функции для работы со строками. В данной статье речь пойдет о функциях работы с датой/временем и функциями предобразования типов для даты. Для хранения даты и времени в Oracle предусмотрен специальный тип DATE. С физической точки зрения это дробное число, целая часть которого хранит количество дней с некоторой базовой даты, а дробная — время. Это позволяет совершать над датами арифметические операции — сложение и вычитание.

Функция SYSDATE

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

SYSDATE

Функция ADD_MONTHS(d, x)

Возвращает дату, полученную в результате прибавления к дате d одного или нескольких месяцев. Количество месяцев задается параметров x, причем x может быть отрицательным — в этом случае указанное количество месяцев вычитается из заданной даты.

SELECT SYSDATE d,

ADD_MONTHS(SYSDATE, 3) d1,

ADD_MONTHS(SYSDATE, -3) d2

D

D1

D2

Функция LAST_DAY(d)

Возвращает последнее число месяца, указанного в дате d.

SELECT SYSDATE d,

D

D1

Данная функция очень удобна для определения количества дней в заданном месяце, например:

SELECT SYSDATE d,

TO_CHAR(LAST_DAY(SYSDATE), 'DD') d1

D

D1

Функция MONTHS_BETWEEN(d1, d2)

Функция MONTH_BETWEEN возвращает количество месяцев между двумя датами d1 и d2 с учетом знака как d1-d2, возвращаемое число является дробным.

SELECT MONTHS_BETWEEN('2.09.2006', '2.05.2006') d1,

MONTHS_BETWEEN('12.09.2006', '2.05.2006') d2,

MONTHS_BETWEEN('2.05.2006', '12.09.2006') d3

D1

D2

D3

Функция TRUNC(d[,mask])

Производит усечение указанной даты в соответствии с маской. Если маска не указана, то усечение производится до даты (время отбрасывается).

SELECT SYSDATE d1,

D1

D2

Рассмотрим типовые примеры — усечение даты до часов, дней, месяца и года. Форматная маска по умолчанию равна «DD»

SELECT SYSDATE d1,

TRUNC(SYSDATE, 'HH24') d2,

TRUNC(SYSDATE, 'DD') d3,

TRUNC(SYSDATE, 'MM') d4,

TRUNC(SYSDATE, 'YYYY') d5

D1

D2

D3

D4

D5

Функция ROUND(d[,mask])

Функция ROUND аналогична TRUNC, но вместо усечения она производит округление. Форматная маска по умолчанию равна «DD».

SELECT SYSDATE d1,

ROUND(SYSDATE, 'HH24') d3,

ROUND(SYSDATE, 'DD') d4,

ROUND(SYSDATE, 'MM') d5,

ROUND(SYSDATE, 'YYYY') d6

D1

D2

D3

D4

D5

D6

Форматные маски, допустимые для функций TRUNC и ROUND

Рассмотрим подробнее форматные маски и особенности их применения.

Маска

Назначение

Первый день столетия

YEAR, или YYYY, или YY, или Y

Первый день года

Первый день квартала

MONTH, или MON, или MM

Первый день месяца

Тот же день недели, что и первый день текущего года

Тот же день недели, что и первый день текущего месяца

DAY, или DY, или D

Первый день недели

HH, или HH12, или HH24

Функция TO_DATE(str[,mask [,nls_lang]])

Функция TO_DATE преобразует строку str в дату. Преобразование ведется по маске mask, если она указана. Если маска не указана, то берется маска по умолчанию. В случае указания маски можно указать еще один параметр — язык, используемый при форматировании названий месяцев и дней. В случае ошибки анализа строки str в соответствии с заданной маской возникает исключительная ситуация. Наиболее распространенная ошибка «ORA-01830: шаблон формата даты завершается перед преобразованием всей строки ввода». Кроме того, нередко встречается ошибка «ORA-01821: формат даты не распознан» — она возникает при указании недопустимой форматной маски.

SELECT TO_DATE('12.09.2006') d

D

Функция TO_CHAR(d[,mask])

Преобразует дату d в символьную строку в соответствии с заданной маской. В случае указания недопустимой маски возникает исключительная ситуация «ORA-01821: формат даты не распознан».

SELECT SYSDATE d1,

TO_CHAR(SYSDATE, 'DD.MM.YY HH24:MI') d2

D1

D2

Форматные маски, допустимые для функций TO_CHAR в случае форматирования даты

Маска

Назначение

SELECT SYSDATE d1,

TO_CHAR(SYSDATE, 'CC') d2

D1

D2

Столетие, причем перед датами до нашей эры ставится знак «минус».

SELECT SYSDATE d1,

TO_CHAR(SYSDATE-1000000, 'SCC') d2

D1

D2

SELECT SYSDATE d1,

TO_CHAR(SYSDATE, 'YYYY') d2

D1

D2

Аналогично YYYY, но перед датами до нашей эры ставится знак «минус»

Аналогичны YYYY, но возвращаются соответственно последние 3,2 или 1 цифра года.

Oracle/PLSQL функция TO_DATE преобразует строку в дату.

Синтаксис

Синтаксис функции Oracle/PLSQL TO_DATE:

Параметры или аргументы

string1 это строка, которая будет преобразована в дату.

format_mask не является обязательным. Это формат, который будет использоваться для преобразования string1 к дате.
Это может быть одно или сочетание следующих значений:

Параметр Пояснение
YYYY 4-х значный год
YYY
YY
Y
Последние 3, 2 или 1 цифры(а) года.
IYY
IY
I
Последние 3, 2 или 1 цифры(а) года ISO.
IYYY 4-значный год в соответствии со стандартом ISO
RRRR Принимает год с 2 цифрами и возвращает год с 4 цифрами.
Значение между 0-49 вернет 20xx год.
Значение между 50-99 вернет 19xx год.
Q Квартал года (1, 2, 3, 4; JAN-MAR = 1).
MM Месяц (01-12; JAN = 01).
MON Сокращенное название месяца.
MONTH Название месяца, дополненное пробелами длиной до 9 символов.
RM Римская цифра RM (I-XII; JAN = I).
WW Неделя года (1-53), где неделя 1 начинается в первый день года и продолжается до седьмого дня года.
W Неделя месяца (1-5), где 1-я неделя начинается в первый день месяца и заканчивается седьмым.
IW Неделя года (1-52 или 1-53) на основе стандарта ISO.
D День недели (1-7).
DAY Название дня.
DD День месяца (1-31).
DDD День года (1-366).
DY Сокращенное название дня.
J Юлианский день; количество дней с 1 января 4712 г. до н.э.
HH Час дня (1-12).
HH12 Час дня (1-12).
HH24 Час дня (0-23).
MI Минута (0-59).
SS Секунда (0-59).
SSSSS Секунды после полуночи (0-86399).
FF Дробные секунды. Используйте значение от 1 до 9 после FF, чтобы указать количество цифр в долях секунды. Например, 'FF4'.
AM, A.M., PM, или P.M. Индикатор меридиана.
AD или A.D AD индикатор.
BC или B.C. BC индикатор.
TZD Летнее время информация. Например, 'PST'
TZH Часовой пояс час.
TZM Часовой пояс минуты.
TZR Часовой пояс региона.

nls_language не является обязательным. NLS language используется для преобразования string1 к дате.

Применение

Функцию TO_DATE можно использовать в следующих версиях Oracle/PLSQL:

  • Oracle 12c, Oracle 11g, Oracle 10g, Oracle 9i, Oracle 8i

Пример

Рассмотрим несколько примеров функции TO_DATE, чтобы понять, как использовать функцию TO_DATE в Oracle/PLSQL.

По умолчанию 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 месяцев

Строка с форматом хранится и на клиентском компьютере и на сервере.

NLS_TERRITORY - задает правила преобразования для ввода чисел, дат.

В системе Windows параметр надо смотреть в реестре.

Значение (например, у меня):

Если вы хотите все настроить по-русски, то установите параметр:
Формат даты будет "DD.MM.YY".

Помимо пользовательских настроек хранения формата существуют также и серверные. Посмотреть их можно следующим запросом:

Обратите внимание на параметр NLS_DATE_FORMAT. Он выставляется в зависимости от параметра NLS_TERRITORY. Изменяя значение NLS_TERRITORY, вы тем самым меняете NLS_DATE_FORMAT. А вот обратное не верно.

Параметр NLS_DATE_LANGUAGE зависит от NLS_LANGUAGE и их зависимости аналогичны представленным выше.

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

Иногда полезно сравнить настройки базы с параметрами вашей сессии:


Как избежать ошибок, связанных с настройками формата даты?

Существуют несколько способов избежать ошибок, возникающих из-за различий в настройках формата даты пользователя и самой базы данных.
Во-первых вы можете использовать неявное преобразование.
Контролируйте (требуйте) правильной конфигурации сервера и рабочих мест. Пропишите нужные вам настройки в руководстве администратора и подобных ему документах.

Если вы решили использовать этот метод, то можете подстелить себе соломку. В начале каждой сессии выполняйте команду:

Или сразу устанавливайте параметр NLS_TERRITORY:

Для несерьезных приложений и маленьких систем этот метод вполне подходит, но он имеет недостатки. Например, не всем пользователям может понравиться ващ формат ввода дат, особенно если он отличается от настроек в операционной системы. А пользователи обычно "бузят", когда им неудобно.

Следующий способ - использовать функцию явного преобразования символьной строки в значение типа DATE. Формат ее очень прост: TO_DATE(строка с датой, строка с форматом).

Пользоваться функцией очень просто. Вставляйте её во всех местах, где вам нужно использовать константу с датой.

Строка с форматом допускает использование порядка 24 масок. Их полный перечень и подробное описание можно найти в документации. В приложении к этой статье есть памятка с наиболее ходовыми масками.

Через некоторое время вы изучите и запомните все основные форматы. И ещё.

. вы обнаружите некоторые недостатки "безудержного" применения TO_DATE.

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

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

Для того чтобы подставить значение даты в нужное место запроса, можно использовать механизм BIND-переменных.

BIND-переменные используютсядля подстановки значений в нужные места запроса. Обычно, для обозначения мест применяются маркеры с символом двоеточия. Например:

При использовании BIND-переменных за преобразование строк с датами в значение DATE отвечает приложение. Вернее сказать, инструментальное средство. Вся суета с преобразование и ответственность за его результат перекладывается с программиста на инструментальное средство.

Хотите узнать подробности? Сейчас расскажу, но прежде давайте представим, что для написание клиентской части вы выбрали какое-нибудь высокоуровневое средство разработки. Пусть это средство поддерживает язык программирования. Язык позволяет работать с данными разных типов. Для работы с датами в нем предусмотрен свой тип. Машинное представление дат в этом средстве разработки будет отличаться от ораклового. Правила обработки тоже будут другими.

А теперь смотрите, что происходит. Вы объявляете в программе для работы с датой переменную нужного типа. Присваиваете ей значение, константу или строку, которую ввел пользователь. Затем передаете значение переменной в запрос с помощью BIND-переменной.

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

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

Второй этап: передача значения переменной в запрос.

Как видите, программист не работает напрямую с оракловым типом DATE. Все хлопоты по передаче даты в запрос переложены на систему разработки.

Читайте также: