为啥匿名块的最后一部分需要 BEGIN END(执行部分)?

Posted

技术标签:

【中文标题】为啥匿名块的最后一部分需要 BEGIN END(执行部分)?【英文标题】:Why do we need BEGIN END (execution section) in last portion for an Anonymus block?为什么匿名块的最后一部分需要 BEGIN END(执行部分)? 【发布时间】:2021-09-01 06:55:05 【问题描述】:

当我尝试运行这段代码时

DECLARE
TYPE type_a IS
    TABLE OF NUMBER INDEX BY PLS_INTEGER;
output NUMBER := 1;

FUNCTION fun_2 RETURN type_a IS
    dum type_a;
BEGIN
    SELECT
        employee_id
    BULK COLLECT
    INTO dum
    FROM
        employees;

    RETURN dum;
END fun_2;

PROCEDURE proc_1 AS
BEGIN
    NULL;
END;

我遇到以下错误:

错误报告 - ORA-06550:第 22 行,第 8 列:PLS-00103:遇到 预期以下之一时的符号“文件结尾”:

开始函数pragma过程 06550. 00000 - “第 %s 行,第 %s 列:\n%s” *原因:通常是 PL/SQL 编译错误。 *行动:

但是当我最后添加 BEGIN END 时它工作正常

    DECLARE
    TYPE type_a IS
        TABLE OF NUMBER INDEX BY PLS_INTEGER;
    output NUMBER := 1;

    FUNCTION fun_2 RETURN type_a IS
        dum type_a;
    BEGIN
        SELECT
            employee_id
        BULK COLLECT
        INTO dum
        FROM
            employees;

        RETURN dum;
    END fun_2;

    PROCEDURE proc_1 AS
    BEGIN
        NULL;
    END;

BEGIN
    null ;
END;

我得到了答案,但这是为什么呢?我的意思是代码是如何执行的,为什么需要它?

【问题讨论】:

你想完成什么?您正在声明一个匿名 PL/SQL 块本地的函数和过程,因此一旦块完成,它们就会消失。由于您没有调用它们,因此声明它们毫无意义。我的猜测是你想创建一个存储过程和一个存储函数(可以从其他块调用的持久对象)或一个包含过程和函数的包(这也将它们保存在数据库中)。 @Justin Cave 我不想要存储过程/函数只是我需要知道为什么错误发生在第一个代码而不是第二个代码中。这不是一个真实的场景,也不是我得到的任何任务,我只是想解决面试问题。我只想知道这两个代码是如何工作的。 :) 匿名块需要一个可执行部分。否则,它只是声明,并且为没有要执行的临时块声明是没有意义的。除了“PL/SQL 不允许只声明局部变量和局部对象但没有可执行部分的匿名块,因为这不是明智之举”跨度> @ Justin Cave "一个匿名块需要一个可执行部分" 现在我明白我为什么需要它了...... :) 【参考方案1】:

PL/SQL 块的结构为DECLARE ... BEGIN ... END;。如果要声明任何变量等,DECLARE 是可选的,但 BEGIN ... END; 是必需的。

如果我们从一个简单的块开始并构建:

BEGIN
  NULL;
END;
/

是最简单的 PL/SQL 语句。然后声明一个类型:

DECLARE
  TYPE type_a IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
BEGIN
  NULL;
END;
/

还有一个变量:

DECLARE
  TYPE type_a IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  output NUMBER := 1;
BEGIN
  NULL;
END;
/

那你DECLARE一个函数;这包括它自己的 PL/SQL BEGIN ... END; 块,该块将嵌套在匿名外部块的 DECLARE 部分中:

DECLARE
  TYPE type_a IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  output NUMBER := 1;

  FUNCTION fun_2 RETURN type_a IS
    dum type_a;
  BEGIN
    SELECT employee_id
    BULK COLLECT INTO dum
    FROM employees;

    RETURN dum;
  END fun_2;
BEGIN
  NULL;
END;
/

然后你声明一个过程;这再次包括它自己的 PL/SQL BEGIN ... END; 块,该块将嵌套在函数之后的匿名外部块的 DECLARE 部分中:

DECLARE
  TYPE type_a IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  output NUMBER := 1;

  FUNCTION fun_2 RETURN type_a IS
    dum type_a;
  BEGIN
    SELECT employee_id
    BULK COLLECT INTO dum
    FROM employees;

    RETURN dum;
  END fun_2;

  PROCEDURE proc_1 AS
  BEGIN
    NULL;
  END proc_1;
BEGIN
  NULL;
END;
/

回到你的问题:

为什么需要它?

因为,否则您有两个 BEGIN ... END; 块用于嵌套在从第一行开始的 DECLARE 部分中的函数和过程,但没有与第一行上的 DECLARE 匹配的 BEGIN ... END;

使用一致的缩进有助于发现这一点。

【讨论】:

@MTO 我太垃圾了 :) 我从没想过匿名块的“BEGIN END”。但你明白我想问什么,谢谢兄弟

以上是关于为啥匿名块的最后一部分需要 BEGIN END(执行部分)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥为 BitmapImage 对象设置 URISource 需要 Begin 和 End init?

正则表达式 - 匹配 BEGIN 和 END 之间的所有内容

为啥“transform(s.begin(),s.end(),s.begin(),tolower)”编译不成功?

为啥 std::basic_string::substr 不遵循 [begin, end) 约定?

Oracle APEX 应用程序包中匿名块的执行点

STM32CubeMx:如何添加自己的“USER CODE BEGIN / END”部分?