创建触发器以比较两个表中的日期

Creating trigger to compare dates from two tables

我有两个表,它们都有单独的 start/end 日期值。一个项目可以包含多个计划,并且特定计划 start/end 日期应介于其项目 start/end 日期之间。我不知道如何验证这一点,我曾尝试使用触发器,但我就是想不通。有人可以就我做错了什么给我一些建议吗?

这是我的触发器:

%%sql
CREATE TRIGGER beforeInsertInPlan BEFORE INSERT ON Plan FOR EACH ROW
BEGIN
    SELECT proID.projectID FROM Project
    INNER JOIN Project ON pID = Project.projectID
    WHERE 

这是我的两个表:

%%sql
DROP TABLE IF EXISTS Project;
CREATE TABLE Project (
    projectID varchar(255) NOT NULL UNIQUE,
    name varchar(255) NOT NULL DEFAULT ' ',
    leader varchar(255) NOT NULL DEFAULT ' ',
    budget varchar(255) NOT NULL DEFAULT '0',
    startDate DATE NOT NULL DEFAULT '2000-12-31',
    endDate DATE NOT NULL DEFAULT '2000-12-31'
    CHECK (JulianDay(startDate) <= JulianDay(endDate)),
    PRIMARY KEY (projectID)
);

和:

%%sql
DROP TABLE IF EXISTS Plan;
CREATE TABLE Plan (
    pID varchar(255) NOT NULL UNIQUE,
    projectID varchar(255) DEFAULT NULL,
    name varchar(255) NOT NULL DEFAULT ' ',
    startDate DATE NOT NULL DEFAULT ' ',
    endDate DARE NOT NULL DEFAULT ' '
    CHECK (JulianDay(startDate) <= JulianDay(endDate) AND (startDate >= Project.startDate) AND 
           (endDate <= Project.endDate)),
    PRIMARY KEY (pID, projectID),
    FOREIGN KEY (projectID) REFERENCES Project(projectID)
);

首先,BEFORE INSERT 触发器可能只会导致问题。参见 https://sqlite.org/lang_createtrigger.html#cautions_on_the_use_of_before_triggers

所以这是一个触发器,我相信它会按预期工作,尽管它会删除插入的行:-

CREATE TRIGGER IF NOT EXISTS afterInsertInPlan 
    AFTER INSERT ON plan 
    WHEN (
            (NOT (new.startdate) BETWEEN 
                (SELECT startdate FROM project WHERE projectID = new.projectID) 
                AND 
                (SELECT enddate FROM project WHERE projectID = new.projectID)
            )
            OR 
            (NOT (new.enddate) BETWEEN 
                (SELECT startdate FROM project WHERE projectID = new.projectID) 
                AND 
                (SELECT enddate FROM project WHERE projectID = new.projectID)
            )
        )
    BEGIN
        DELETE FROM plan WHERE pID = new.pID ;
    END
;

Testing/Demo

以上测试使用:-

DROP TABLE IF EXISTS Project;
CREATE TABLE Project (
    projectID varchar(255) NOT NULL UNIQUE,
    name varchar(255) NOT NULL DEFAULT ' ',
    leader varchar(255) NOT NULL DEFAULT ' ',
    budget varchar(255) NOT NULL DEFAULT '0',
    startDate DATE NOT NULL DEFAULT '2000-12-31',
    endDate DATE NOT NULL DEFAULT '2000-12-31'
    CHECK (JulianDay(startDate) <= JulianDay(endDate)),
    PRIMARY KEY (projectID)
);
DROP TABLE IF EXISTS Plan;
CREATE TABLE Plan (
    pID varchar(255) NOT NULL UNIQUE,
    projectID varchar(255) DEFAULT NULL,
    name varchar(255) NOT NULL DEFAULT ' ',
    startDate DATE NOT NULL DEFAULT ' ' ,
    endDate DATE NOT NULL DEFAULT ' ',
    CHECK (endDate >= startDate),
    PRIMARY KEY (pID, projectID),
    FOREIGN KEY (projectID) REFERENCES Project(projectID)
);
DROP TABLE IF EXISTS trigger_log;
CREATE TABLE IF NOT EXISTS trigger_log (id INTEGER PRIMARY KEY, timestamp TEXT DEFAULT CURRENT_TIMESTAMP, trigger_text TEXT);
DROP TRIGGER IF EXISTS beforeInsertInPlan;
CREATE TRIGGER IF NOT EXISTS afterInsertInPlan 
    AFTER INSERT ON plan 
    WHEN (
            (NOT (new.startdate) BETWEEN 
                (SELECT startdate FROM project WHERE projectID = new.projectID) 
                AND 
                (SELECT enddate FROM project WHERE projectID = new.projectID)
            )
            OR 
            (NOT (new.enddate) BETWEEN 
                (SELECT startdate FROM project WHERE projectID = new.projectID) 
                AND 
                (SELECT enddate FROM project WHERE projectID = new.projectID)
            )
        )
    BEGIN
        DELETE FROM plan WHERE pID = new.pID ;
        INSERT INTO trigger_log (trigger_text) VALUES('DELETED FROM Plan Table due to date(s) not within project. pID was '||new.pID);
    END
;

INSERT INTO project  VALUES ('P1','P1','Mary',100,'2021-09-01','2022-09-30');
INSERT INTO plan VALUES ('P1P1','P1','Plan1','2021-09-01','2022-09-30');
INSERT INTO plan VALUES ('P1P2','P1','Plan2','2021-08-01','2022-09-30'); /* X */
INSERT INTO plan VALUES ('P1P3','P1','Plan3','2021-09-01','2022-10-30'); /* X */
INSERT INTO plan VALUES ('P1P4','P1','Plan4','2020-09-01','2022-10-30'); /* X */
INSERT INTO plan VALUES ('P1P5','P1','Plan5','2021-09-01','2021-10-01');
INSERT INTO plan VALUES ('P1P6','P1','Plan6','2021-10-01','2021-11-01');
INSERT INTO plan VALUES ('P1P7','P1','Plan7','2021-11-01','2021-12-01');
SELECT * FROM plan;
/* Cleanup Environment */
SELECT * FROM trigger_log;
DROP TABLE IF EXISTS trigger_log;
DROP TRIGGER IF EXISTS beforeInsertInPlan;
DROP TABLE IF EXISTS Plan;
DROP TABLE IF EXISTS Project;

当 运行 时,结果为:-

  1. 计划在 计划中 table:-

  • 即未插入那些带有 X (3) 的评论
  1. trigger_log(测试时用于确认触发):-

  • 即未插入的 3 个带有 X 的评论已相应记录。

为什么不使用 BEFORE INSERT 触发器的示例

交换触发器以使用 BEFORE INSERT 和 :-

全部插入:-

None 即使已登录也被删除:-

  • 即没有要删除的内容,因为没有插入任何内容。