我有一个使用动态sql语句的postgresql函数。我有一个配置表,我想从中获取存储所有where子句条件的列。但是这样做的时候,我的错误越来越小。 SQL错误[42804]:错误:WHERE的参数必须为布尔型,而不是字符变化。我尝试了多个选项,但它一次又一次引发相同的错误。
CREATE OR REPLACE FUNCTION ech_test.usr_select_tab(p_tabname text)
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
declare
r record;
l_fields text;
begin
for r in
EXECUTE
'SELECT field1, field2'
|| ' FROM '
|| p_tabname::regclass
|| ' WHERE '
|| '( select where_clause from table2 where rule_id is not null)'
loop
return next r;
end loop;
return;
end;
$function$
;
它将大声返回table2中的where_clause字段,将其应用于主查询并返回结果行。
答案 0 :(得分:1)
如果要将table2
中的文本连接为WHERE
子句,则必须在构建查询时执行此操作,而不是在查询本身中执行。
'SELECT field1, field2'
|| ' FROM '
|| p_tabname::regclass
|| ' WHERE '
|| ( select where_clause from table2 where rule_id is not null)
也许您也想更改该子查询。您必须确保只返回了一行(和一列)。否则,您会收到一个错误消息,即不允许在此处显示多行;如果没有返回任何行,则将整个字符串为空。
答案 1 :(得分:0)
也许您只想检查WHERE
子句中是否存在匹配记录:
EXECUTE
'SELECT field1, field2'
|| ' FROM '
|| p_tabname::regclass
|| ' WHERE EXISTS '
|| '( select 1 from table2 where rule_id is not null)'
如果这不能满足您的需求,那么您可能不得不处理子查询返回多个记录的情况。另外,子查询正在选择一个列值,该值不一定是布尔值。
答案 2 :(得分:0)
您需要首先检索要使用的条件,将它们存储在变量中,然后将该变量连接到动态SQL中。
请注意,您的查询可能会返回多个行。在这种情况下,SELECT将在函数内部失败(或仅使用返回的“第一个”,具体取决于您的Postgres配置和版本)。
问题是:如果table2
上的查询返回多行,您要怎么做?在下面的代码示例中,我添加了第二个版本,该版本将所有条件与AND
结合在一起-但这只是一个猜测。您必须对其进行调整以满足您的要求。
也不需要使用for
循环。
因此您的函数应如下所示:
CREATE OR REPLACE FUNCTION ech_test.usr_select_tab(p_tabname text)
RETURNS SETOF record
LANGUAGE plpgsql
AS
$function$
declare
l_condition text;
l_sql text;
begin
-- !!!! this will fail if the query returns multiple rows !!!!
select where_clause
into l_condition
from table2 where rule_id is not null;
-- if you want to combine the conditions from table2 then use this:
select string_agg(where_clause, ' AND ')
into l_condition
from table2 where rule_id is not null;
-- build the complete SELECT query
l_sql := format('SELECT field1, field2 FROM %I WHERE %s', p_tabname, l_condition);
-- and return the result of running that query
return query execute l_sql;
end;
$function$
;