​You are right that my purpose does seem kind of confusing.

What I really want is UPSERT to avoid doing an UPDATE, checking if the
number of rows affected is zero, then doing an INSERT. The lack of UPSERT
leads to a lot more application code using the UPDATE/INSERT combination.
UPSERT doesn't exist in SQLite so I was trying to work around that by using
INSERT OR REPLACE which is not the same thing. I can see from another
recent thread that some others also think that UPSERT would be a valuable
addition to SQLite.​

Peter


On Fri, Mar 16, 2018 at 2:07 PM, Keith Medcalf <kmedc...@dessus.com> wrote:

>
> It is kind of hard to write a specific trigger since your "purpose" is
> confusing.  You have defined some referential integrity and are then
> ignoring it.  If your goal is to update the parent, then why not use the
> statement designed to do that (UPDATE) ... ?
>
> ---
> The fact that there's a Highway to Hell but only a Stairway to Heaven says
> a lot about anticipated traffic volume.
>
>
> >-----Original Message-----
> >From: sqlite-users [mailto:sqlite-users-
> >boun...@mailinglists.sqlite.org] On Behalf Of Peter Michaux
> >Sent: Friday, 16 March, 2018 12:42
> >To: SQLite mailing list
> >Subject: Re: [sqlite] Bug? INSERT OR REPLACE not equivalent to DELETE
> >followed by INSERT
> >
> >Thank you for the information, Keith.
> >
> >It comes as a surprise to me that the conflict resolution clause of
> >the
> >statement that causes a trigger to fire can override an explicit
> >conflict
> >resolution clause in the body of a trigger. But, as you pointed out,
> >it is
> >documented.
> >
> >How can I write the trigger to not use a conflict resolution clause?
> >I'm
> >trying a bunch of different things but with no luck. Something like
> >the
> >following is possible?
> >
> >CREATE TRIGGER users_after_insert AFTER INSERT ON users
> >BEGIN
> >    CASE WHEN (SELECT count(*) FROM user_extras WHERE user_id =
> >new.id)) =
> >0 THEN
> >        INSERT INTO user_extras (user_id) VALUES (new.id)
> >    END;
> >END;
> >
> >Thanks.
> >
> >Peter
> >
> >
> >
> >On Mon, Mar 12, 2018 at 8:50 PM, Keith Medcalf <kmedc...@dessus.com>
> >wrote:
> >
> >>
> >> On this page, 7th paragrph:
> >>
> >> https://www.sqlite.org/lang_createtrigger.html
> >>
> >> See that:
> >>
> >> An ON CONFLICT clause may be specified as part of an UPDATE or
> >INSERT
> >> action within the body of the trigger. However if an ON CONFLICT
> >clause is
> >> specified as part of the statement causing the trigger to fire,
> >then
> >> conflict handling policy of the outer statement is used instead.
> >>
> >> ---
> >> The fact that there's a Highway to Hell but only a Stairway to
> >Heaven says
> >> a lot about anticipated traffic volume.
> >>
> >>
> >> >-----Original Message-----
> >> >From: sqlite-users [mailto:sqlite-users-
> >> >boun...@mailinglists.sqlite.org] On Behalf Of Peter Michaux
> >> >Sent: Monday, 12 March, 2018 21:09
> >> >To: sqlite-users@mailinglists.sqlite.org
> >> >Subject: [sqlite] Bug? INSERT OR REPLACE not equivalent to DELETE
> >> >followed by INSERT
> >> >
> >> >Hi,
> >> >
> >> >I have read that INSERT OR REPLACE is equivalent to a DELETE
> >followed
> >> >by an
> >> >INSERT. I came across a case where that is not true.
> >> >
> >> >Set up a test case
> >> >
> >> >    $ rm -f asdf.sqlite && sqlite3 asdf.sqlite
> >> >
> >> >    sqlite> .mode columns
> >> >    sqlite> .headers on
> >> >    sqlite> PRAGMA foreign_keys=OFF;
> >> >
> >> >    sqlite> CREATE TABLE users (
> >> >       ...>     id INT UNSIGNED NOT NULL PRIMARY KEY,
> >> >       ...>     username TEXT NOT NULL
> >> >       ...> );
> >> >
> >> >    sqlite> CREATE TABLE user_extras (
> >> >       ...>     user_id INT UNSIGNED NOT NULL PRIMARY KEY,
> >> >       ...>     other INT NULL DEFAULT NULL,
> >> >       ...>     FOREIGN KEY (user_id) REFERENCES users(id) ON
> >UPDATE
> >> >CASCADE ON DELETE CASCADE
> >> >       ...> );
> >> >
> >> >    sqlite> INSERT INTO users (id, username) VALUES (1, 'asdf');
> >> >
> >> >    sqlite> INSERT INTO user_extras (user_id, other) VALUES (1,
> >33);
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >    id          username
> >> >    ----------  ----------
> >> >    1           asdf
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >
> >> >Let's try a delete followed by an insert.
> >> >
> >> >    sqlite> DELETE FROM users WHERE id = 1;
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >    sqlite> INSERT INTO users (id, username) VALUES (1, 'asdf');
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >    id          username
> >> >    ----------  ----------
> >> >    1           asdf
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >Notice that the value `user_extras.other` is still 33. That's
> >good.
> >> >
> >> >    sqlite> INSERT OR REPLACE INTO users (id, username) VALUES (1,
> >> >'asdf');
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >    id          username
> >> >    ----------  ----------
> >> >    1           asdf
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >Still 33. That's good.
> >> >
> >> >Based on the above, it looks like `INSERT OR REPLACE` is
> >equivalent
> >> >to a
> >> >`DELETE` followed by an `INSERT`.
> >> >
> >> >If we add a trigger, things change...
> >> >
> >> >    sqlite> CREATE TRIGGER users_after_insert AFTER INSERT ON
> >users
> >> >       ...> BEGIN
> >> >       ...>     INSERT OR IGNORE INTO user_extras (user_id) VALUES
> >> >(new.id);
> >> >       ...> END;
> >> >
> >> >A `DELETE` followed by an `INSERT` still works as before.
> >> >
> >> >    sqlite> DELETE FROM users WHERE id = 1;
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >    sqlite> INSERT INTO users (id, username) VALUES (1, 'asdf');
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >    id          username
> >> >    ----------  ----------
> >> >    1           asdf
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1           33
> >> >
> >> >See above that the value of `user_extras.other` survived the
> >`DELETE`
> >> >followed by the `INSERT`.
> >> >
> >> >When we use `INSERT OR REPLACE` the `user_extras.other` value is
> >> >cleared
> >> >out.
> >> >
> >> >    sqlite> INSERT OR REPLACE INTO users (id, username) VALUES (1,
> >> >'asdf');
> >> >
> >> >    sqlite> SELECT * FROM users;
> >> >    id          username
> >> >    ----------  ----------
> >> >    1           asdf
> >> >
> >> >    sqlite> SELECT * FROM user_extras;
> >> >    user_id     other
> >> >    ----------  ----------
> >> >    1
> >> >
> >> >Because of the trigger, `INSERT OR REPLACE` is no longer
> >equivalent
> >> >to
> >> >`DELETE` followed by `INSERT`.
> >> >
> >> >
> >> >Peter
> >> >_______________________________________________
> >> >sqlite-users mailing list
> >> >sqlite-users@mailinglists.sqlite.org
> >> >http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
> >users
> >>
> >>
> >>
> >> _______________________________________________
> >> sqlite-users mailing list
> >> sqlite-users@mailinglists.sqlite.org
> >> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-
> >users
> >>
> >_______________________________________________
> >sqlite-users mailing list
> >sqlite-users@mailinglists.sqlite.org
> >http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
>
>
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to