我正在 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))
检查约束必须是确定性的。 也就是说,特定行必须始终满足约束,否则它必须始终无法满足约束。 但
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;
另一种方法是创建一个域出生日期,并将约束内置到域中。这将允许您在其他表定义中重用相同的类型。
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
...
);
还有另一种解决方法吗
将 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
您需要创建一个包含 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)
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'
);
在 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')
);