web-dev-qa-db-ja.com

PostgreSQLの文字列値(evalなど)内でクエリを実行する方法はありますか?

私はこのようにしたい:

SELECT (EVAL 'SELECT 1') + 1;

PostgreSQLでこのようにする方法(EVAL)はありますか?

14
minhee

「eval」しようとしているステートメントが常に同じデータ型を返す場合は、Grzegorzが言及したEXECUTEを使用するeval()関数を作成できます。

create or replace function eval(expression text) returns integer
as
$body$
declare
  result integer;
begin
  execute expression into result;
  return result;
end;
$body$
language plpgsql

その後、あなたは次のようなことをすることができます

SELECT eval('select 41') + 1;

ただし、動的ステートメントが評価する式ごとに異なるものを返す場合、このアプローチは機能しません。

また、これにより、任意のステートメントを実行することにより、セキュリティ上の大きなリスクが発生することにも注意してください。それが問題であるかどうかはあなたの環境に依存します。それが対話型SQLセッションでのみ使用される場合、それは問題ではありません。

18

ノート

言語PLpgSQL構文には、次のように言う多くの方法があります。

_ Y := f(X);
_

EXECUTE句は、「動的実行」(パフォーマンスの低下)専用です。

_ EXECUTE 'f(X)' INTO Y;     
_

静的宣言を実行するには、Y := f(X);またはSELECTを使用します。

_ SELECT f(X) INTO Y;
_

結果を破棄するとき、またはvoidリターンを処理するときは、 [〜#〜] perform [〜#〜] ステートメントを使用します。

_ PERFORM f(X);     
_
2
Peter Krauss

データ型テキストであるため、必要に応じて_::int_などのキャスト演算子を使用するとより柔軟になります:

_create or replace function eval( sql  text ) returns text as $$
declare
  as_txt  text;
begin
  if  sql is null  then  return null ;  end if ;
  execute  sql  into  as_txt ;
  return  as_txt ;
end;
$$ language plpgsql
-- select eval('select 1')::int*2         -- => 2
-- select eval($$ select 'a'||1||'b' $$)  -- => a1b
-- select eval( null )                    -- => null
_

また、これと別のeval( sql, keys_arr, vals_arr )関数を追加して、いくつかのカスタムキー値置換をサポートしました。例:便利な_:param1_置換用から postgres-utils

2

それがあなたに合っているかどうかはわかりませんが、PostgreSQLには EXECUTE ステートメントがあります。

1

良いアイデア。直接式を実行するように変更できます。

create or replace function eval(expression text) returns integer
as
$body$
declare
  result integer;
begin
  execute 'SELECT ' || expression into result;
  return result;
end;
$body$
language plpgsql;

実行するには、次のように入力します。

SELECT eval('2*2');
0
Oberdan