Oracle 10g在日期中接受5位数字的年份

问题描述 投票:0回答:1

我设法在Oracle 10g的日期栏中输入日期2017年2月21日(我知道这不是正确的日期)。甲骨文接受了罚款。当我尝试在SQL Developer中重新选择它时,SQL Developer将其显示为NULL。但是,当我尝试通过java检索日期时,我又回到了插入时的值。想知道发生了什么,因为我还可以看到Oracle将不同的5位数字年份转换为4位数字年份。我输入了21019年2月21日,Oracle在存储时将年份转换为4581。我什至可以在SQL Developer中选择此值。

[我想知道是否可以读取原始日期,例如21-Feb-21019更改为21-Feb-4581,所以如何读取21-Feb-21019而不是21-Feb-4581。

java oracle oracle10g oracle-sqldeveloper
1个回答
2
投票

Oracle使用DATE7 bytes存储在表中,其中前两个字节为:

  • 世纪+ 100
  • 世纪+ 100

因此,(在技术上)可以存储的最大日期是当这两个字节的值分别为255199时,它们的年份为15599(我忽略了理论上可以存储255 ]在第二个字节中,这样会打开一大堆单独的问题。

您可以使用convert a raw value to a date使用DBMS_STATS.CONVERT_RAW_VALUE,这意味着我们可以绕过创建日期的常规方法,直接生成将要存储的字节值。

此功能是一个示例:

CREATE FUNCTION createDate(
  year   int,
  month  int,
  day    int,
  hour   int,
  minute int,
  second int
) RETURN DATE DETERMINISTIC
IS
  hex CHAR(14);
  d DATE;
BEGIN
  hex := TO_CHAR( FLOOR( year / 100 ) + 100, 'fm0X' )
      || TO_CHAR( MOD( year, 100 ) + 100, 'fm0X' )
      || TO_CHAR( month, 'fm0X' )
      || TO_CHAR( day, 'fm0X' )
      || TO_CHAR( hour + 1, 'fm0X' )
      || TO_CHAR( minute + 1, 'fm0X' )
      || TO_CHAR( second + 1, 'fm0X' );
  DBMS_OUTPUT.PUT_LINE( hex );
  DBMS_STATS.CONVERT_RAW_VALUE( HEXTORAW( hex ), d );
  RETURN d;
END;
/

然后,如果您有日期列,则可以插入通常不允许插入的值:

CREATE TABLE table_name ( date_column DATE );

INSERT INTO table_name ( date_column )
VALUES ( DATE '2019-12-31' + INTERVAL '1:02:03' HOUR TO SECOND );

INSERT INTO table_name ( date_column ) VALUES ( createDate( 15599, 12, 31, 1, 2, 3 ) );

INSERT INTO table_name ( date_column ) VALUES ( createDate( 12017, 2, 21, 0, 0, 0 ) );

TO_CHAR在年份超出日期的正常范围时不起作用。要获取存储在表中的值,可以使用DUMP获取包含字节值的字符串,也可以使用EXTRACT获取各个组件。

SELECT DUMP( date_column ),
       TO_CHAR( date_column, 'YYYY-MM-DD' ) AS value,
       TO_CHAR( EXTRACT( YEAR FROM date_column ), 'fm00000' )
         || '-' || TO_CHAR( EXTRACT( MONTH  FROM date_column ), 'fm00' )
         || '-' || TO_CHAR( EXTRACT( DAY    FROM date_column ), 'fm00' )
         || ' ' || TO_CHAR( EXTRACT( HOUR   FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         || ':' || TO_CHAR( EXTRACT( MINUTE FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         || ':' || TO_CHAR( EXTRACT( SECOND FROM CAST( date_column AS TIMESTAMP ) ), 'fm00' )
         AS full_value
FROM table_name;

输出:

DUMP(DATE_COLUMN)| VALUE | FULL_VALUE:-------------------------------- | :--------- | :-------------------Typ = 12 Len = 7:120,119,12,31,2,3,4 | 2019-12-31 | 02019-12-31 01:02:03Typ = 12 Len = 7:255,199,12,31,2,3,4 |注册| 15599-12-31 01:02:03Typ = 12 Len = 7:220,117,2,21,1,1,1 |注册| 12017-02-21 00:00:00

db <>小提琴here

© www.soinside.com 2019 - 2024. All rights reserved.