使用 INSERT INTO 触发器时 SQLite sqlite3_last_insert_rowid 不增加

问题描述 投票:0回答:1

我有一个带有

INTEGER PRIMARY KEY
的表和指向其他表的几个
FOREIGN KEY
字段:

CREATE TABLE DifficultTable 
(
    id     INTEGER NOT NULL UNIQUE,
    name   TEXT,
    fooId  INTEGER,
    barId  INTEGER,

    PRIMARY KEY(id AUTOINCREMENT),
    FOREIGN KEY(fooId) REFERENCES FooTable(id)
    FOREIGN KEY(barId) REFERENCES BarTable(id)
);

CREATE TABLE FooTable
(
    id   INTEGER NOT NULL UNIQUE,
    name TEXT    NOT NULL UNIQUE,

    PRIMARY KEY (id AUTOINCREMENT)
);

CREATE TABLE BarTable
(
    id   INTEGER NOT NULL UNIQUE,
    name TEXT    NOT NULL UNIQUE,

    PRIMARY KEY (id AUTOINCREMENT)
);

为了简化访问它的 C-API,我还在

VIEW
中提供此数据,将这些外键解析为名称,并为
INSERT
提供触发器:

CREATE VIEW SimpleView 
AS
    SELECT
        DifficultTable.id,
        DifficultTable.name,
        FooTable.name AS foo,
        BarTable.name AS bar
    FROM 
        DifficultTable
    LEFT JOIN 
        FooTable ON DifficultTable.fooId = FooTable.id
    LEFT JOIN 
        BarTable ON DifficultTable.barId = BarTable.id;

CREATE TRIGGER SimpleInsert 
AS
INSTEAD OF INSERT ON SimpleView
BEGIN
    INSERT INTO DifficultTable(name, fooId, barId) 
    VALUES (NEW.name,
            (SELECT id FROM FooTable WHERE name = New.foo),
            (SELECT id FROM BarTable WHERE name = New.bar)
           );
END;

如果我在

FooTable
BarTable
中插入一些值,我可以确认
sqlite3_last_insert_rowid()
运行良好:

sqlite> INSERT INTO FooTable(name) VALUES ("One"),("Two"),("Three"),("Four");
sqlite> SELECT last_insert_rowid();
4    <-- Good.  There are now four rows in FooTable.
sqlite> INSERT INTO BarTable(name) VALUES ("One"),("Two");
sqlite> SELECT last_insert_rowid();
2    <-- Good.  There are now two rows in BarTable

但是如果我插入

SimpleView
last_insert_rowid()
不会更新:

sqlite> INSERT INTO SimpleView (name, foo, bar) VALUES ("One", "Four", "Two");
sqlite> SELECT last_insert_rowid();
2  <-- Expected 1 because there is now 1 row in DifficultTable

有没有简单的方法来获取 rowid?

运行这些命令后数据库中所有数据的摘要:

FooTable

id 名字
1 一个
2 两个
3
4 四个

吧台

id 名字
1 一个
2 两个

简单视图

id 名字 酒吧
1 一个 四个 两个

难看

id 名字 fooId 栏ID
1 一个 4 2

我希望使用

sqlite3_last_insert_rowid()
,因为它只是 C 中的 1-liner。我也许可以执行另一个 SQL 查询,但是否保证
id
始终会递增(即使行被删除?)

SELECT id 
FROM DifficultTable 
ORDER BY id DESC 
LIMIT 1
sqlite
1个回答
0
投票

这是根据肖恩的评论给出的答案。 最后插入 Rowid 文档 说:

如果在触发器内发生 INSERT,则只要触发器正在运行,此例程就会返回插入行的 rowid。一旦触发器程序结束,该例程返回的值将恢复为触发触发器之前的值。

这意味着在触发器上完成 INSERT 后您无法使用

sqlite3_last_insert_rowid()
。另一种方法是执行查询:

SELECT id 
FROM DifficultTable 
ORDER BY id DESC 
LIMIT 1

这会很好地工作,除非由于

AUTOINCREMENT
:

的描述而填满了表格

通常的算法是为新创建的行指定一个比插入之前表中最大 ROWID 大 1 的 ROWID。 ...如果最大的 ROWID 等于最大可能的整数...数据库引擎开始随机挑选正候选 ROWID,直到找到以前未使用过的 ROWID。

AUTOINCREMENT
没有必要。使用此关键字将上面的描述更改为:

为新行选择的 ROWID 至少比同一表中之前存在的最大 ROWID 大 1

© www.soinside.com 2019 - 2024. All rights reserved.