Postgresql 如何使用作为参数传递给plpgsql函数的列名执行查询?

Postgresql 如何使用作为参数传递给plpgsql函数的列名执行查询?,postgresql,parameter-passing,plpgsql,Postgresql,Parameter Passing,Plpgsql,我在PostgreSQL中有一个包含多列的表。我尝试让一个函数返回一个包含几个默认列和一个变量列的表。列名应作为函数参数传递。例如: SELECT * FROM get_gas('temperature'); 这是我现在的代码: CREATE OR REPLACE FUNCTION get_gas(gas text) RETURNS TABLE (id INTEGER, node_id INTEGER, gas_name DOUBLE PRECISION

我在PostgreSQL中有一个包含多列的表。我尝试让一个函数返回一个包含几个默认列和一个变量列的表。列名应作为函数参数传递。例如:

SELECT * FROM get_gas('temperature');
这是我现在的代码:

CREATE OR REPLACE FUNCTION get_gas(gas text) 
RETURNS TABLE (id INTEGER, node_id INTEGER, 
                  gas_name DOUBLE PRECISION, 
                  measurement_timestamp timestamp without time zone )
AS 
$$
BEGIN
  SELECT measurements_lora.id, measurements_lora.node_id, gas, measurements_lora.measurement_timestamp
  AS  measure
  FROM public.measurements_lora;
END
$$ LANGUAGE plpgsql; 
例如,当传递“temperature”作为列名(
gas
)时,我希望从函数调用中获得一个包含这些列的表

id-节点\u id-温度-测量\u时间戳


如何实现这一点?

您可以使用
EXECUTE
语句

CREATE或REPLACE函数get_gas(gas text)返回表(f1整数、f2整数、f3双精度、f4时间戳,不带时区),如下所示
$$
声明
sql_执行文本;
开始
选择“选择测量值”,
测量值\u lora.node\u id,'
||气体| |',
测量值\u lora.measurement\u时间戳作为测量值
来自public.Measures_lora'
进入sql_执行;
返回查询执行sql\u到\u执行;
结束
$$语言plpgsql;
这将使用您的字段和创建一个变量
sql\u来执行<代码>查询执行
将执行已解释的查询


编辑1:查看另一个答案,了解有关安全问题的关注点。

如果您确实需要在PL/pgSQL函数()中使用动态SQL,请务必防范SQL注入。!比如:

CREATE OR REPLACE FUNCTION get_gas(gas text)
  RETURNS TABLE (id integer
               , node_id integer 
               , gas_name double precision 
               , measurement_timestamp timestamp)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY EXECUTE format(
   'SELECT m.id, m.node_id, m.%I, m.measurement_timestamp
    FROM   public.measurements_lora m'
  , gas
   );
END
$func$;
format()
中的格式说明符
%I
在需要时双引号括起标识符

见:


我尝试了此操作,但出现了以下错误:错误:返回“记录”第1行的函数需要列定义列表:从get_gas('temperature')中选择*我通过更改返回表来解决此问题:创建或替换函数get_gas(gas text)RETURNS table(f1整数、f2整数、f3双精度、f4无时区时间戳)正如$$…@WilliamPrigolLopes-仅当您从表中读取时才使用
选择进入
。如果没有必要,则使用经典的赋值语句
:=
。它更快、更可读。在不防御SQL注入的情况下,永远不要将用户输入连接到SQL语句中。这就是创建数据库的方式。我相信hat@ErwinBrandstetter是一种更好(更安全)的方法。看看这个细节,如果您的变量在某种程度上被表单操纵,那么可以避免SQL注入。