检查约束以确保日期不在未来?

Posted

技术标签:

【中文标题】检查约束以确保日期不在未来?【英文标题】:Check constraint for making sure a date is not in the future? 【发布时间】:2011-01-19 18:43:52 【问题描述】:

我正在尝试创建一个表来记录对另一个表的估计小时数所做的更改。数据库作为一个整体是一个项目管理系统,供公司将工作分配给员工并为客户创建发票。

目前我有:

CREATE TABLE task_history
(
    task_history_id         NUMBER(5),
    previous_est_hours      NUMBER(3,1),
    change_date         DATE,
    reason_for_change       VARCHAR2(50),
    task_id             NUMBER(5),

CONSTRAINT TASKHIST_TASKHISTID_PK   PRIMARY KEY (task_history_id),
CONSTRAINT TASKHIST_TASKID_FK       FOREIGN KEY (task_id) REFERENCES task(task_id),
CONSTRAINT TASKHIST_TASKID_NN CHECK (task_id IS NOT NULL),
CONSTRAINT TASKHIST_CHANGEDATE_NONFUTURE CHECK (change_date <= sysdate)
);

change_date 不能是未来的日期,它必须是今天或过去。 最后一个检查约束是问题所在。据我了解,由于我忘记的原因,您不能使用 sysdate,但您不能。我还尝试了 GETDATE() 以及我在网上找到的所有其他变体。 我怎样才能完成这个可能很简单的任务?

【问题讨论】:

GETDATE() 是特定于 TSQL 的。 SYSDATE 是 PLSQL 特定的获取当前日期和时间的方法,而 CURRENT_TIMESTAMP 是 ANSI 替代方法(大多数数据库都支持)。你真的遇到错误了吗?因为这是我第一次听说不使用 SYSDATE,所以我想听听更多。您的 Oracle 版本也会有所帮助。 【参考方案1】:

您不能从检查约束中调用函数,因此最自然的方法是在 task_history 表上定义触发器,即

CREATE OR REPLACE TRIGGER task_change_date_in_past
  BEFORE INSERT OR UPDATE ON task_history
  FOR EACH ROW
BEGIN
  IF( :new.change_date > sysdate )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 'Change date must be in the past' );
  END IF;
END;

【讨论】:

@Andomar - D'oh。你是对的。我做了那个更正。【参考方案2】:

在 11g 中,可以使用带有 sysdate 的检查约束:http://rwijk.blogspot.com/2007/12/check-constraints-with-sysdate.html

在 11g 之前你应该使用 Justin 的方法。

问候, 抢。

【讨论】:

【参考方案3】:
CONSTRAINT TASKHIST_CHANGEDATE_NONFUTURE CHECK (change_date <= sysdate)

这作为一个约束确实是有问题的。 考虑如果要更新一行(其他列)或停用/反应约束会发生什么。它不会检查原始日期,而是检查current SYSDATE!

我主张向表中添加另一列,默认为 SYSDATE,并构建一个约束或 TRIGGER,将新列(存储的 SYSDATE)与 change_date 进行比较。

【讨论】:

【参考方案4】:

我认为您可以定义一个用户定义的函数来执行该检查并在检查约束中使用它。

【讨论】:

据我所知,您不能从检查约束中调用用户定义的函数

以上是关于检查约束以确保日期不在未来?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 的检查约束内使用“不在”查询

Oracle数据库之SQL基础

ORACLE

使用 JPA 标准的“不在”约束

在 BigQuery SQL 中:在满足日期约束时检查和更新表列值

检查约束不允许我添加数据