使用此表
create table FOLDER
(
_ID integer primary key autoincrement,
NAME text not null,
PARENT integer not null,
DELETED integer,
constraint VALUEOF_folder_deleted check (DELETED == 1 or DELETED isnull) on conflict abort,
unique (NAME, PARENT) on conflict abort
);
我想替换存在NAME PARENT组合的插入,并将DELETED设置为1,并将替换设置为DELETED字段为null。
我尝试了这个触发器:
CREATE TRIGGER REPLACE_INS_folder instead of insert on FOLDER
when exists (select 1 from FOLDER where NAME == new.NAME and PARENT == new.PARENT and DELETED == 1)
begin
update FOLDER set DELETED = null where NAME == new.NAME and PARENT == new.PARENT;
end;
但收到:
Error: cannot create INSTEAD OF trigger on table: FOLDER
最初我在触发器中遇到语法错误,但收到了相同的错误,表明存在更严格的限制。本文档https://www.sqlite.org/lang_createtrigger.html中的图表表明我的触发器有效。但是,文本的第二部分A trigger may be specified to fire whenever a DELETE, INSERT, or UPDATE of a particular database table occurs, or whenever an UPDATE occurs on on one or more specified columns of a table.
让我想知道WHEN是否只允许使用更新触发器。
请注意,这是表格上的触发器,而不是视图。
答案 0 :(得分:6)
通过在CREATE TRIGGER语句中指定INSTEAD OF,可以在视图和普通表上创建触发器。
这是相当误导的。这句话实际上试图说的是
您不能在表上使用INSTEAD OF触发器。将其更改为视图:
CREATE TABLE FolderTable(...);
CREATE VIEW Folder AS SELECT * FROM FolderTable;
CREATE TRIGGER ... INSTEAD OF INSERT ON Folder ...;
(然后你还需要INSTEAD OF UPDATE / DELETE触发器。)
答案 1 :(得分:1)
尝试一下:
CREATE TRIGGER replace_ins_folder
BEFORE INSERT ON folder
WHEN EXISTS (SELECT 1 FROM folder
WHERE name == new.name
AND parent == new.parent
AND deleted == 1)
BEGIN
UPDATE folder
SET deleted = NULL
WHERE name == new.name AND parent == new.parent;
SELECT RAISE(IGNORE);
END;
答案 2 :(得分:0)
自SQLite 3.24.0(2018-06-04)起,所请求的功能已优雅地封装在UPSERT方案INSERT..ON CONFLICT中:https://www.sqlite.org/lang_UPSERT.html
但是,就我而言,我用来编写数据库客户端的编程语言无法识别“ ON CONFLICT”子句。
因此,我已经实施了Artem Odnovolov的建议的修改版本。它可以工作,但是需要对我的方案进行一些调整,这要比Steve Waring发布的方案更具通用性。通用版本为:
仍然以史蒂夫·沃林(Steve Waring)的表格为例,表格创建代码如下所示:
CREATE TABLE folder(id integer PRIMARY KEY,
name text,
parent integer,
deleted integer,
UNIQUE(name, parent)
);
以及BEFORE INSERT触发器:
CREATE TRIGGER replace_ins_folder
BEFORE INSERT ON folder
WHEN EXISTS (SELECT 1 FROM folder --check for violation of UNIQUE constraint
WHERE name IS NEW.name
AND parent IS NEW.parent
)
BEGIN
UPDATE folder
SET deleted = NEW.deleted
WHERE name IS NEW.name
AND parent IS NEW.parent
AND deleted IS NOT NEW.deleted; -- only do update when there is something to change
-- otherwise subsequent ON UPDATE triggers may fire when not intended
END;