2010-01-18 7 views
7

Tengo una aplicación con datos existentes, que tiene cero en la columna de fecha.Uso de Oracle Zero Date

Cuando miro desde sqlplus veo: 00-DECEMB

cuando se utiliza la función de volcado en esta columna, me sale: Typ = 12 Len = 7: 100,100,0,0,1 , 1,1

que necesito para trabajar con los datos existentes de .Net (no hay cambios en los datos, o la estructura de datos o sentencias SQL aún existentes)

Cómo el hack puedo leer este valor, o Escribelo.

La versión db varía, de 8 a 11.

ayuda se agradece

+0

Por favor, aclare algo. ¿Estas fechas ya están en su base de datos Oracle? Si es así, ¿están realmente en una columna con un tipo de datos FECHA? ¿O está tratando de importarlos de un producto de base de datos diferente? – APC

+0

Sí, estas fechas ya están en la base de datos. La columna tiene el tipo de datos DATE. – Noam

+0

Cuando lee la fila en la aplicación .NET, ¿qué aparece en la columna? –

Respuesta

1

Al final del día, no había solución a mi problema.

Lo que hice fue que cada vez que la lógica de negocios intentaba introducir una fecha cero, lo cambiaba a 1/1/0001 y cada vez que recibía 1/1/0001 o una excepción de la base de datos, me comportaba en el lógica de negocios como si tuviera fecha cero.

+0

¿Qué pasará con su marca de tiempo en el año 10k? ;-) –

1

Felicidades, eso es muy bueno!

Typ = 12 Len = 7: 100,100,0,0,1,1,1

Los elementos que son volcado siglo, año, mes, día, hora minuto segundo. Así que lo que tienes ahí es midight el 0-0-0000, que definitivamente no es una fecha válida ...

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> 

edición

Solía ​​excelente truco de Gary a sacaclavos una fecha cero en una tabla ....

SQL> select * from d 
    2/

D1 
--------- 
00-DECEMB 
19-JAN-10 

SQL> 

Así que al menos sabemos cómo lo hicieron sus desarrolladores de "Magic". Ahora todo lo que tenemos que hacer es trabajar en torno a su astucia.

Creo que la única manera de hacer esto - y es probable que no le va a gustar que - es la construcción de una capa de API, el uso de vistas ....

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> 

No es el aspecto menos preocupante de esto es que necesitará tener activadores INSTEAD IF que en realidad inserten fechas cero en la tabla subyacente (nuevamente, usando la función de Gary). Además, para mantener los mismos nombres de objeto, es probable que deba compilar la API en un esquema diferente.

Así que no estoy minimizando la cantidad de trabajo que está involucrado. El problema es que los desarrolladores anteriores corrieron una gran cantidad de deuda técnica con su solución. Ahora depende de usted pagar la deuda pendiente (dado que no desea pagar el capital reescribiendo la base de datos).

finales de noticias de última hora

Acabo de venir a través de esta fecha divertido en mi propio entorno, que ofrece una explicación alternativa para estas fechas divertidos. Agregué una columna de FECHA a una tabla que tenía filas. Usé la cláusula DEFAULT para establecer un valor predeterminado para sysdate. ¿Adivina qué pasó?

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> 

Para el registro, el sysdate funciona como se espera para las nuevas filas ...

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> 
+0

Sí Desafortunadamente estoy trabajando con una base de datos mantenida por una aplicación de legado escrito en un lenguaje llamado magia (eDevelper, UniPaaS, etc ...) que el lenguaje es muy aficionado a la fecha cero - así que esto no es un problema localizado para mi. Este es un show stopper. – Noam

+0

Supongo que un lenguaje llamado Magic sería muy aficionado a los valores mágicos. Pero, sinceramente, los valores mágicos son peores que los nulos. – APC

+0

Estoy completamente de acuerdo, pero desafortunadamente para mí, eso es un – Noam

0

Como APC descubrió, no se puede arreglar esto desde SQL * PLUS. Me encontré con un problema similar de un valor actualizado jdbc.

La única solución que se me ocurrió fue ACTUALIZAR la fila para establecer la fecha en un valor razonable (si aún incorrecto) - necesita hacer referencia a la fila usando una clave principal (que no incluye la columna en cuestión) o use el rowid o haga una actualización en todo donde la columna de fecha está fuera de lo que parece ser un rango válido utilizando el mismo tipo de herramienta que creó los datos incorrectos en primer lugar (es decir, no sql * plus)

(oh - y tratar de corregir el error que causó el problema!)

HTH

C.

+0

Desafortunadamente, cambiar los datos originales no es una opción – Noam

+0

Entonces será mejor que empieces a esperar consecuencias de otras consultas en la tabla :( – symcbean

+0

Tengo varias consultas en esa tabla, pero todas se enrutan a través de una capa de DataAccess, por lo que puedo aborde el problema allí. Pero necesito alguna forma de obtener esa información sin cambiar el SQL o los datos – Noam

3

No estoy seguro de lo que realmente espera lograr, pero puede generar días 'cruddy' a través de 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); 

Entonces, ¿qué puede ayudar es una función

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; 
/

entonces usted puede utilizar que en una consulta como

select case when date_col = trash_date then null else date_col 
from table... 
+0

¿Conoces una forma de obtener el valor RAW de .Net sin manipular el sql? – Noam

+0

No sé .Net El SQL existente devuelve una fecha, que es de siete bytes, o la convierte en una cadena con TO_CHAR. Si usa TO_CHAR, está atascado en la interpretación de la cadena. Si devuelve una fecha de Oracle, ¿es posible seleccione una columna de fecha como OracleBinary en lugar de OracleDate? –

0

Ésta es ridículamente peligroso que ver con la forma en Oracle utiliza las estadísticas del optimizador.

Tiene un valor de fecha inválido, artificialmente bajo, que casi con seguridad se está utilizando como sustituto NULO. Oracle no sabe que es un sustituto NULO, solo un valor, por lo que cuando reúne las estadísticas del optimizador, usará esa fecha no válida como el valor bajo para la columna, y supondrá que los datos se distribuyen linealmente entre los valores alto y bajo. valores que se encuentran, y que el 10% del total de datos se encuentra por encima del valor alto y por debajo del valor bajo.

Si tiene datos NULOS (ausentes o no válidos), escriba datos NULL en la tabla.

+0

Desafortunadamente para mí, esta es una aplicación heredada con datos heredados, y la lógica heredada que cuenta en este valor problemático. – Noam