我如何检查年份是否介于 2000 年和当前年份之间?
How do i CHECK if a year is between 2000 and the current year?
我需要为汽车创建一个table。
每辆汽车都有制造年份。制造年份必须在 2000 年和当前年份之间。
year_manufacture INTEGER CONSTRAINT nn_automobiles_year_manufacture NOT NULL
CONSTRAINT ck_automobiles_year_manufacture
CHECK ((year_manufacture>= 2000)AND(year_manufacture<= "current year")),
这是不可能的,根据 Restrictions on Check Constraints :
Conditions of check constraints cannot contain the following constructs:
[...]
- Calls to the functions that are not deterministic (
CURRENT_DATE
, CURRENT_TIMESTAMP
, DBTIMEZONE
, LOCALTIMESTAMP
, SESSIONTIMEZONE
, SYSDATE
, SYSTIMESTAMP
, UID
, USER
, and USERENV
)
您不能创建包含 SYSDATE
的 CHECK
约束,但可以使用 DML
(Insert
) 触发器来检查条件(考虑 year_manufacture 是日期类型 ) :
Create or Replace Trigger trg_chk_man_date
Before Insert On tab -- replace with your table's name
For Each Row
Begin
if to_char(:new.year_manufacture,'YYYY') < 2000
or to_char(:new.year_manufacture,'YYYY') > to_char(sysdate,'YYYY') then
Raise_Application_Error(-20001,'The Wrong Manufacture Year !');
end if;
End;
如果 year_manufacture 是数字类型的列,那么只需考虑 :new.year_manufacture < 2000 and extract(year from sysdate) < :new.year_manufacture
正如@Wernfried Domscheit 已经指出的那样。
无法使用约束创建它。您可以使用虚拟列进行破解,但实际上您的要求没有多大意义。
今天无效的值将在五个月后有效。但是,约束必须在任何时候都有效(或无效)。
您所能做的就是创建一个触发器,在插入或更新时检查制造年份。会像这样:
CREATE OR REPLACE TRIGGER check_manufacture_date
BEFORE UPDATE OR INSERT ON automobiles
FOR EACH ROW
BEGIN
IF :NEW.year_manufacture NOT BETWEEN 2000 AND EXTRACT(YEAR FROM SYSDATE) THEN
raise_application_error(20001, 'Manufacture must be between 2000 and current year');
END IF;
END;
看看这样的解决方法是否有帮助。
你已经被告知的一切都是正确的。由于您无法根据 SYSDATE
直接检查年份,因此请创建另一列 - THIS_YEAR
- 它不会在您的代码中的任何地方使用。它会在每次插入时自动填充并获取当前年份。
约束(不能内联)然后将 YEAR_MANUFACTURE
与 THIS_YEAR
进行比较。
SQL> create table cars
2 (id number constraint pk_cars primary key,
3 name varchar2(20) not null,
4 this_year number(4) default extract (year from sysdate),
5 year_manufacture number(4),
6 --
7 constraint ch_year_manufacture check (year_manufacture between 2000 and this_year)
8 );
Table created.
SQL>
测试:
SQL> -- OK - after 2000, before 2019 (which is the current year)
SQL> insert into cars (id, name, year_manufacture) values (1, 'BMW', 2005);
1 row created.
SQL> -- Wrong - before 2000
SQL> insert into cars (id, name, year_manufacture) values (2, 'Mercedes', 1998);
insert into cars (id, name, year_manufacture) values (2, 'Mercedes', 1998)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_YEAR_MANUFACTURE) violated
SQL> -- Wrong - after 2019 (which is the current year)
SQL> insert into cars (id, name, year_manufacture) values (3, 'Cooper', 2020);
insert into cars (id, name, year_manufacture) values (3, 'Cooper', 2020)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_YEAR_MANUFACTURE) violated
SQL> -- OK - current year
SQL> insert into cars (id, name, year_manufacture) values (4, 'Opel', 2019);
1 row created.
SQL>
SQL> select * from cars;
ID NAME THIS_YEAR YEAR_MANUFACTURE
---------- -------------------- ---------- ----------------
1 BMW 2019 2005
4 Opel 2019 2019
SQL>
我需要为汽车创建一个table。
每辆汽车都有制造年份。制造年份必须在 2000 年和当前年份之间。
year_manufacture INTEGER CONSTRAINT nn_automobiles_year_manufacture NOT NULL
CONSTRAINT ck_automobiles_year_manufacture
CHECK ((year_manufacture>= 2000)AND(year_manufacture<= "current year")),
这是不可能的,根据 Restrictions on Check Constraints :
Conditions of check constraints cannot contain the following constructs:
[...]
- Calls to the functions that are not deterministic (
CURRENT_DATE
,CURRENT_TIMESTAMP
,DBTIMEZONE
,LOCALTIMESTAMP
,SESSIONTIMEZONE
,SYSDATE
,SYSTIMESTAMP
,UID
,USER
, andUSERENV
)
您不能创建包含 SYSDATE
的 CHECK
约束,但可以使用 DML
(Insert
) 触发器来检查条件(考虑 year_manufacture 是日期类型 ) :
Create or Replace Trigger trg_chk_man_date
Before Insert On tab -- replace with your table's name
For Each Row
Begin
if to_char(:new.year_manufacture,'YYYY') < 2000
or to_char(:new.year_manufacture,'YYYY') > to_char(sysdate,'YYYY') then
Raise_Application_Error(-20001,'The Wrong Manufacture Year !');
end if;
End;
如果 year_manufacture 是数字类型的列,那么只需考虑 :new.year_manufacture < 2000 and extract(year from sysdate) < :new.year_manufacture
正如@Wernfried Domscheit 已经指出的那样。
无法使用约束创建它。您可以使用虚拟列进行破解,但实际上您的要求没有多大意义。
今天无效的值将在五个月后有效。但是,约束必须在任何时候都有效(或无效)。
您所能做的就是创建一个触发器,在插入或更新时检查制造年份。会像这样:
CREATE OR REPLACE TRIGGER check_manufacture_date
BEFORE UPDATE OR INSERT ON automobiles
FOR EACH ROW
BEGIN
IF :NEW.year_manufacture NOT BETWEEN 2000 AND EXTRACT(YEAR FROM SYSDATE) THEN
raise_application_error(20001, 'Manufacture must be between 2000 and current year');
END IF;
END;
看看这样的解决方法是否有帮助。
你已经被告知的一切都是正确的。由于您无法根据 SYSDATE
直接检查年份,因此请创建另一列 - THIS_YEAR
- 它不会在您的代码中的任何地方使用。它会在每次插入时自动填充并获取当前年份。
约束(不能内联)然后将 YEAR_MANUFACTURE
与 THIS_YEAR
进行比较。
SQL> create table cars
2 (id number constraint pk_cars primary key,
3 name varchar2(20) not null,
4 this_year number(4) default extract (year from sysdate),
5 year_manufacture number(4),
6 --
7 constraint ch_year_manufacture check (year_manufacture between 2000 and this_year)
8 );
Table created.
SQL>
测试:
SQL> -- OK - after 2000, before 2019 (which is the current year)
SQL> insert into cars (id, name, year_manufacture) values (1, 'BMW', 2005);
1 row created.
SQL> -- Wrong - before 2000
SQL> insert into cars (id, name, year_manufacture) values (2, 'Mercedes', 1998);
insert into cars (id, name, year_manufacture) values (2, 'Mercedes', 1998)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_YEAR_MANUFACTURE) violated
SQL> -- Wrong - after 2019 (which is the current year)
SQL> insert into cars (id, name, year_manufacture) values (3, 'Cooper', 2020);
insert into cars (id, name, year_manufacture) values (3, 'Cooper', 2020)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_YEAR_MANUFACTURE) violated
SQL> -- OK - current year
SQL> insert into cars (id, name, year_manufacture) values (4, 'Opel', 2019);
1 row created.
SQL>
SQL> select * from cars;
ID NAME THIS_YEAR YEAR_MANUFACTURE
---------- -------------------- ---------- ----------------
1 BMW 2019 2005
4 Opel 2019 2019
SQL>