Sql 是否检查出生日期限制?

Sql 是否检查出生日期限制?,sql,database,oracle,oracle-sqldeveloper,Sql,Database,Oracle,Oracle Sqldeveloper,我正在Oracle中创建我的employee表,对于emp_date,我希望创建它,以便出生日期不会早于过去,也不能在将来设置 这是否太复杂,无法在CREATETABLE语句中实现?如果是这样,我想我必须跳过它,因为这是我必须创建约束的部分 , emp_dob DATE NOT NULL CREATE TABLE employee(emp_id NUMBER(4) PRIMARY KEY , emp_name VARCHAR2(40) NOT NULL , emp_address VA

我正在Oracle中创建我的employee表,对于emp_date,我希望创建它,以便出生日期不会早于过去,也不能在将来设置

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

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

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

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
    ...
    );
将域出生日期创建为日期默认值NULL

检查(值>='1900-01-01'和值检查约束必须是确定性的。也就是说,特定行必须始终满足约束或始终无法满足约束。但是
SYSDATE
本质上是不确定性的,因为返回值不断变化。因此,您无法定义
检查
约束调用
SYSDATE
或任何其他用户定义函数的int

如果尝试在约束定义中引用
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
您可以创建一个
检查
约束,其中最小日期和最大日期都是硬编码的,但这并不特别实用,因为您必须不断删除并重新创建约束

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;
创建或替换触发器检查\u出生日期\u
在插入或更新员工信息之前
每行
开始
如果(:new.emp_dob<日期'1900-01-01'或
:new.emp_dob>sysdate)
然后
引发应用程序错误(
-20001, 
“员工出生日期必须晚于1900年1月1日且早于今天”);
如果结束;
结束;

另一种解决方法怎么样

将sysdate写入列并使用它进行验证。此列可能是您的审核列(例如:创建日期)


您需要创建一个包含出生日期和当前日期的表,即我被使用的日期,然后使用年龄默认值减去出生日期

最后将检查约束设置为年龄是否大于您的要求,即我被设置为20岁

见下文

创建表Employee 向表中插入数据 年龄大于20,因此将插入该年龄。 现在插入一个不到20年的DOB
由于检查而未插入。您可以直接使用间隔:

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

不幸的是,Oracle不支持
CREATE DOMAIN
语句。我不知道这一点。这对Oracle用户来说真的很痛苦,因为它会迫使他们使用类型或表作为域,甚至创建丑陋的触发器(见下文)只是为了模拟域。非常有趣和有用的分析。
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)
SELECT * FROM EMPLOYEE;
+-------+------------+--------------+------+
| NAME  | DOB        | DATE_JOINING | AGE  |
+-------+------------+--------------+------+
| NAYAK | 1998-02-03 | 2019-10-15   |   21 |
+-------+------------+--------------+------+
1 row in set (0.001 sec)
INSERT INTO EMPLOYEE(NAME,DOB) VALUES('NIRAJAN','2005-2-3');
ERROR 4025 (23000): CONSTRAINT `EMPLOYEE.AGE` failed for `NAYAK`.`EMPLOYEE`
ALTER TABLE "students"
  ADD CONSTRAINT "students_must_be_over_18" CHECK (
    CURRENT_TIMESTAMP - "date_of_birth" > INTERVAL '18 years'
  );