Проблема поля даты базы данных Oracle о функции to_char

Делюсь скрин о своей проблеме. Как это возможно, я действительно не понимаю. 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

Это действительно очень странно. Запустите его в другом клиенте (не в sqlplus) и посмотрите, получите ли вы те же результаты.

Paul W 22.02.2023 15:30

Также убедитесь, что в действительности не вызывается определяемая пользователем функция или синоним какой-либо функции с именем TO_CHAR, а не встроенная функция Oracle.

Paul W 22.02.2023 16:22

Возможно, у вас сохранено поврежденное значение — , как показано здесь , которое может выглядеть нормально при отображении по умолчанию, даже с модифицированным NLS, но не с явным to_char() даже с той же маской формата. Я полагаю, что Toad тоже может показывать null, но не могу найти вопрос, где это произошло. Можете ли вы добавить dump(start_date, 16) к своему запросу и добавить запрос и результаты к своему вопросу, пожалуйста, в виде форматированного текста, а не в виде изображения.

Alex Poole 22.02.2023 17:15
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
3
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Не знаю насчет 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 в своем сеансе, и администраторы баз данных иногда переопределяют значение по умолчанию, поэтому более полный формат не удивителен. Но тип данных должен быть реальной датой, иначе как другие строки вернут правильные значения?

Paul W 22.02.2023 15:48

@PaulW Верно, но to_char() работает так же, из двоичного значения. NLS задает формат отображения, но не меняет тип.

d r 22.02.2023 15:56

@Paul Не знаю о Жабе ( !? ) - может быть. Сам по себе Oracle так не работает.

d r 22.02.2023 16:03

Я имел в виду ваш вывод из расширенного формата первого столбца о том, что на самом деле он может не храниться как реальная дата. Это ясно из правильных результатов, наблюдаемых в 3 из 4 строк. Изображение пользователя взято из SQL*Plus. Как можно объяснить, что TO_CHAR работает со всеми строками, кроме одной? Прямо сейчас единственное, о чем я могу думать, это то, что, возможно, TO_CHAR не является Oracle TO_CHAR, а чем-то нестандартным.

Paul W 22.02.2023 16:20

@PaulW Точно - должно быть что-то еще - это не может быть только Oracle ... Мой ответ ссылается на даты и форматирование Oracle.

d r 22.02.2023 17:05
Ответ принят как подходящий

Похоже, у вас есть поврежденное значение даты в вашей таблице.

С действительными датами вы не увидите этого:

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;
ДАТА НАЧАЛА СИЛ ПУД 11 августа 2000 г. 00:00:00 11 августа 2000 г. 00:00:00 Тип=12 Лен=7: 78,64,8,б,1,1,1 15 ноября 2008 г. 00:40:04 15 ноября 2008 г. 00:40:04 Тип=12 Лен=7: 78,6c,b,f,1,29,5 15 ноября 2008 г. 00:19:56 15 ноября 2008 г. 00:19:56 Тип=12 Лен=7: 78,6c,b,f,1,14,39 29 апреля 2016 г. 23:42:02 29 апреля 2016 г. 23:42:02 Тип=12 Лен=7: 78,74,4,1д,18,2б,3

Но если я испорчу двоичное значение, хранящееся для третьего значения, что можно сделать с помощью измененного шестнадцатеричного значения:

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;
ДАТА НАЧАЛА СИЛ ПУД 11 августа 2000 г. 00:00:00 11 августа 2000 г. 00:00:00 Тип=12 Лен=7: 78,64,8,б,1,1,1 15 ноября 2008 г. 00:40:04 15 ноября 2008 г. 00:40:04 Тип=12 Лен=7: 78,6c,b,f,1,29,5 15 ноября 2008 г. 00:20:04 00-000-0000 00:00:00 Тип=12 Лен=7: 78,6c,b,f,1,15,fd 29 апреля 2016 г. 23:42:02 29 апреля 2016 г. 23:42:02 Тип=12 Лен=7: 78,74,4,1д,18,2б,3

рабочий пример

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

Строковая версия этого поврежденного значения с явным форматированием выглядит как 00-000-0000 00:00:00, что вы и видите, хотя смотрите на отдельные элементы. (Интересно, что даже аббревиатура месяца здесь 000... И extract() по-прежнему дает ожидаемые числа года/месяца/дня, по крайней мере, с этим конкретным искажением, но может и не с вашим.)

Некоторые клиенты могут вообще отказаться показывать это, и я подозреваю, что именно поэтому вы ничего не видите в Toad.

Если вы не знаете, как произошло повреждение - что может быть из-за неправильно сформированного вызова OCI, или я, кажется, припоминаю, что в наследии imp раньше была ошибка, которая могла сделать это, - и какое значение на самом деле должно быть, вы, возможно, не сможете его исправить правильно.

Лучшее, что вы можете сделать, это заменить его допустимой версией той же кажущейся даты/времени, обновив эту строку. Но у вас нет возможности узнать, близко ли значение к тому, что было задумано - я немного изменил минуты и секунды, ваше искажение может быть намного хуже, и это может быть очень трудно сказать. (Некоторые значения могут немного отличаться, некоторые сильно, некоторые отрицательные...)

Вы правы.. Большое спасибо. Мой вывод;

user3646666 22.02.2023 19:27

Было бы лучше добавить запрос и результаты к вашему вопросу, а не в виде комментария. Но да, установка байтов времени на 1,ee,c9 вместо 1,15,fd, которую я использовал , дает тот же результат . Несмотря на то, что извлечение работает, вы не можете быть уверены, что часть даты верна, не зная, как она была повреждена.

Alex Poole 22.02.2023 19:47

Другие вопросы по теме