【问题标题】:Error in plpgsql parameters in WHERE clauseWHERE 子句中的 plpgsql 参数错误
【发布时间】:2022-01-17 11:03:36
【问题描述】:

我创建了一个用于过滤的函数

CREATE OR REPLACE FUNCTION filtersearch(
    val1 text[] DEFAULT NULL::text[],
    val2 text[] DEFAULT NULL::text[],
    val3 text[] DEFAULT NULL::text[],
    val4 boolean DEFAULT NULL::boolean)
    RETURNS SETOF student_table
    LANGUAGE 'plpgsql'

AS $BODY$

DECLARE
   where_val text := '';
   result_text int;
BEGIN

    IF $4 = true THEN
        where_val := 'attendance = true';
        raise notice 'Value: %', where_val;
    END IF;
    
    
RETURN QUERY EXECUTE    
'SELECT * FROM student_table"
    WHERE (LOWER("student_name") = ($1) OR $1 IS NULL)
    AND ((LOWER("subject") = ($2)) OR $2 IS NULL)
    AND ((LOWER("comments") ILIKE $3) 
        OR ($3 IS NULL) 
        )
    '|| where_val ||'' USING where_val;
    --raise notice 'Value: %', result_text;
END 
$BODY$;

我调用它时出错,

错误:操作 ANY/ALL(数组)需要右侧的数组

非常感谢我代码中的任何建议或 cmets

这是我的表格的示例数据

student_name subject professor comments attendance
Amelia Math Digory Kirkle TRUE
Benjamin Science Hari Seldon FALSE
Charlotte English Lee Everett TRUE
Amelia English Lee Everett FALSE

我是这样调用代码的

SELECT filtersearch(
    (array['Amelia, Charlotte']::text[]), 
    (NULL), 
    (NULL), 
    (true)
)

【问题讨论】:

  • 你能用样本数据创建一个 MVE 吗?如果没有您为我们创建student_table,我们将无法调用函数。你怎么称呼这段代码?
  • 我在我的问题中添加了一个示例数据,非常感谢
  • 要比较数组,您需要使用 = any ($1) 但您没有将 3 个参数传递给 execute query - 只有 一个'''attendance = true'
  • @a_horse_with_no_name 我遇到了一个错误 ERROR: op ANY/ALL (array) requires array on the right side 如何解决?
  • 正如我所说:您需要传递 3 个参数(函数的参数),而不仅仅是带有using 子句的一个。

标签: postgresql plpgsql


【解决方案1】:

SQL 字符串 中的$1、$2、$3 占位符引用通过EXECUTE QUERY 命令的USING 子句传递的参数。您只传递了一个参数,即'' 或字符串'attendance = true' - 两者都不能用于IN 条件。

因此,您需要使用 USING 子句传递三个参数,但不是附加到 SQL 查询的字符串。如果您使用的是 ILIKE,则无需在该条件下使用 lower()。您的where_val 字符串也缺少AND(或OR

CREATE OR REPLACE FUNCTION filtersearch(
    val1 text[] DEFAULT NULL::text[],
    val2 text[] DEFAULT NULL::text[],
    val3 text[] DEFAULT NULL::text[],
    val4 boolean DEFAULT NULL::boolean)
    RETURNS SETOF student_table
    LANGUAGE plpgsql

AS $BODY$

DECLARE
   where_val text := '';
BEGIN

  IF $4 = true THEN
    where_val := 'AND attendance = true';
    raise notice 'Value: %', where_val;
  END IF;
    
  RETURN QUERY EXECUTE    
   'SELECT * 
    FROM student_table
      WHERE (LOWER(student_name) = ANY($1) OR $1 IS NULL)
      AND (LOWER(subject") = ANY ($2) OR $2 IS NULL)
      AND (LOWER("comments") ILIKE ANY($3) OR $3 IS NULL)
     '|| where_val
  USING val1, val2, val3; -- do NOT pass where_val here
END 
$BODY$;

您实际上并不需要动态 SQL。您可以应用与布尔参数的前 3 个参数相同的逻辑。

CREATE OR REPLACE FUNCTION filtersearch(
    val1 text[] DEFAULT NULL::text[],
    val2 text[] DEFAULT NULL::text[],
    val3 text[] DEFAULT NULL::text[],
    val4 boolean DEFAULT NULL::boolean)
    RETURNS SETOF student_table
    LANGUAGE plpgsql

AS $BODY$
BEGIN

  RETURN QUERY
    SELECT * 
    FROM student_table
      WHERE (LOWER(student_name) = any(val1) OR val1 IS NULL)
        AND (LOWER(subject) = any(val2) OR val2 IS NULL)
        AND (comments ILIKE ANY(val3) OR val3 IS NULL)
        AND (attendance = val4 or val4 = false or val4 is null);
END 
$BODY$;

您甚至不需要 PL/pgSQL 来完成上述操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2013-02-03
    • 1970-01-01
    相关资源
    最近更新 更多