在 SQLITE 中插入后使用触发器创建复合唯一键字段

Create composed unique key field with trigger after insert in SQLITE

我有一个包含多个列的 table,其中一个(唯一键)应该是由其他两列的值组成的值。

CREATE TABLE batches (
    id   TEXT PRIMARY KEY UNIQUE,
    name TEXT NOT NULL,
    project_id INTEGER);

在每次插入时,我想根据 'name' 和 'project_id' 的值生成 id(这个可以为 null):

INSERT INTO batches (name,project_id) VALUES
     ('21.01',NULL),
     ('21.01',1),
     ('21.02',2);

所以,我创建了一个 table TRIGGER 但没有执行。

CREATE TRIGGER create_batches_id 
AFTER INSERT ON batches FOR EACH ROW
BEGIN
    UPDATE batches 
    SET id = SELECT quote(name ||"_"|| (CASE project_id 
            WHEN NULL THEN '' ELSE project_id END )
        FROM batches WHERE rowid = (SELECT MAX(rowid) FROM batches))
    WHERE rowid = (SELECT MAX(rowid) FROM batches);
END;

错误:

SQL Error [1]: [SQLITE_ERROR] SQL error or missing database (near "SELECT": syntax error)

我预计:

id = 21.01_
id = 21.01_1
id = 21.01_2

我做错了什么?如果我 运行 只有 SELECT/CASE 声明它 returns ok: '21.01_2'

我也尝试过不使用 quote() 函数,但没有成功。

更新一:

我已经成功执行了整个创建触发器语句(缺少括号):

CREATE TRIGGER create_batch_id 
AFTER INSERT ON batches FOR EACH ROW
BEGIN
    UPDATE batches 
    SET id = (SELECT name ||"_"|| (CASE project_id WHEN NULL THEN 0 ELSE project_id END ) FROM batches WHERE rowid = (SELECT MAX(rowid) FROM batches) )
    WHERE rowid = (SELECT MAX(rowid) FROM batches);
END;  

我的编辑器 (DBeaver) 似乎在使用以下换行符时出现问题。如果它在 selection 内,它 运行s 进入这个异常(或者我遗漏了一些东西):

SQL Error [1]: [SQLITE_ERROR] SQL error or missing database (incomplete input)

如果我仅手动 select 上述行(从 CREATE 到 ;),则会创建触发器,但不是预期的结果。如果 project_id 中的值为 NULL,则不会创建任何 id 值。

不要在 table 中添加列 id
而是将nameproject_id的组合定义为table的PRIMARY KEY,这样也是UNIQUE:

CREATE TABLE batches (
    name TEXT NOT NULL,
    project_id INTEGER,
    PRIMARY KEY(name, project_id)
)

然后,只要您需要 id,您就可以 运行 查询:

SELECT name || '_' || COALESCE(project_id, '') AS id, 
       name, 
       project_id
FROM batches

或创建视图:

CREATE VIEW v_batches AS
SELECT name || '_' || COALESCE(project_id, '') AS id, 
       name, 
       project_id
FROM batches

并查询视图:

SELECT * FROM v_batches

参见demo

或者如果您的 SQLite 版本是 3.31.0+,您可以将列 id 作为 generated column:

CREATE TABLE batches (
    name TEXT NOT NULL,
    project_id INTEGER,
    id TEXT GENERATED ALWAYS AS (name || '_' || COALESCE(project_id, '')),
    PRIMARY KEY(name, project_id)
);