Делюсь скрин о своей проблеме. Как это возможно, я действительно не понимаю. Oracle показывает мне значение даты в поле столбца. Но если я хочу получить значение дня или месяца, я просто вижу 00 или 000. Я также вижу это значение в значении Toad NULL. Но это не ноль.
Кто-нибудь может мне помочь?
Отредактировано:
select start_date,to_char(start_date, 'DD-MON-YYYY HH24:MI:SS') as str,
dump(start_date, 16) as dmp,
extract(day from start_date) day,
extract(month from start_date) month
from my_table where gsm_no='xxxx';
START_DATE STR DMP DAY MONTH
11.08.2000 11-AĞU-2000 00:00:00 Typ=12Len=7:78,64,8,b,1,1,1 11 8
15.11.2008 00:40:04 15-KAS-2008 00:40:04 Typ=12Len=7:78,6c,b,f,1,29,5 15 11
00-000-0000 00:00:00 Typ=12 Len=7:78,6c,b,f,1,ee,c9 15 11
29.04.2016 23:42:02 29-NIS-2016 23:42:02 Typ=12Len=7:78,74,4,1d,18,2b,3 29 4
Также убедитесь, что в действительности не вызывается определяемая пользователем функция или синоним какой-либо функции с именем TO_CHAR, а не встроенная функция Oracle.
Возможно, у вас сохранено поврежденное значение — , как показано здесь , которое может выглядеть нормально при отображении по умолчанию, даже с модифицированным NLS, но не с явным to_char()
даже с той же маской формата. Я полагаю, что Toad тоже может показывать null, но не могу найти вопрос, где это произошло. Можете ли вы добавить dump(start_date, 16)
к своему запросу и добавить запрос и результаты к своему вопросу, пожалуйста, в виде форматированного текста, а не в виде изображения.
Не знаю насчет Toad, но тип данных Oracle DATE представляет собой 7-байтовый двоичный файл, содержащий как дату, так и время. Функция Oracle sql to_char() не возвращает 00 или 000 из этих данных (возможно, ошибка с недопустимым числом). Скорее всего, это тип данных Varchar2 в вашем описании изображения (пожалуйста, не используйте изображения - используйте текст). В случае типа данных DATE вы увидите формат, определенный параметрами NLS, и я не думаю, что какой-либо администратор базы данных установил для него такую полную версию, как на вашем рисунке. Как это могло быть, если исходные значения имеют тип данных DATE - вы можете найти здесь:
-- Sample data
WITH
tbl AS
( Select To_Date('11-AUG-2000 00:00:00', 'dd-MON-yyyy hh24:mi:ss') "DATE_DATE" From Dual Union All
Select To_Date('15-NOV-2008 00:40:04', 'dd-MON-yyyy hh24:mi:ss') "DATE_DATE" From Dual Union All
Select To_Date('15-NOV-2008 00:19:56', 'dd-MON-yyyy hh24:mi:ss') "DATE_DATE" From Dual Union All
Select To_Date('29-APR-2016 23:42:02', 'dd-MON-yyyy hh24:mi:ss') "DATE_DATE" From Dual
)
SELECT DATE_DATE,
EXTRACT(Year From DATE_DATE) "YEAR_FROM_DATE",
EXTRACT(Month From DATE_DATE) "MONTH_FROM_DATE",
EXTRACT(Day From DATE_DATE) "DAY_FROM_DATE",
To_Char(DATE_DATE, 'dd-MON-yyyy hh24:mi:ss') "ALL_FROM_DATE"
FROM tbl
DATE_DATE YEAR_FROM_DATE MONTH_FROM_DATE DAY_FROM_DATE ALL_FROM_DATE
--------- -------------- --------------- ------------- --------------------
11-AUG-00 2000 8 11 11-AUG-2000 00:00:00
15-NOV-08 2008 11 15 15-NOV-2008 00:40:04
15-NOV-08 2008 11 15 15-NOV-2008 00:19:56
29-APR-16 2016 4 29 29-APR-2016 23:42:02
... где первый столбец показывает формат типа данных DATE в моей базе данных, а последний столбец показывает полный набор даты и времени, содержащийся в типе данных DATE
-- examples of to_char() from DATE and Varchar
-- --------------------------------------------------------------
SELECT To_Char(To_Date('11-AUG-00', 'dd-MON-yy'), 'dd') "DD"
FROM dual
DD
--
11
-- ---------------------------------------------------
SELECT To_Char('11-AUG-2000 00:00:00', 'dd') "DD"
FROM dual
SQL Error: ORA-01722: invalid number
Люди могут установить свой собственный NLS_DATE_FORMAT в своем сеансе, и администраторы баз данных иногда переопределяют значение по умолчанию, поэтому более полный формат не удивителен. Но тип данных должен быть реальной датой, иначе как другие строки вернут правильные значения?
@PaulW Верно, но to_char() работает так же, из двоичного значения. NLS задает формат отображения, но не меняет тип.
@Paul Не знаю о Жабе ( !? ) - может быть. Сам по себе Oracle так не работает.
Я имел в виду ваш вывод из расширенного формата первого столбца о том, что на самом деле он может не храниться как реальная дата. Это ясно из правильных результатов, наблюдаемых в 3 из 4 строк. Изображение пользователя взято из SQL*Plus. Как можно объяснить, что TO_CHAR работает со всеми строками, кроме одной? Прямо сейчас единственное, о чем я могу думать, это то, что, возможно, TO_CHAR не является Oracle TO_CHAR, а чем-то нестандартным.
@PaulW Точно - должно быть что-то еще - это не может быть только Oracle ... Мой ответ ссылается на даты и форматирование Oracle.
Похоже, у вас есть поврежденное значение даты в вашей таблице.
С действительными датами вы не увидите этого:
alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';
select start_date,
to_char(start_date, 'DD-MON-YYYY HH24:MI:SS') as str,
dump(start_date, 16) as dmp
from your_table;
Но если я испорчу двоичное значение, хранящееся для третьего значения, что можно сделать с помощью измененного шестнадцатеричного значения:
declare
d date;
begin
dbms_stats.convert_raw_value('786c0b0f0115fd', d);
update your_table set start_date = d
where start_date = cast(timestamp '2008-11-15 00:19:56' as date);
end;
/
... то теперь сохраненное значение на первый взгляд выглядит нормально, даже если оно отформатировано как строка с использованием настройки сеанса NLS; но явное форматирование - даже с той же строкой формата - показывает нули для всех элементов:
select start_date,
to_char(start_date, 'DD-MON-YYYY HH24:MI:SS') as str,
dump(start_date, 16) as dmp
from your_table;
Ваше фактическое значение дампа может, конечно, отличаться, я только что нашел тот, который дал то же видимое значение, которое вы видите.
Строковая версия этого поврежденного значения с явным форматированием выглядит как 00-000-0000 00:00:00
, что вы и видите, хотя смотрите на отдельные элементы. (Интересно, что даже аббревиатура месяца здесь 000
... И extract()
по-прежнему дает ожидаемые числа года/месяца/дня, по крайней мере, с этим конкретным искажением, но может и не с вашим.)
Некоторые клиенты могут вообще отказаться показывать это, и я подозреваю, что именно поэтому вы ничего не видите в Toad.
Если вы не знаете, как произошло повреждение - что может быть из-за неправильно сформированного вызова OCI, или я, кажется, припоминаю, что в наследии imp
раньше была ошибка, которая могла сделать это, - и какое значение на самом деле должно быть, вы, возможно, не сможете его исправить правильно.
Лучшее, что вы можете сделать, это заменить его допустимой версией той же кажущейся даты/времени, обновив эту строку. Но у вас нет возможности узнать, близко ли значение к тому, что было задумано - я немного изменил минуты и секунды, ваше искажение может быть намного хуже, и это может быть очень трудно сказать. (Некоторые значения могут немного отличаться, некоторые сильно, некоторые отрицательные...)
Вы правы.. Большое спасибо. Мой вывод;
Было бы лучше добавить запрос и результаты к вашему вопросу, а не в виде комментария. Но да, установка байтов времени на 1,ee,c9
вместо 1,15,fd
, которую я использовал , дает тот же результат . Несмотря на то, что извлечение работает, вы не можете быть уверены, что часть даты верна, не зная, как она была повреждена.
Это действительно очень странно. Запустите его в другом клиенте (не в sqlplus) и посмотрите, получите ли вы те же результаты.