0

私は、次のような多対多の関係を保持するいくつかのテーブル(postgres/pgsql)を持つWebベースのシステムを持っています。table 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 部分の配列変換を手伝っていただけますか?

4

1 に答える 1

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);
于 2012-06-12T00:36:18.590 に答える