Postgresql Postgres介绍如何将查询中的表达式计算为函数中的变量

Postgresql Postgres介绍如何将查询中的表达式计算为函数中的变量,postgresql,dynamic,execute,plpgsql,evaluation,Postgresql,Dynamic,Execute,Plpgsql,Evaluation,我希望能够从表中查询其名称的函数变量的值 编辑以显示查询表而不是从静态值查询: create table __test__ ( _col text ); insert into __test__ (_col) values('_a'); create or replace function __test() returns void language 'plpgsql' as $$ declare _r record; _

我希望能够从表中查询其名称的函数变量的值

编辑以显示查询表而不是从静态值查询:

    create table __test__
(
_col text
);
insert into __test__
(_col)
values('_a');

   create or replace function __test() 
    returns void
    language 'plpgsql' as
    $$
    declare
      _r record;
      _a int;
      _b int;
      _sql text;
    begin

      _a = 1;
      _b = 0;

      for _r in select _col as _nam from __test__ a loop
      -- query returns one row valued "_a"
        _sql = 'select ' || _r._nam ;
        execute _sql into _b;
      end loop;

      raise info 'value of _b %', _b;

    end;
    $$;
select __test()
当函数执行时_b=1。可能吗

同样的错误

ERROR:  column "_a" does not exist
LINE 1: select _a
               ^
QUERY:  select _a
CONTEXT:  PL/pgSQL function "__test" line 15 at EXECUTE statement

让我们试着重新定义这个问题:你所追求的将等同于 函数,它能够执行“任何外部词法变量对其可见”的动态生成的代码段。在您的示例中,变量应该是
\u a
,但从错误消息中可以看出,它不能由动态SQL语句插值。原因是SQL解释器对当前pl/pgsql变量没有可见性,甚至不知道这些变量存在。它们仅限于pl/pgsql

这里需要的是一个上下文感知的动态生成的pl/pgsql语句,但是这种语言没有这个特性。如果没有这个功能,是否能找到一个技巧来达到这个效果是值得怀疑的。尽管它能够很好地与SQL接口,但除此之外,它是一种相当静态的语言


另一方面,这对于pl/perl来说是没有问题的。

让我们试着重新定义这个问题::您所追求的将等同于 函数,它能够执行“任何外部词法变量对其可见”的动态生成的代码段。在您的示例中,变量应该是
\u a
,但从错误消息中可以看出,它不能由动态SQL语句插值。原因是SQL解释器对当前pl/pgsql变量没有可见性,甚至不知道这些变量存在。它们仅限于pl/pgsql

这里需要的是一个上下文感知的动态生成的pl/pgsql语句,但是这种语言没有这个特性。如果没有这个功能,是否能找到一个技巧来达到这个效果是值得怀疑的。尽管它能够很好地与SQL接口,但除此之外,它是一种相当静态的语言


另一方面,这对于pl/perl来说是没有问题的。

您可以创建一个临时表,在其中插入变量名和值,然后对其执行select。吃完就打扫干净。我以前也用过类似的方法。它工作正常。不过它确实有额外的开销

编辑:添加示例

CREATE FUNCTION switch (in_var text) RETURNS text
LANGUAGE PLPGSQL VOLATILE AS $$

declare t_test text;
    switch_vals text[];

BEGIN

   CREATE TEMPORARY TABLE switch_values (var text, value text);

   EXECUTE $e$ INSERT INTO switch_values VALUES 
       ('a', '1'), ('b', '2'), ('c', '3') $e$;

   EXECUTE $e$ SELECT value FROM switch_values WHERE var = $e$ || quote_literal(in_var)
       INTO t_test;

   DROP TABLE switch_values;

   RETURN t_test;

END; $$; 

postgres=# select switch('a');
  switch 
 --------
   1
 (1 row)

您可以创建一个临时表,在其中插入变量名和值,然后对其执行select。吃完就打扫干净。我以前也用过类似的方法。它工作正常。不过它确实有额外的开销

编辑:添加示例

CREATE FUNCTION switch (in_var text) RETURNS text
LANGUAGE PLPGSQL VOLATILE AS $$

declare t_test text;
    switch_vals text[];

BEGIN

   CREATE TEMPORARY TABLE switch_values (var text, value text);

   EXECUTE $e$ INSERT INTO switch_values VALUES 
       ('a', '1'), ('b', '2'), ('c', '3') $e$;

   EXECUTE $e$ SELECT value FROM switch_values WHERE var = $e$ || quote_literal(in_var)
       INTO t_test;

   DROP TABLE switch_values;

   RETURN t_test;

END; $$; 

postgres=# select switch('a');
  switch 
 --------
   1
 (1 row)


似乎有可能。你还没试过吗?我不确定到底是什么问题。当然试过了。我得到了
注意:ErrCode(42703)(列“…var name,在示例中是a”不存在)
如果我从
表达式中的
\u a
周围删除引号,它会为我输出
信息:值的
。@deszo:你说得对。在实际程序中,值来自查询。请看我的代码编辑,它现在查询一个表,并抛出相同的错误。似乎是可能的。你还没试过吗?我不确定到底是什么问题。当然试过了。我得到了
注意:ErrCode(42703)(列“…var name,在示例中是a”不存在)
如果我从
表达式中的
\u a
周围删除引号,它会为我输出
信息:值的
。@deszo:你说得对。在实际程序中,值来自查询。请查看我的代码编辑,它现在查询表并抛出相同的错误。谢谢!对于一个真正的应用程序来说,它的开销有点大。老实说,我也不喜欢它,尽管我过去在非常复杂的领域使用过临时表解决方案。如果我需要做一个真正的应用程序,我会做类似的事情:1)我会创建一个类型来表示我的条件2)我会将存储过程中的条件表示为该类型的元组数组,3)我会使用unest(conditions)c中的select c.value,而不是从temp表中进行选择。然而,这会增加开发人员的开销。否则,这与工作原理完全相同。问题在于,变量的名称在“for_r in select _colas _namfrom _; test _; a loop”查询之后可用,该查询返回plpgsql函数中某处存在的变量名称。我不知道将它放入数组并使用unnest如何“eval()”它的值。不知道查询返回的变量名。在您的示例中,变量名是静态值+作为输入传递的值,与imo不完全相同。在将所有函数变量添加到数组/TENTRABLE中后,您的示例将起作用。关键是您必须在条件和输出的函数中具有某种表示形式。然后,您可以从您的条件中进行选择并生成输出。这就绕过了范围问题,因为实际上您创建了一个查找表(但是一个被序列化为数组而不是存储到临时表中的查找表)。这与我提供的解决方案之间的唯一区别是:1)模式方面,它更复杂,因为您需要自定义类型;2)由于表格式是在函数中以序列化形式定义的,因此不需要实际的表创建/清理开销。谢谢!对于一个真正的应用程序来说,它的开销有点大。老实说,我也不喜欢它,尽管我过去在非常复杂的领域使用过临时表解决方案。如果我需要做一个真正的应用程序,我会做类似的事情:1)我会创建一个类型来表示我的条件2)我会将存储过程中的条件表示为该类型的元组数组,3)我会使用unest(conditions)c中的select c.value,而不是从temp表中进行选择。然而,这会增加开发人员的开销。否则,这与工作原理完全相同