2

我正在 ORDS 中编写一个 REST 处理程序。URL 端点应该允许使用许多可选参数进行查询。编写 PL/SQL 代码的一种方法是:

DECLARE
  cur SYS_REFCURSOR
BEGIN
  OPEN cur FOR
    SELECT * FROM MYTABLE WHERE
    (:param1 IS NULL OR column1 = :param1) AND
    (:param2 IS NULL OR column2 = :param2);
  :resultSetOut := cur;
END;

我认为性能稍高的另一种方法是构造 SQL 字符串

DECLARE
  cur SYS_REFCURSOR
  sqlString VARCHAR2(200)
BEGIN
  sqlString := 'SELCT * FROM MYTABLE WHERE 1=1';
  IF (:param1 IS NOT NULL) THEN sqlString := sqlString || ' AND COLUMN1=:param1'; END IF;
  IF (:param2 IS NOT NULL) THEN sqlString := sqlString || ' AND COLUMN1=:param2'; END IF;
  OPEN cur FOR sqlString USING :param1, :param2;
  :resultSetOut := cur;
END;

但是,最后的这个字符串构造需要静态绑定到变量,这实际上使得所有变量在 URL 查询中都是必需的而不是可选的。

对于允许动态 WHERE 子句的 PL/SQL 块,是使用此处显示的第一种方法的唯一方法吗?有没有办法构造一个字符串并绑定类似于这里显示的第二种方式?

4

2 回答 2

1

你走在正确的轨道上:

IF (:param1 IS NOT NULL) THEN sqlString := sqlString || ' AND COLUMN1=:param1'; 
Else sqlString := sqlString || ' and (1=1 or :param1 is null) ';
END IF;

现在,无论如何您都需要相同数量的绑定变量,Oracle 优化器将知道 1 始终为 1,因此它不需要考虑其他谓词。

于 2021-10-31T12:20:20.370 回答
0

您可以在没有动态 SQL 的情况下以等效方式执行此操作:

BEGIN
  IF :param1 IS NOT NULL AND :param1 IS NOT NULL THEN
    OPEN :resultSetOut FOR
      SELECT *
      FROM   MYTABLE
      WHERE  COLUMN1=:param1
      AND    COLUMN2=:param2;
  ELSIF :param1 IS NOT NULL THEN
    OPEN :resultSetOut FOR
      SELECT *
      FROM   MYTABLE
      WHERE  COLUMN1=:param1;
  ELSIF :param2 IS NOT NULL THEN
    OPEN :resultSetOut FOR
      SELECT *
      FROM   MYTABLE
      WHERE  COLUMN2=:param2;
  ELSE
    OPEN :resultSetOut FOR
      SELECT *
      FROM   MYTABLE;
  END IF;
END;
于 2021-10-31T13:42:08.360 回答