У меня есть приложение с существующими данными, которые имеют Нуль в столбце даты.
Когда я смотрю на него от sqlplus, я вижу: 00-DECEMB
когда я использую функцию дампа на этом столбце, я Добираюсь: Typ=12 Len=7: 100,100,0,0,1,1,1
Я должен работать с существующими данными .NET (никакие изменения в данных, или структура данных или даже существующие sql операторы)
Как взлом делает я считал это значение или пишу это.
Версия дб варьируется, от 8 до 11.
Справка ценилась бы
В конце концов, решения моей проблемы не было.
Я сделал следующее: всякий раз, когда бизнес-логика пыталась ввести нулевую дату, я менял ее на 1/1/0001, и когда я получал 1/1/0001 или исключение из базы данных, я вел себя в бизнес-логике так, как будто я получил нулевую дату.
Поздравляю, это хранитель!
Тип = 12 Len = 7: 100,100,0,0,1,1,1
Элементами в этой дампе являются век, год, месяц, день, час, минута, секунда. Итак, у вас есть середина ночи 0-0-0000, что определенно не является действительной датой ...
SQL> create table d (d1 date)
2 /
Table created.
SQL> insert into d values (to_date('00-00-0000', 'dd-mm-yyyy'))
2 /
insert into d values (to_date('00-00-0000', 'dd-mm-yyyy'))
*
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
SQL>
править
Я использовал отличный трюк Гэри, чтобы вставить нулевую дату в таблицу ....
SQL> select * from d
2 /
D1
---------
00-DECEMB
19-JAN-10
SQL>
] Итак, по крайней мере, мы знаем, как это сделали ваши "волшебные" разработчики. Теперь все, что нам нужно сделать, это обойти их сообразительность.
Я думаю, что единственный способ сделать это - и вам, вероятно, это не понравится - это создать уровень API, используя представления ....
SQL> create or replace view v_d as
2 select case when d1 = trash_date then null else d1 end as d1
3 from d
4 /
View created.
SQL> select * from v_d
2 /
D1
---------
19-JAN-10
SQL>
Не менее тревожным аспектом здесь является то, что вы будете необходимо иметь триггеры INSTEAD IF, которые фактически вставляют нулевые даты в базовую таблицу (опять же, используя функцию Гэри). Кроме того, чтобы сохранить те же имена объектов, вам, вероятно, потребуется создать API в другой схеме.
Таким образом, я не преуменьшаю объем необходимой работы. Проблема в том, что предыдущие разработчики столкнулись с большим техническим долгом со своим решением. Теперь вам нужно заплатить по этому долгу (учитывая, что вы не хотите погашать капитал, переписывая базу данных).
последние новости
Я только что наткнулся на это забавное свидание в своем собственном окружении, которое предлагает альтернативное объяснение этим забавным свиданиям. Я добавил столбец DATE в таблицу, в которой были строки. Я использовал предложение DEFAULT, чтобы установить значение по умолчанию для sysdate. Угадайте, что случилось?
SQL> select * from t69
2 /
ID
----------
1
2
SQL> alter table t69 add col2 date default sysdate not null
2 /
Table altered.
SQL> select * from t69
2 /
ID COL2
---------- ---------
1 00-DECEMB
2 00-DECEMB
SQL>
Для записи: sysdate работает должным образом для новых строк ...
SQL> insert into t69 (id) values (3)
2 /
1 row created.
SQL> select * from t69
2 /
ID COL2
---------- ---------
1 00-DECEMB
2 00-DECEMB
3 28-APR-10
SQL>
Как узнал APC, вы не можете это исправить от SQL * PLUS. Я столкнулся с аналогичной проблемой от обновленной стоимости JDBC.
Единственное решение, которое я мог бы придумать, должен был обновить ряд, чтобы установить дату разумной (если все еще неверное) значение - вам нужно ссылаться на строку с помощью первичного ключа (которая не включает в себя под сомнение Или используйте ROWID или выполните обновление во всем, где столбец даты снаружи, кажется, что является действительным диапазоном, используя тот же тип инструмента, который создал плохие данные в первую очередь (то есть не SQL * Plus)
- И попробуйте исправить ошибку, вызванную проблему!)
HTH
c.
Не уверены, что вы действительно ожидаете, но вы можете генерировать «Cruddy» Dayes через DBMS_STATS.Convert_RAW_Value.
create or replace function stats_raw_to_date (p_in raw) return date is
v_date date;
v_char varchar2(25);
begin
dbms_stats.CONVERT_RAW_VALUE(p_in, v_date);
return v_date;
exception
when others then return null;
end;
/
select x, dump(x) y from (select stats_raw_to_date('64640000010101') x from dual);
Итак, что может помочь, это функция
create or replace function trash_date return date deterministic is
v_date date;
begin
dbms_stats.CONVERT_RAW_VALUE('64640000010101', v_date);
return v_date;
end;
/
, тогда вы можете использовать это в таком запросе
select case when date_col = trash_date then null else date_col
from table...
Это смехотально опасно для того, чтобы оракул использует статистику оптимизатора.
Вы получили недействительное, искусственно низкое значение даты, которое почти наверняка используется в качестве нулевого суррогата. Oracle не знает, что это нулевой суррогат, просто значение, поэтому, когда он собирает статистику оптимизатора, это будет использовать эту неверную дату в качестве низкого значения для столбца и предполагает, что данные линейно распределены в пределах высокой и низкой Значения его найдены, и что 10% от общего объема данных лежит выше высокого значения и ниже низкого значения.
Если у вас есть нулевые (отсутствие или неверные) данные, напишите нулевые данные в таблицу.