# name: test/sql/upsert/upsert_basic.test # group: [upsert] statement ok PRAGMA enable_verification; statement ok CREATE TABLE tbl( i INT PRIMARY KEY, j INT UNIQUE, k INT ); statement ok INSERT INTO tbl VALUES (1, 10, 1), (2, 20, 1), (3, 30, 2); # Update the on-conflict column. statement ok INSERT INTO tbl VALUES (3, 5, 1) ON CONFLICT (i) DO UPDATE SET i = i + 1; query III SELECT i, j, k FROM tbl ORDER BY ALL; ---- 1 10 1 2 20 1 4 30 2 query III SELECT i, j, k FROM tbl WHERE i = 4; ---- 4 30 2 # Update the on-conflict column again. statement ok INSERT INTO tbl VALUES (4, 30, 2) ON CONFLICT (i) DO UPDATE SET i = i - 1; query III SELECT i, j, k FROM tbl ORDER BY ALL; ---- 1 10 1 2 20 1 3 30 2 # Cannot update to the same PK value as another column. statement error INSERT INTO tbl VALUES (3, 30, 2) ON CONFLICT (i) DO UPDATE SET i = i - 2; ---- :Constraint Error.*violates primary key constraint.* # 'excluded' refers to the VALUES list, turning this into: # (k)2 + (k.excluded)1 = 3 statement ok insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = k + excluded.k; query III select * from tbl; ---- 1 10 1 2 20 1 3 30 3 # The ON CONFLICT does not refer to a column that's indexed on, so it's never true statement error insert into tbl VALUES (3,5,1) ON CONFLICT (k) DO UPDATE SET k = excluded.k; ---- Binder Error: The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT # Overwrite the existing value with the new value statement ok insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = excluded.k; query III select * from tbl; ---- 1 10 1 2 20 1 3 30 1 # Don't alter the existing row, but still insert the non-conflicting row statement ok insert into tbl VALUES (4,2,3), (3,5,10) ON CONFLICT (i) DO NOTHING; query III select * from tbl; ---- 1 10 1 2 20 1 3 30 1 4 2 3 # Two rows cause a conflict, on the same existing row # only the last one is used statement ok insert into tbl VALUES (3,3,10), (3,3,10) ON CONFLICT (i) DO UPDATE SET k = excluded.k; query III select * from tbl order by all ---- 1 10 1 2 20 1 3 30 10 4 2 3 # condition is not matched - no updates have happened query I insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 1 WHERE k < 5; ---- 0 query III select * from tbl; ---- 1 10 1 2 20 1 3 30 10 4 2 3 # When the condition is met, the DO is performed query I insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 1 WHERE k >= 5; ---- 1 # 'k' in row_id:3 is updated to 1 query III select * from tbl; ---- 1 10 1 2 20 1 3 30 1 4 2 3 # When the condition is on the DO UPDATE part, # it will always succeed, but turn into a DO NOTHING for the conflicts that don't meet the condition statement ok insert into tbl VALUES (3,5,3) on conflict (i) do update set k = 10 WHERE k != 1; # Unchanged, because the where clause is not met query III select * from tbl; ---- 1 10 1 2 20 1 3 30 1 4 2 3 statement ok insert into tbl VALUES (3,5,3) on conflict (i) do update set k = 10 WHERE k == 1; # Changed, because the where clause is met query III select * from tbl; ---- 1 10 1 2 20 1 3 30 10 4 2 3 # When we don't specify a conflict target, all unique/primary key constraints are used as the conflict target statement ok insert into tbl VALUES (5,1,0), (3,5,20) ON CONFLICT DO NOTHING; query III select * from tbl; ---- 1 10 1 2 20 1 3 30 10 4 2 3 5 1 0 # Not supported because: # > It's because one insert row could violate multiple different unique constraints, # with it being a different row for each of the constraints that's causing the violation, # and the upsert is only intended to update a single row. # https://sqlite.org/forum/info/45cf84d3e89d590d statement error insert into tbl VALUES (5,1,0), (3,5,20) ON CONFLICT DO UPDATE set k = excluded.k; ---- Binder Error: Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints statement ok create or replace table single_constraint ( i integer PRIMARY KEY, j integer, k varchar, ); statement ok insert into single_constraint values (5,1,'hello'), (1,10,'test'); # This is however accepted if only a single constraint exists on the table statement ok insert into single_constraint values (1,5,'bye'), (3,10,'quack') on conflict do update set j = excluded.j, k = concat(k, excluded.k); query III select * from single_constraint ---- 5 1 hello 1 5 testbye 3 10 quack