检查出生日期的限制?

发布于 2024-12-20 14:33:31 字数 526 浏览 2 评论 0原文

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

I am creating my employee table in Oracle and for emp_date I would like to make it so the date of birth is not way back in the past and can not be set in the future?

Is this too complex to implement in the CREATE TABLE statement? if so then I guess I have to skip it because that is the part where I have to create the constraints.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

似梦非梦 2024-12-27 14:33:31

另一种解决方法是

将 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

What about another workaround

Write sysdate into a column and use it for validation. This column might be your audit column (For eg: creation date)

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
掌心的温暖 2024-12-27 14:33:31

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

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

请参见下面

创建表 Employee

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)

Age 大于 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`

由于检查而未插入。

You need to create a table with DATE_OF_BIRTH and the PRESENT_DATE i.e I am used DATE_JOINING and then use an AGE default value by subtracting the DATE_JOINING minus DATE_OF_BIRTH.

Finally set CHECK constraint to AGE is it greater than your requirement i.e I am set 20.

See below

Createing Table Employee

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

Inserting Data to the Table

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

Age is greater than 20 so it is inserted.

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

Now Insert a DOB less than 20 years

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

Not Inserted because of check.

撧情箌佬 2024-12-27 14:33:31

检查约束必须是确定性的。也就是说,特定行必须始终满足约束,否则它必须始终无法满足约束。但 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;

Check constraints must be deterministic. That is, a particular row must always satisfy the constraint or it must always fail to satisfy the constraint. But SYSDATE is inherently non-deterministic since the returned value is constantly changing. Thus, you cannot define a CHECK constraint that calls SYSDATE or any other user-defined function.

If you try to reference SYSDATE in the constraint definition, you'll get an error

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

You could create a CHECK constraint where both the minimum and maximum date were hard-coded but that would not be particularly practical since you'd have to constantly drop and recreate the 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.

The practical way to enforce this sort of requirement would be to create a trigger on the table

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;
浸婚纱 2024-12-27 14:33:31

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

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

Another way would be to create a domain birthdate, with the constraint built into the domain. This will allow you to reuse the same type in other table definitions.

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
    ...
    );
空城旧梦 2024-12-27 14:33:31

您可以直接使用间隔:

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

You can use interval directly:

ALTER TABLE "students"
  ADD CONSTRAINT "students_must_be_over_18" CHECK (
    CURRENT_TIMESTAMP - "date_of_birth" > INTERVAL '18 years'
  );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文