摆弄SQL片刻之后,我无法达到预期的效果。 我搜索了PostgreSQL的文档,但是无法按照我想要的方式进行任何工作。
我有一个包含5列的表格:
| id | some_serial | user_id | foo | bar |
|----|-------------|---------|--------|--------|
| 1 | 8000000 | 42 | AA | <null> |
| 2 | 8000001 | <null> | <null> | CC |
我想将新值插入到表中,返回相应的序列。 如果新值与 user_id , foo 或 bar 中的任何数据匹配,则我希望更新该行,再次在此返回相应的序列号。
期望的行为:
例如:
插入42, AA, BB
将更新第一行。 bar将变成BB,并返回8000000。
| id | some_serial | user_id | foo | bar |
|----|-------------|---------|--------|--------|
| 1 | 8000000 | 42 | AA | BB |
| 2 | 8000001 | <null> | <null> | CC |
插入43, null, CC
将更新第二行。 user_id将变为43,并返回8000001。
| id | some_serial | user_id | foo | bar |
|----|-------------|---------|--------|--------|
| 1 | 8000000 | 42 | AA | BB |
| 2 | 8000001 | 43 | <null> | CC |
插入44, DD, EE
将创建一个新行,并返回新序列号。
| id | some_serial | user_id | foo | bar |
|----|-------------|---------|--------|--------|
| 1 | 8000000 | 42 | AA | BB |
| 2 | 8000001 | 43 | <null> | CC |
| 3 | 8000002 | 44 | DD | EE |
实际行为:
我已经尝试对(user_id,foo,bar)进行了唯一的约束,但这并没有给我想要的行为。第一次插入后,结果将是:
| id | some_serial | user_id | foo | bar |
|----|-------------|---------|--------|--------|
| 1 | 8000000 | 42 | AA | <null> |
| 2 | 8000001 | <null> | <null> | CC |
| 3 | 8000002 | 42 | AA | BB |
据我了解,这是因为约束将一起检查3列的唯一性。
我拥有的约束
ALTER TABLE my_table
ADD CONSTRAINT my_table_user_id_foo_bar_unique
UNIQUE (user_id, foo, bar);
我拥有的UPSERT:
INSERT INTO my_table (user_id, foo, bar)
VALUES (42, 'AA', 'BB')
ON CONFLICT ON CONSTRAINT my_table_user_id_foo_bar_unique
DO UPDATE
SET user_id = 42,
foo = COALESCE(my_table.foo, EXCLUDED.foo),
bar = COALESCE(my_table.bar, EXCLUDED.bar)
RETURNING some_serial;
任何帮助将不胜感激。 :-)
与此同时,我的解决方案是
我首先尝试更新该行,如果存在则返回该行。
UPDATE my_table
SET user_id = $1
, foo = COALESCE(foo, $2)
, bar = COALESCE(bar, $3)
WHERE (foo = $2 AND foo <> NULL)
OR (bar = $3 AND bar <> NULL)
RETURNING some_serial
如果该请求未返回任何内容,我将其插入:
INSERT INTO my_table (user_id, foo, bar)
VALUES ( $1, $2, $3)
RETURNING some_serial