检查出生日期的限制?

问题描述 投票:0回答:6

我正在 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))
sql database oracle-database oracle-sqldeveloper
6个回答
12
投票

检查约束必须是确定性的。 也就是说,特定行必须始终满足约束,否则它必须始终无法满足约束。 但

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;

3
投票

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

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

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

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 岁以下的出生日期

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

因检查而未插入。


0
投票

可以直接使用区间:

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

0
投票

在 PostgreSQL 中,你不需要 current_timestamp,它会自动计算。

CREATE TABLE Customer (
  customerID SERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  address TEXT,
  birthdate DATE,
  CONSTRAINT age_check CHECK (AGE(birthdate) >= INTERVAL '18 years')
);
© www.soinside.com 2019 - 2024. All rights reserved.