5

plpgsql 関数またはストアド プロシージャを使用してテーブルにデータを挿入しようとしています。しかし、一度に複数のレコードを挿入したい。これらはすべて VARCHAR になるので、 のような関数を使用できると思いましたfunction(tablename VARCHAR, records VARCHAR[][])。しかし、その後、plpgsql での多次元配列のサポートはそれほど素晴らしいものではないことがわかりました。

これは、現時点で私の機能がどのように見えるかです。これは、私が探している結果を生成しません。私が尋ねると

SELECT insert_data('tennis', ARRAY[ARRAY['1','2'], ARRAY['3','4']])

次のエラーが表示されます

ERROR:  syntax error at or near "{"
LINE 1: INSERT INTO tennis VALUES (null, {{1}}), (null, {{3}});
                                         ^
QUERY:  INSERT INTO tennis VALUES (null, {{1}}), (null, {{3}});
CONTEXT:  PL/pgSQL function "insert_data" line 26 at EXECUTE statement

ただし、次のようなクエリを期待しています

INSERT INTO tennis VALUES (null, '1', '2'), (null, '3', '4');

卓球はこの構造なので、うまくいくでしょう。

CREATE OR REPLACE FUNCTION insert_data (dsetname_in VARCHAR, records VARCHAR[][])
RETURNS BOOLEAN AS $PROC$
DECLARE
    insertquery TEXT;
    val VARCHAR;
    i INT;
    j INT;
BEGIN
    insertquery = $$INSERT INTO $$ || dsetname_in || $$ VALUES $$;
    FOR i IN array_lower(records, 1)..array_upper(records, 1)
    LOOP
        insertquery = insertquery || $$(null, $$;
        FOR j IN array_lower(records[i:i], 1)..array_upper(records[i:i], 1)
        LOOP
            val = records[i:i][j:j];
            insertquery = insertquery || val;
            IF j <> array_upper(records[i:i], 1) THEN
                insertquery = insertquery || $$, $$;
            END IF;
        END LOOP;
        insertquery = insertquery || $$)$$;
        IF i <> array_upper(records, 1) THEN
            insertquery = insertquery || $$, $$;
        END IF;
    END LOOP;
    insertquery = insertquery || $$;$$;
    EXECUTE insertquery;
    RETURN TRUE;
END;$PROC$ LANGUAGE 'plpgsql';
4

1 に答える 1

5

有用なレベルの抽象化が追加されるとは思えないため、このアプローチ全体の価値については懐疑的です。ただし、それを行う必要があり、すべての値が文字列である場合、最もクリーンなアプローチは次のとおりだと思います。

CREATE OR REPLACE FUNCTION insert_data(dsetname_in text, records text[])
RETURNS VOID LANGUAGE plpgsql AS $PROC$
DECLARE
  insertquery text;
  i int;
BEGIN
  insertquery := 'INSERT INTO ' || dsetname_in || ' VALUES ';
  FOR i IN array_lower(records, 1)..array_upper(records, 1)
  LOOP
    insertquery := insertquery || '(null, ' || records[i] || '),';
  END LOOP;
  insertquery := left(insertquery, char_length(insertquery) - 1);
  EXECUTE insertquery;
END;
$PROC$;

次に、次のように呼び出すことができます。これは、ネストされた配列について示したものよりもきれいに見えます。

SELECT insert_data('tennis',
                   ARRAY[$$'1','2'$$,
                         $$'3','4'$$]);
于 2012-05-02T22:55:00.633 に答える