Oracle 约束 - 比较两个字符串两次

Oracle constraint - compare two string like two times

我想创建 table witj 约束,它将两个 varchar2(8 char) 列作为时间进行比较。 可能吗?

我有过这样的想法,但它不起作用:(

CONSTRAINT "my_constraint" CHECK (to_number(to_char(to_date(window_stop, 'hh24:mi:ss'), 'sssss')) > to_number(to_char(to_date(window_start, 'hh24:mi:ss'), 'sssss'))) ENABLE

感谢所有帮助。 保罗.

正如我所说,将 varchar2 用于日期字段总是一个非常糟糕的主意。让我向您展示当字段为日期

时您的约束如何如此简单
SQL> create table t ( c1 date , c2 date ) ;

Table created.

SQL> alter session set nls_date_format='dd.mm.yyyy hh24:mi:ss' ;

Session altered.

SQL> insert into t values ( to_date('11.08.2020 14:00:00') , to_date('11.08.2020 14:10:00') ) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> select * from t ;

C1                  C2
------------------- -------------------
11.08.2020 14:00:00 11.08.2020 14:10:00

SQL> select ( c2 - c1 ) * 24 * 60 * 60 from t ;

(C2-C1)*24*60*60
----------------
             600

现在,让我们添加约束

SQL> alter table t add constraint chk_test check ( c2 > c1 ) ;

Table altered.

SQL> insert into t values ( to_date('11.08.2020 14:11:00') , to_date('11.08.2020 14:10:00') ) ;
insert into t values ( to_date('11.08.2020 14:11:00') , to_date('11.08.2020 14:10:00') )
*
ERROR at line 1:
ORA-02290: check constraint (SYS.CHK_TEST) violated

您想存储时间,也就是日期,并且您想要比较 window_stop 是否大于 window_start。无需进行如此复杂的转换,只需将字段存储为日期即可。尽管这是您要存储的数据的正确数据类型,但约束会更好地工作。

您的约束将得到“ORA-02436:在 CHECK 约束中错误指定的日期或系统变量”,因为如果您不提供日期元素,则 to_date() 默认为当月的第一天;因此,在插入数据后评估约束检查的结果可能会发生变化,这是不允许的。在这种特定情况下,它实际上无法更改,但正在应用一般规则,导致错误。

您可以改用名义上的固定日期:

CONSTRAINT "my_constraint"
  CHECK (
      to_number(to_char(to_date('2000-01-01 ' || window_stop, 'YYYY-MM-DD hh24:mi:ss'), 'sssss'))
    > to_number(to_char(to_date('2000-01-01 ' || window_start, 'YYYY-MM-DD hh24:mi:ss'), 'sssss'))
  ) ENABLE

db<>fiddle

尽管转换为数字没有多大意义,只需比较日期:

CONSTRAINT "my_constraint"
  CHECK (
      to_date('2000-01-01 ' || window_stop, 'YYYY-MM-DD hh24:mi:ss')
    > to_date('2000-01-01 ' || window_start, 'YYYY-MM-DD hh24:mi:ss')
  ) ENABLE

db<>fiddle

或者 - 如果您确信值始终是有效时间并且会有前导零 - 只需比较字符串:

CONSTRAINT "my_constraint" CHECK (window_stop > window_start) ENABLE

db<>fiddle

您还可以将时间存储为标称日期、午夜后的秒数或间隔,这样可以更轻松地防止使用完全无效的值(例如“99:00:00”) .但是您可能有一个可以改用的真实日期-取决于这些日期是否与真实日期相关联,或者例如轮班模式或类似模式 - 这将允许您处理 windows 穿越午夜。 (你应该做的是将相关的日期和时间存储为单独的字段,但没有迹象表明你正在这里做什么。)