检查出生日期的约束?

时间:2011-12-08 01:04:35

标签: sql database oracle oracle-sqldeveloper

我正在Oracle中创建我的员工表,并且我想使用emp_date,因此出生日期不会再回到过去,也不能在将来设置?

在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))

5 个答案:

答案 0 :(得分:9)

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

如果您尝试在约束定义中引用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;

答案 1 :(得分:2)

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

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
    ...
    );

答案 2 :(得分: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

答案 3 :(得分:0)

您需要使用DATE_OF_BIRTH和PRESENT_DATE创建一个表,即我使用了DATE_JOINING,然后通过减去DATE_JOINING减去DATE_OF_BIRTH来使用AGE默认值。

最后将CHECK约束设置为AGE是否大于您的要求,即我设置为20。

见下文

创建表员工

CREATE TABLE EMPLOYEE(
    NAME VARCHAR(20) NOT NULL,
    DOB DATE NOT NULL,
    DATE_JOINING DATE DEFAULT NOW(),
    AGE INTEGER DEFAULT TIMESTAMPDIFF(YEAR,DOB,DATE_JOINING) CHECK(AGE>20)
    );

将数据插入表

INSERT INTO EMPLOYEE(NAME,DOB) VALUES('NAYAK','1998-2-3');
Query OK, 1 row affected, 1 warning (0.128 sec)

年龄大于20,因此将其插入。

SELECT * FROM EMPLOYEE;
+-------+------------+--------------+------+
| NAME  | DOB        | DATE_JOINING | AGE  |
+-------+------------+--------------+------+
| NAYAK | 1998-02-03 | 2019-10-15   |   21 |
+-------+------------+--------------+------+
1 row in set (0.001 sec)

现在插入少于20年的DOB

INSERT INTO EMPLOYEE(NAME,DOB) VALUES('NIRAJAN','2005-2-3');
ERROR 4025 (23000): CONSTRAINT `EMPLOYEE.AGE` failed for `NAYAK`.`EMPLOYEE`

由于检查未插入。

答案 4 :(得分:0)

您可以直接使用间隔:

ALTER TABLE "students"
  ADD CONSTRAINT "students_must_be_over_18" CHECK (
    CURRENT_TIMESTAMP - "date_of_birth" > INTERVAL '18 years'
  );