Given
the below schema
CREATE TABLE Item (
_id INTEGER NOT NULL,
name NVARCHAR NOT NULL,
parent INTEGER NULL
CONSTRAINT fk_Recursive
REFERENCES Item(_id),
PRIMARY KEY(_id AUTOINCREMENT)
);
CREATE TABLE Container (
_id INTEGER NOT NULL,
name NVARCHAR NOT NULL,
root INTEGER NOT NULL
CONSTRAINT fk_Container_root
REFERENCES Item(_id),
PRIMARY KEY(_id AUTOINCREMENT)
);
Used in client
e.g. Java equivalent prepared statements with ?
s and params of these two statements:
INSERT INTO Item VALUES (1, 'ROOT', NULL);
INSERT INTO Container VALUES (1, 'My Box', 1);
Question
Is it possible to write a trigger (or anything else) without client code (only SQL) which achieves the above results with only
INSERT INTO Container(name) VALUES('My Box');
Note: Of course the client code will retrieve the new rowid
for the inserted Container
, but I don't care about the new (root) Item
, that will be used much later by reading from Container
.
The trigger would be along the lines of:
CREATE TRIGGER Rooter
INSTEAD OF INSERT ON Container WHEN (root IS NULL) BEGIN
SET newRoot = INSERT INTO Item(name, parent) VALUES ('ROOT', NULL);
INSERT INTO Container VALUES (new._id, new.name, newRoot);
END;
Changing Container.root
to NULL
and creating an AFTER INSERT TRIGGER
shouldn't be an option. But then I guess the same problem of getting the Item
's rowid
would still stand.
Best Answer
Based on CL's suggestion to take another look at
last_insert_rowid()
and now that it's clear thatINSTEAD OF
triggers are only forVIEW
s (see question's comments), here's a working version:Output with comments:
Notes:
INSERT INTO Table VALUES
format helps to catch schema modification bugs since when a new column is added theINSERT
will fail instead of ignoring the new column.Container
table to insert into.last_insert_rowid()
doesn't work when used after anINSERT INTO
on a view withINSTEAD OF INSERT
, i.e. afterINSERT INTO Container_Auto
, you'll have to requery the inserted row :(