创建触发器以比较两个表中的日期
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;
当 运行 时,结果为:-
- 计划在 计划中 table:-
- 即未插入那些带有 X (3) 的评论
- trigger_log(测试时用于确认触发):-
- 即未插入的 3 个带有 X 的评论已相应记录。
为什么不使用 BEFORE INSERT 触发器的示例
交换触发器以使用 BEFORE INSERT 和 :-
全部插入:-
None 即使已登录也被删除:-
- 即没有要删除的内容,因为没有插入任何内容。
我有两个表,它们都有单独的 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;
当 运行 时,结果为:-
- 计划在 计划中 table:-
- 即未插入那些带有 X (3) 的评论
- trigger_log(测试时用于确认触发):-
- 即未插入的 3 个带有 X 的评论已相应记录。
为什么不使用 BEFORE INSERT 触发器的示例
交换触发器以使用 BEFORE INSERT 和 :-
全部插入:-
None 即使已登录也被删除:-
- 即没有要删除的内容,因为没有插入任何内容。