Files
email-tracker/external/duckdb/test/sql/upsert/upsert_basic.test
2025-10-24 19:21:19 -05:00

219 lines
4.3 KiB
SQL

# 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;
----
<REGEX>: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