2011-12-08 56 views
4

我正在Oracle中创建我的员工表并为emp_date创建我想让它的出生日期不会回到过去,并且不能在将来设置?CHECK约会出生日期?

这是否太复杂,无法在CREATE TABLE语句中实现?如果是这样,那么我想我必须跳过它,因为那是我必须创建约束的部分。

, emp_dob DATE NOT NULL 

    CREATE TABLE employee(emp_id NUMBER(4) PRIMARY KEY 
, emp_name VARCHAR2(40) NOT NULL 
, emp_address VARCHAR2(60) NOT NULL 
, emp_tel NUMBER(11) NOT NULL 
, CONSTRAINT emp_tel_length CHECK (LENGTH(emp_tel) BETWEEN 9 and 11) 
, emp_dob DATE NOT NULL 
, CONSTRAINT check_date_of_birth CHECK (emp_dob BETWEEN DATE '1950-01-01' AND sysdate)) 

回答

9

检查约束必须是确定性的。也就是说,一个特定的行必须总是满足约束,否则它总是不能满足约束。但SYSDATE本质上是非确定性的,因为返回的值不断变化。因此,您无法定义调用SYSDATE或任何其他用户定义函数的约束条件CHECK

如果试图在约束定义引用SYSDATE,你会得到一个错误

SQL> ed 
Wrote file afiedt.buf 

    1 create table t(
    2  birth_date date check(birth_date between date '1900-01-01' and 
    3            sysdate) 
    4*) 
SQL>/
               sysdate) 
               * 
ERROR at line 3: 
ORA-02436: date or system variable wrongly specified in CHECK constraint 

您可以创建一个CHECK约束其中两个最小和最大的日期被硬编码,但是这不会是特别实用,因为你必须不断地删除和重新创建约束。

SQL> ed 
Wrote file afiedt.buf 

    1 create table t(
    2  birth_date date check(birth_date between date '1900-01-01' and 
    3             date '2011-12-08') 
    4* ) 
SQL>/

Table created. 

强制执行这种要求是,在表上创建一个触发器

CREATE OR REPLACE TRIGGER check_birth_date 
    BEFORE INSERT OR UPDATE ON employee 
    FOR EACH ROW 
BEGIN 
    IF(:new.emp_dob < date '1900-01-01' or 
     :new.emp_dob > sysdate) 
    THEN 
    RAISE_APPLICATION_ERROR( 
     -20001, 
     'EMployee date of birth must be later than Jan 1, 1900 and earlier than today'); 
    END IF; 
END; 
+0

非常有趣和有用的分析。 –

2

另一种方法是创建一个域名birthdate,并在域中建立约束。这将允许您在其他表定义中重用相同的类型。

CREATE DOMAIN birthdate AS date DEFAULT NULL 
    CHECK (value >= '1900-01-01' AND value <= now()) 
    ; 

CREATE TABLE employee 
    (empno INTEGER NOT NULL PRIMARY KEY 
    , dob birthdate NOT NULL 
    ... 
    ); 
+0

不幸的是,Oracle不支持'CREATE DOMAIN'声明。 –

+0

嗯,我不知道。对于oracle用户来说真的很痛苦,因为它会迫使他们使用类型或表格作为域名,甚至为了模拟域名而创建丑陋的触发器(见下文)。 – wildplasser

1

什么其他解决办法

写SYSDATE成一列,用它来验证的实用方法。此列可能是您的审计列(如:创建日期)

CREATE TABLE "AB_EMPLOYEE22" 
(
    "NAME"  VARCHAR2 (20 BYTE), 
    "AGE"  NUMBER, 
    "SALARY" NUMBER, 
    "DOB"  DATE, 
    "DOJ"  DATE DEFAULT SYSDATE 
); 

Table Created  

ALTER TABLE "AB_EMPLOYEE22" ADD CONSTRAINT 
AGE_CHECK CHECK((ROUND((DOJ-DOB)/365)) = AGE) ENABLE; 

Table Altered