如何修复SQL错误[42804]:错误:WHERE的参数必须为布尔型,而不是可变字符

时间:2019-04-08 11:08:54

标签: postgresql

我有一个使用动态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字段,将其应用于主查询并返回结果行。

3 个答案:

答案 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$
;