2

次のように、PostgreSQL テーブル内に格納されたクエリを実行する PL/PgSQL 関数を作成しようとしています。

CREATE OR REPLACE FUNCTION evaluate_scenario(scenario_id int)
RETURNS TABLE(line_item_id int, organization_id int, data_element_id int, value varchar) AS $$
BEGIN
  RETURN QUERY
  SELECT
    li.id,
    li.organization_id,
    de.id,
    (EXECUTE 'SELECT ' || de.query)::varchar
  FROM
    line_items AS li INNER JOIN
    summary_files AS sf ON li.summary_file_id = sf.id INNER JOIN
    scenarios AS s ON s.summary_file_id = sf.id CROSS JOIN
    data_elements AS de
  WHERE
    s.id = 1 AND
    de.scope = 3 AND (
      de.model_id = s.model_id OR
      de.scenario_id = s.id OR
      de.organization_id = s.organization_id
    );
END;
$$ LANGUAGE plpgsql;

このクエリを実行しようとすると:

select line_item_id, data_element_id, value from evaluate_scenario(1)

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

********** Error **********

ERROR: type "execute" does not exist
SQL state: 42704
Context: PL/pgSQL function "evaluate_scenario" line 3 at RETURN QUERY

どんな助けでも大歓迎です。「EXECUTE」を削除して、これらの括弧内で SELECT de.query を実行すると、期待どおりにその列の値を受け取りますが、de.query を「EXECUTE」の受け入れ可能なクエリ文字列にする方法がわかりません。 "。

4

1 に答える 1

5

EXECUTEクエリ文字列をパラメーターとして受け取り、それを実行しますが、クエリでネストすることはできません EXECUTE

EXECUTEplpgsqlにはいくつかのバリアントがあります。あなたの場合、RETURN QUERY EXECUTE query最善かもしれません。マニュアルを読んでください。

これは機能する可能性があります-すべての混乱を修正しようとしているわけではなく、実際の例を示しているだけです。

CREATE OR REPLACE FUNCTION evaluate_scenario(_scenario_id int)
RETURNS TABLE(line_item_id int, organization_id int, data_element_id int, value varchar) AS
$func$

BEGIN
  RETURN QUERY EXECUTE '
  SELECT li.id,
         li.organization_id,
         de.id,
        (SELECT '
|| (SELECT query
    FROM   data_elements
    WHERE  scenario_id = _scenario_id)
|| ')
  FROM   line_items AS li
  JOIN   summary_files AS sf ON li.summary_file_id = sf.id
  JOIN   scenarios AS s ON s.summary_file_id = sf.id
  CROSS  JOIN data_elements AS de
  WHERE  s.id = 1
  AND    de.scope = 3
  AND   (de.model_id = s.model_id OR
         de.scenario_id = s.id OR
         de.organization_id = s.organization_id
        )';

END;
$func$ LANGUAGE plpgsql;

テキストリテラルをコードとして実行することは、本質的に安全ではないことに注意してください。誰かが aDROP * FROM tblまたはそのようなものをテーブルに密輸できる場合data_elements、あなたは大きな問題を抱えています. 私はSQLインジェクションについて話しています。
SQLi の詳細については、bobby-tables.com を参照してください

于 2012-09-20T23:13:21.443 に答える