>>>>> Igor Tandetnik writes:
[…]
> Note that ending up in the IGNORE branch of INSERT OR IGNORE
> statement doesn't constitute failure, but normal execution. The same
> is true for INSERT ... SELECT statement where SELECT returns zero
> rows so nothing is actually inserted.
Thus was my question: how do I ensure that a SELECT … INSERT
statement results in exactly one row being inserted?
(Additional constraint: it should be possible to use the code in
a trigger.) The best thing I was able to imagine is to replace:
INSERT INTO "bar" ("foo")
SELECT f."rowid" FROM "foo" f WHERE f."foo" = ?1;
with:
INSERT INTO "bar" ("foo")
VALUES ((SELECT f."rowid" FROM "foo" f WHERE f."foo" = ?1));
… The task I'm solving seems unlike an unusual one. Suppose
that, e. g., I'm recording a history of clients. Each client
has a name, and is served an arbitrary (but positive) number of
times, at particular dates. Or, for the 0'th approximation:
CREATE TABLE "history" (
"client-name" TEXT NOT NULL,
-- as in: CAST (strftime ('%s', 'now') AS INTEGER), or now ()
"timestamp" INTEGER NOT NULL
);
The redundancy of the schema above could, however, be reduced as
follows:
CREATE TABLE "client" (
"name" TEXT NOT NULL
);
CREATE UNIQUE INDEX "client-unique"
ON "client" ("name");
CREATE TABLE "history-1" (
"client" INTEGER NOT NULL REFERENCES "client",
"timestamp" INTEGER NOT NULL
);
Now, I wish to preserve the simplicity of access of the first
variant. Thus, I create a VIEW:
CREATE VIEW "history"
AS SELECT c."name" AS "client-name",
h."timestamp"
FROM "history-1" h
INNER JOIN "client" c
ON (c."rowid" = h."client");
… and a TRIGGER:
CREATE TRIGGER "history-insert"
INSTEAD OF INSERT ON "history" FOR EACH ROW BEGIN
INSERT OR IGNORE INTO "client" ("name")
VALUES (new."client-name");
INSERT INTO "history-1" ("client", "timestamp")
VALUES ((SELECT c."rowid"
FROM "client".c
WHERE c."name" = new."client-name"),
new."timestamp");
END;
This way, an application can SELECT from and INSERT into this
new "history" VIEW with just the same simplicity as was possible
with the former "history" TABLE. Naturally, this trigger
requires that a single INSERT to the "history" VIEW results in
exactly a single INSERT to the underlying "history-1" TABLE.
(Which is what brought my question above.)
To note is that, with little CASE trickery, it's possible to
support “hybrid” (id, value) views (c."rowid" AS "client-id" in
the VIEW above), and NULL non-constraints, just as well.
--
FSF associate member #7257 np. ml_hygm.xm
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users