我可以在 PL/SQL 块中使用 REGEXP_LIKE 作为 IF 的条件吗

Posted

技术标签:

【中文标题】我可以在 PL/SQL 块中使用 REGEXP_LIKE 作为 IF 的条件吗【英文标题】:Can i use REGEXP_LIKE as a condition with IF in a PL/SQL block 【发布时间】:2016-11-11 11:59:42 【问题描述】:

我正在尝试创建一个函数,旨在遍历组织单元树,根据它们在树结构中的级别和它们出现在我们的 Intranet 页面上的天气过滤掉一些组织单元。该函数的输入是起始单元的 ORG_UNIT_ID,一个显示我们是否应该关心 Intranet 标志的标志和一个逗号分隔的级别列表。例如“2,3”。我正在尝试将 REGEXP_LIKE 与循环内的 ELSEIF 结合使用以向上运行树,直到遇到第一个符合条件的父单元。

T_STOP 是循环的控制变量。 R_ORG_UNIT_OVER 用于查询上述单元的元数据。在循环第一次传递期间,这将是作为输入传递给函数的单元之上的单元。

光标定义:

CURSOR C_ORG_UNIT_OVER(V_ORG_UNIT_ID ORG_UNIT.ORG_UNIT_ID%TYPE) IS
  SELECT  ORUI.ORG_UNIT_ID
  ,       ORUI.ORG_LEVEL
  ,       ORUI.SHOW_ON_INTRANET
FROM    ORG_UNIT ORUI
JOIN    ORG_UNIT_PARENT OUPA ON ORUI.ORG_UNIT_ID=OUPA.ORG_UNIT_ID_PARENT
WHERE   OUPA.ORG_UNIT_ID = V_ORG_UNIT_ID;

循环中失败的代码段:

IF R_ORG_UNIT_OVER.SHOW_ON_INTRANET = 'N' THEN
  T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSEIF REGEXP_LIKE (P_SKIP_LEVEL, '(^|,)' || R_ORG_UNIT_OVER.ORG_LEVEL || '($|,)') THEN
  T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSE
  T_STOP := 'Y';
END IF;

但是,此代码总是在 REGEXP_LIKE 符号上引发 PLS-00103 错误。当 REGEXP_LIKE 用作 PL/SQL IF/ELSEIF 块中的条件而不是常规查询时,是否存在某种限制或替代方式?

【问题讨论】:

这看起来有效。您得到的完整错误堆栈是什么,其中的行号与您显示的内容有何关系?您是否调试过R_ORG_UNIT_OVER.ORG_LEVEL 出错时的实际值?您使用的是哪个版本的 Oracle?一些上下文也可能有用 - 实际问题可能在前面。 我尝试将 REGEXP_LIKE 替换为更基本的 = 检查游标变量。它工作得很好,但每当我用 REGEXP_LIKE 替换它时,我都会得到显示的错误。我可以附上完整的错误日志,但鉴于这是来自更大用例的一个小例子,它可能没有多大意义。 好的,但这适用于最近的版本;可能在 9i 中没有(不记得当它被添加到 PL/SQL 时),所以你使用的是旧版本吗? 所以我可能把她搞砸了。我将修改 IF 语句以更准确地反映我的代码。每个部分都单独工作,但作为 IF-ELSEIF-ELSE 语句的一部分,它会失败。 是的,如果您显示实际产生错误的代码 *8-) 【参考方案1】:

PL/SQL uses ELSIF, not ELSEIF。通过您的编辑,您的代码确实会出现您描述的错误;有了这个它不会:

IF R_ORG_UNIT_OVER.SHOW_ON_INTRANET = 'N' THEN
  T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSIF REGEXP_LIKE (P_SKIP_LEVEL, '(^|,)' || R_ORG_UNIT_OVER.ORG_LEVEL || '($|,)') THEN
  T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSE
  T_STOP := 'Y';
END IF;

【讨论】:

谢谢。我整天盯着这个docs.oracle.com/cloud/latest/db112/LNPLS/…,还是没注意到:(【参考方案2】:

是的,你可以。

declare 
    testvar varchar2(20) := 'Kittens';
begin
    if regexp_like(testvar, '^K') then
        dbms_output.put_line(testvar || ' matches ''^K''');
    end if;
end;

Kittens matches '^K'

PL/SQL procedure successfully completed.

包括一些测试数据,我会尝试看看有什么没有按预期工作。例如,

declare 
    p_skip_level number := 2;
    org_level number := 3;
begin
    if regexp_like (p_skip_level, '(^|,)' || org_level || '($|,)')
    then
        dbms_output.put_line('Matched');
    else
        dbms_output.put_line('Not matched');
    end if;
end;

【讨论】:

以上是关于我可以在 PL/SQL 块中使用 REGEXP_LIKE 作为 IF 的条件吗的主要内容,如果未能解决你的问题,请参考以下文章

我们可以在一个 PL/SQL 块中使用多个函数吗

是否可以在 PL/SQL 开发人员测试窗口的“声明”块中声明子过程?

您可以将 CREATE TABLE 语句放在 PL/SQL 块中吗?

在 PL\SQL 块中使用 EXECUTE IMMEDIATE

在 JDBC PL/SQL 块中多次使用命名参数时出错

如何处理 pl/sql 块中的编译时异常?