在 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
。
而是将name
和project_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)
);
我有一个包含多个列的 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
。
而是将name
和project_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)
);