2012-06-11 108 views
0

我有一個基於Web的系統,有幾個表(postgres/pgsql),可以容納多對多的關係,如; 表X column_id1 SMALLINT FK column_id2 SMALLINT FK使用postgresql/plpgsql更新許多記錄

在這種情況下的更新是基於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?)爲當前版本。

首先,我的方法是否正確或者是否有更優雅的解決方案,因爲有幾個表需要這種類型的處理?如果不是,請你指點我正確的方向?

如果這是正確的方法,你可以請協助數組轉換的NOT IN部分的where子句?

回答

1

代替array_to_string,使用unnest到陣列轉換成一組行的(就好像它是一個表),和問題可以用香草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);