我有一个基于网络的系统,它有几个表(postgres / pgsql),可以容纳多对多的关系,例如; 表x column_id1 smallint FK column_id2 smallint FK
在此方案中,更新基于column_id2
首先更新这些记录,我们将运行以下函数;
-- edited to protect the innocent
CREATE FUNCTION associate_id1_with_id2(integer[], integer) RETURNS integer
AS $_$
DECLARE
a alias for $1;
b alias for $2;
i integer;
BEGIN
delete from tablex where user_id = b;
FOR i IN array_lower(a,1) .. array_upper(a,1) LOOP
INSERT INTO tablex (
column_id2,
column_id1)
VALUES (
b,
a[i]);
end loop;
RETURN i;
END;
$_$
LANGUAGE plpgsql;
这似乎很草率,现在增加了审计,它确实显示出来了。
我现在要做的只是删除并插入必要的行。
我一直在尝试各种形式的以下运气
CREATE OR REPLACE FUNCTION associate_id1_with_id2(integer[], integer) RETURNS integer
AS $_$
DECLARE
a alias for $1;
b alias for $2;
c varchar;
i integer;
BEGIN
c = array_to_string($1,',');
INSERT INTO tablex (
column_id2,
column_id1)
(
SELECT column_id2, column_id1
FROM tablex
WHERE column_id2 = b
AND column_id1 NOT IN (c)
);
DELETE FROM tablex
WHERE column_id2 = b
AND column_id1 NOT IN (c);
RETURN i;
END;
$_$
LANGUAGE plpgsql;
取决于我正在尝试的函数的版本,当前版本存在各种错误,例如显式类型转换(我猜它不像c是varchar?)。
首先,我的方法是正确的还是有一个更优雅的解决方案,因为有几个表需要这种类型的处理?如果没有,请指出我正确的方向?
如果这是正确的方法,你可以协助where子句的NOT IN部分的数组转换吗?
答案 0 :(得分:1)
而不是array_to_string
,使用unnest
将数组转换为一组行(就好像它是一个表),并且可以使用vanilla SQL解决问题:
INSERT INTO tablex(column_id1,column_id2)
select ai,b from unnest(a) as ai where not exists
(select 1 from tablex where column_id1=ai and column_id2=b);
DELETE FROM tablex
where column_id2=b and column_id1 not in
(select ai from unnest(a) as ai);