Oracle 19c 零时默认日期格式,不使用任何格式化函数

Oracle 19c zero hour default date format with time without using any formating function

我正在尝试插入 零小时 20 分钟日期和时间 而不使用任何格式化函数,但我收到一些错误关注

insert into employee(created_date) values('4/Jan/21 00:20:00 AM');

ORA-01849: 小时必须在 1 到 12 之间

如何在 oracle 19c 中插入 零时 而不使用任何格式化函数

without using any formatting function

那将是一个非常糟糕的主意。这意味着您要将 string 插入到 DATE 数据类型列中,希望 Oracle 将“识别”该字符串,将其隐式转换为有效的 DATE 数据类型值并将其插入到列中。有太多的“假设”可能会出错,而且迟早会出错。

样本table:

SQL> create table test (id number, datum date);

Table created.

这是您的查询:

SQL> insert into test (id, datum) values (1, '4/Jan/21 00:20:00 AM');
insert into test (id, datum) values (1, '4/Jan/21 00:20:00 AM')
                                        *
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected

我将 to_date 应用于它,使用适当的格式模型(是的,我知道,你不想要那个 - 看看会发生什么):

SQL> insert into test (id, datum) values (1, to_date('4/Jan/21 00:20:00 AM', 'dd/Mon/yy hh:mi:ss am'));
insert into test (id, datum) values (1, to_date('4/Jan/21 00:20:00 AM', 'dd/Mon/yy hh:mi:ss am'))
                                                *
ERROR at line 1:
ORA-01843: not a valid month

为什么“一月”不是有效的月份?好吧,事实并非如此。在克罗地亚(这是我的数据库使用的语言),它是“Sij”。但是好吧,我可以向 TO_DATE:

添加额外的参数
SQL> insert into test (id, datum) values (1, to_date('4/Jan/21 00:20:00 AM', 'dd/Mon/yy hh:mi:ss am', 'nls_date_language = english'));
insert into test (id, datum) values (1, to_date('4/Jan/21 00:20:00 AM', 'dd/Mon/yy hh:mi:ss am', 'nls_date_language = english'))
                                                *
ERROR at line 1:
ORA-01849: hour must be between 1 and 12

正如 Zakaria 评论的那样,00 是一个无效值;将其更改为 12:

SQL> insert into test (id, datum) values (1, to_date('4/Jan/21 12:20:00 AM', 'dd/Mon/yy hh:mi:ss am', 'nls_date_language = english'));

1 row created.

没成功。我插入了什么?对,那是午夜过后 20 分钟。

SQL> select id, to_date(datum, 'dd.mm.yyyy hh24:mi:ss') datum from test;

        ID DATUM
---------- -------------------
         1 04.01.2021 00:20:00

SQL>

如果您坚持要求,请确保 Oracle 理解它。

SQL> rollback;

Rollback complete.
SQL> alter session set nls_date_language = 'english';

Session altered.

SQL> alter session set nls_date_format = 'dd/mon/yy hh:mi:ss am';

Session altered.

SQL> insert into test (id, datum) values (1, '4/Jan/21 12:20:00 AM');

1 row created.

SQL> select * From test;

        ID DATUM
---------- ---------------------
         1 04/jan/21 12:20:00 AM

SQL>

如果我是你,我不会这样做

一个DATE是一个二进制数据类型,由7个字节组成(世纪,year-of-century,月,日,时,分,秒);它总是包含这些组件并且从不以任何特定格式存储。

如果你想存储数据和时间,那么你可以使用:

  1. 一个DATE文字和一个INTERVAL DAY TO SECOND文字:

    INSERT INTO employee(created_date)
    VALUES ( DATE '2021-01-04' + INTERVAL '00:20:00' HOUR TO SECOND);
    

    这需要 ISO 8601 格式的日期和 24 小时制的时间。

  2. A TIMESTAMP 文字(将隐式转换为 DATE):

    INSERT INTO employee(created_date) VALUES ( TIMESTAMP '2021-01-04 00:20:00');
    

    这需要 ISO 8601 格式的日期和时间(在日期和时间部分之间使用 space 而不是 T)和 24 小时制时间。

  3. 从string-to-date显式转换:

    INSERT INTO employee(created_date) VALUES (
      TO_DATE(
        '4/Jan/21 12:20:00 AM',
        'DD/Mon/RR HH12:MI:SS AM',
        'NLS_DATE_LANGUAGE=English'
      )
    );
    

    您可以明确设置您希望使用的格式和语言。 (注意:在 12 小时制中,小时数需要 12 而不是 00。)

  4. 隐式转换自 string-to-date:

    首先,设置要与隐式 string-to-date(或 date-to-string)转换一起使用的格式模型:

    ALTER SESSION SET NLS_DATE_FORMAT = 'DD/Mon/RR HH12:MI:SS AM';
    

    然后:

    INSERT INTO employee(created_date) VALUES ('4/Jan/21 12:20:00 AM');
    
  5. 东西 non-standard,比如直接创建二进制 DATE 值:

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

    然后:

    INSERT INTO employee(created_date)
    VALUES (createDate(2021,1,4,0,20,0));
    

选项 1、2 和 3 是创建日期的标准方法。

选项 4 是不好的做法(因为任何用户都可以随时更改自己的会话参数,因此如果 NLS_DATE_FORMAT 与您预期的格式不同,查询将失败)但如果您能保证NLS_DATE_FORMAT不会改变。

选项 5 仅在为测试目的创建格式错误或错误的日期时真正有用,因为它绕过了正常的错误检查过程。

how to insert zero hour in oracle 19c without using any formatting function

选项 3 是这些选项中唯一使用格式化功能的选项。但是,选项 1、2 和 5 涉及的日期格式设置与您的格式不同,而选项 4 要求您在单独的文件中设置隐式格式模型声明。