我在数据库中有以下表格:
CREATE TYPE status AS ENUM (
'void',
'steady',
'transition'
);
CREATE TABLE relations (
marker integer NOT NULL,
related integer[] NOT NULL,
status status DEFAULT 'void'::status NOT NULL,
id serial -- pgAdmin requires primary key
);
ALTER TABLE ONLY relations
ADD CONSTRAINT pkey_id PRIMARY KEY (id);
INSERT INTO relations (marker, related, status)
VALUES
(3, '{6}', 'steady'::status),
(3, '{2}', 'transition'::status),
(6, '{4}', 'void'::status),
(6, '{2}', 'steady'::status),
(4, '{2}', 'steady'::status),
(4, '{6}', 'void'::status);
这就是表格的样子:
marker | related | status | id
--------+---------+------------+----
3 | {6} | steady | 1
3 | {2} | transition | 2
6 | {4} | void | 3
6 | {2} | steady | 4
4 | {2} | steady | 5
4 | {6} | void | 6
marker/status
组合应该是唯一的,即使没有相应的约束。这不是问题。
我也有这个功能:
CREATE OR REPLACE FUNCTION update_relations(integer, integer, status) RETURNS void
LANGUAGE plpgsql
AS $_$
BEGIN
update relations
set related = array_append(related,
(CASE
WHEN marker = $1 THEN $2
WHEN marker = $2 THEN $1
END)
)
where
marker in ($1,$2) AND
status = $3;
END;
$_$;
当我跑步时
SELECT update_relations(3, 4, 'void'::status);
然后我希望marker
值为4
且status
为'无效'的行更新其related
值并将3
附加到marker = 3
阵列。因此,具有status = 'void'::status
和4
的行应将related
附加到其 marker | related | status | id
--------+---------+------------+----
3 | {6} | steady | 1
3 | {2} | transition | 2
6 | {4} | void | 3
6 | {2} | steady | 4
4 | {2} | steady | 5
4 | {6,3} | void | 6
数组。但是,这就是结果:
marker = 4
如您所见,status = 'void'::status
和 marker | related | status | id
--------+---------+------------+----
3 | {6} | steady | 1
3 | {2} | transition | 2
6 | {4} | void | 3
6 | {2} | steady | 4
4 | {2} | steady | 5
4 | {6,3} | void | 6
3 | {4} | void | 7
的行已按预期更新。由于没有符合'marker = 3和status ='void':: status`要求的相应行,因此不会发生更新。在这种情况下,我想插入一行,结果将是:
marker/status
如果不存在所需的{{1}}组合,我该怎样对表格进行UPSERT?
PS:我正在使用postgres 9.4。
答案 0 :(得分:1)
Postgres“upsert”函数ON CONFLICT UPDATE适用于9.5及更高版本,但您的版本为9.4。
如果您不担心并发性,可以这么做:
if exists (select * from relations where marker in ($1,$2) AND status = $3) then
update relations
set ...
where marker in ($1,$2) AND status = $3;
else
insert into relations
(marker, related, status)
values ($1, ARRAY[$2], $3);
end if
这种方法确实存在并发问题。有关更好(和更复杂)的解决方案,请参阅this question。