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
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users