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
尽管转换为数字没有多大意义,只需比较日期:
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
或者 - 如果您确信值始终是有效时间并且会有前导零 - 只需比较字符串:
CONSTRAINT "my_constraint" CHECK (window_stop > window_start) ENABLE
您还可以将时间存储为标称日期、午夜后的秒数或间隔,这样可以更轻松地防止使用完全无效的值(例如“99:00:00”) .但是您可能有一个可以改用的真实日期-取决于这些日期是否与真实日期相关联,或者例如轮班模式或类似模式 - 这将允许您处理 windows 穿越午夜。 (你应该不做的是将相关的日期和时间存储为单独的字段,但没有迹象表明你正在这里做什么。)
我想创建 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
尽管转换为数字没有多大意义,只需比较日期:
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
或者 - 如果您确信值始终是有效时间并且会有前导零 - 只需比较字符串:
CONSTRAINT "my_constraint" CHECK (window_stop > window_start) ENABLE
您还可以将时间存储为标称日期、午夜后的秒数或间隔,这样可以更轻松地防止使用完全无效的值(例如“99:00:00”) .但是您可能有一个可以改用的真实日期-取决于这些日期是否与真实日期相关联,或者例如轮班模式或类似模式 - 这将允许您处理 windows 穿越午夜。 (你应该不做的是将相关的日期和时间存储为单独的字段,但没有迹象表明你正在这里做什么。)