如何在 PL/SQL 的 LIKE 子句中使用变量

Posted

技术标签:

【中文标题】如何在 PL/SQL 的 LIKE 子句中使用变量【英文标题】:How to use a variable in a LIKE clause in PL/SQL 【发布时间】:2020-02-07 12:29:24 【问题描述】:

我是 Oracle 新手,正在学习;我只是想运行这个 T-SQL 查询

DECLARE @SearchObj varchar(100);
SET @SearchObj='%aldbrough%';

SELECT
      obj_id,
      name,
      description
   FROM
      agnis.t_object
   WHERE
      lower(name) = ObjToSearch ;

我正在使用 SQL Developer Oracle 工具,它还有一个“草稿编辑器”来帮助翻译 T-SQL。当我运行该工具时,它给了我这段代码

     DECLARE
   v_SearchObj VARCHAR2(100);

    BEGIN
       v_SearchObj := '%aldbrough%' ;
       SELECT obj_id ,
              NAME ,
              DESCRIPTION 
         FROM agnis.t_object 
        WHERE  LOWER(NAME) = ObjToSearch;

    END;

但是同样的工具给了我这个错误

    Error report -
ORA-06550: line 10, column 26:
PL/SQL: ORA-00904: "OBJTOSEARCH": invalid identifier
ORA-06550: line 6, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.

那么在返回多行的 LIKE 子句中使用变量的正确语法是什么? 我希望我不必像this question 中建议的那样使用游标等简单语句

【问题讨论】:

至于您的另一点,您不必使用显式光标。但是您必须将结果集选择到 something 中。当您的查询返回多行 you should use an array。除非您使用 12c 或更高版本,在这种情况下您可以使用 T-SQL 样式的隐式游标,但仍然比 T-SQL 中的编码更多。 Find out more 感谢 = 而不是 LIKE 等,这是我复制和粘贴的坏习惯 【参考方案1】:

嗯,是的 - 那些“翻译”并不总是做他们应该做的。

你的代码应该是这样的:

where 子句中使用like,而不是= 在 PL/SQL 中,您必须将 select 语句 into 的结果放入某些东西 - 例如,本地声明的变量(如我的示例所示)。

所以:

DECLARE
   v_SearchObj    VARCHAR2 (100) := '%aldbrough%';
   --
   v_obj_id       t_object.obj_id%TYPE;
   v_name         t_object.name%TYPE;
   v_description  t_object.description%TYPE;
BEGIN
   SELECT obj_id, NAME, DESCRIPTION
     INTO v_obj_id, v_name, v_description
     FROM agnis.t_object
    WHERE LOWER (NAME) LIKE v_searchobj;
END;

如果这样的代码返回错误 - too_many_rows(是的,确实如此),那么一种选择是循环通过行并做某事(例如显示这些值):

DECLARE
   v_SearchObj  VARCHAR2 (100) := '%aldbrough%';
BEGIN
   FOR cur_r IN (SELECT obj_id, NAME, DESCRIPTION
                   FROM agnis.t_object
                  WHERE LOWER (NAME) LIKE v_searchobj)
   LOOP
      DBMS_OUTPUT.put_line (
         'Name = ' || cur_r.name || ', description = ' || cur_r.description);
   END LOOP;
END;

【讨论】:

好的,我知道我必须为查询返回的每个数据项声明一个变量,但是是的,在这种情况下,使用您的好代码会给我返回多行错误 完全正确,就像@APC 所说的那样。我添加了更多代码来显示您如何“修复”它,但是 - 最终结果取决于您想要做什么。这只是在支持 DBMS_OUTPUT 的工具(例如 SQLPlus 或 SQL Developer)中显示值。 我现在使用这个代码 DECLARE v_SearchObj VARCHAR2 (100) := '%aldbrough%';类型 v_obj_id 是数字表;类型 v_name 是 VARCHAR 表(200);类型 v_description 是 VARCHAR 表(200); BEGIN SELECT obj_id, NAME, DESCRIPTION BULK COLLECT INTO v_obj_id, v_name, v_description FROM agnis.t_object WHERE LOWER (NAME) LIKE v_searchobj;结尾;但我收到此错误错误报告 - ORA-06550:第 9 行,第 24 列:PLS-00321:表达式“V_OBJ_ID”不适合作为赋值语句的左侧 无法在 cmets 中格式化代码;最好编辑您发布的原始问题。无论如何,您不能将 3 列批量收集到 3 个数组中。创建一个包含所有 3 列的数组。 @brillox 你可以将BULK COLLECT 3 列分成 3 个数组db<>fiddle。您只需要将集合声明为变量并声明这些集合的类型。您可以通过将代码包装在 ` 反引号中来编写代码,但您不能在 cmets 中包含换行符。【参考方案2】:

由于这是标记为 SQL Developer,所以使用绑定变量:

SELECT obj_id,
       name,
       description
FROM   agnis.t_object
WHERE  lower(name) = :ObjToSearch;

SQL 开发人员会弹出一个对话框,您可以在其中设置ObjToSearch 变量的值。

如果你想在代码中指定绑定变量,那么:

VARIABLE objtosearch VARCHAR2(50)

BEGIN
  :objtosearch := '%aldbrough%';
END;
/

SELECT obj_id,
       name,
       description
FROM   agnis.t_object
WHERE  lower(name) = :ObjToSearch;

并使用 F5 将语句作为脚本运行,而不是作为单个语句运行。

【讨论】:

以上是关于如何在 PL/SQL 的 LIKE 子句中使用变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 select 的 where 子句中替换 oracle pl/sql 变量

Oracle PL/SQL:在 SAMPLE 子句中使用变量时出现语法错误

变量作为 Oracle PL/SQL 中 where 子句中的列名

PL/SQL - 如何在 IN 子句中使用数组

如何在使用变量的动态查询中指定 IN 子句?

PL/SQL-REGEXP_LIKE