在PostgreSQL中是否有一种类似于eval的方法可以在字符串值内执行查询?

22

我想要做这样的事情:

SELECT (EVAL 'SELECT 1') + 1;

在 PostgreSQL 中有没有类似于这样的方法(EVAL)?

6个回答

22
如果你尝试使用 "eval" 执行的语句始终返回相同的数据类型,那么你可以编写一个 eval() 函数,该函数使用 Grzegorz 提到的 EXECUTE。
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会话中使用,则不是问题。


2

如果需要,我会选择使用数据类型文本,因为它使用强制转换运算符比如::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


能否使用这个方法返回多列?例如:select * from eval('select 1, ''hello''') ... 目前这个实现只返回结果集中的第一列,即 1 - skilbjo
@john-skilbeck:在这里:https://bitbucket.org/andi1234/postgres-utils#markdown-header-eval-eval2 我添加了支持多列/多行功能的eval2(...)变体。 - Andreas Covidiot
@AndreasCovidiot,postgres-utils的链接不再有效。那个代码还能在其他地方找到吗? - Robert Mikes
很遗憾,@RobertMikes,没有。您有哪个平台可以轻松提供和维护它的建议吗?这里有私信你的方式吗?(找不到 :-( )(我稍后会删除此评论) - Andreas Covidiot
在 GitHub 上吗?你可以查看我的个人资料并在 LinkedIn 上找到我。 - Robert Mikes

2

注意事项

PLpgSQL语言有许多表达方式:


请注意,我已经保留了原始HTML标签。
 Y := f(X);
EXECUTE子句仅用于"动态执行"(性能较差)。
 EXECUTE 'f(X)' INTO Y;     

使用Y := f(X);SELECT执行静态声明。
 SELECT f(X) INTO Y;

当需要丢弃结果或处理空返回值时,请使用PERFORM语句:

 PERFORM f(X);     

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');

1
假设大多数SQL查询都是系统的一部分,因此通常情况下您会使用后端代码形成查询,然后执行它。
因此,如果您的情况是这样,您可以在执行之前使用子查询或公共表达式将其放入后端代码中的查询字符串中。
除了没有任何后端应用程序之外,我很难想出您想要的解决方案适用的情况,而我的解决方案则不适用。

1

我不确定它是否适合您,但PostgreSQL有EXECUTE语句。


在执行 EXECUTE 之前,必须使用 PREPARE 声明语句,是吗? - minhee
1
不可以将字符串作为另一个语句的一部分执行,但是可以直接执行字符串。 - user330315
4
Grzegorz提到的是PostgreSQL自带的plpgsql编程语言中的EXECUTE命令,这是一种"完整的"编程语言,可用于编写函数、循环和条件等。混淆的源头在于,PostgreSQL中还有一个"纯SQL"的EXECUTE语句,其作用完全不同--它运行一个PREPARE语句。 - j_random_hacker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接