包“set serveroutput on”导致编译错误

Posted

技术标签:

【中文标题】包“set serveroutput on”导致编译错误【英文标题】:Package "set serveroutput on" causing compilation error 【发布时间】:2021-05-12 09:55:36 【问题描述】:

我正在使用我的类包模板将两个过程收集到包中,在粘贴和格式化所有内容后,我遇到了这个错误:

这是我的包裹代码。头和身是分开的。

CREATE OR REPLACE 
PACKAGE PAQEX AS 
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );

END PAQEX;

CREATE OR REPLACE
PACKAGE BODY PAQEX AS

  PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER) AS
  -- 
V_AEROPUERTO NUMBER;
V_TERMINAL NUMBER;
V_ID_AEROPUERTO AEROPUERTO.ID%TYPE;
BEGIN

-----------

SELECT COUNT(*) INTO V_AEROPUERTO FROM AEROPUERTO WHERE NOMBRE = P_NOMBRE AND LUGAR = P_LUGAR;

IF V_AEROPUERTO = 0 THEN
    INSERT INTO AEROPUERTO (NOMBRE, LUGAR) VALUES (P_NOMBRE, P_LUGAR);
    DBMS_OUTPUT.PUT_LINE('INSERTANDO AEROPUERTO');
ELSE
    DBMS_OUTPUT.PUT_LINE('YA EXISTE EL AEROPUERTO');
END IF;

SELECT ID INTO V_ID_AEROPUERTO FROM AEROPUERTO WHERE NOMBRE = P_NOMBRE AND LUGAR = P_LUGAR;

------------

SELECT COUNT(*) INTO V_TERMINAL FROM TERMINAL WHERE NUMERO = P_NUMERO AND ID_AEROPUERTO = V_ID_AEROPUERTO;

IF V_TERMINAL = 0 THEN
    INSERT INTO TERMINAL (NUMERO, ID_AEROPUERTO) VALUES (P_NUMERO, V_ID_AEROPUERTO);
    DBMS_OUTPUT.PUT_LINE('INSERTANDO TERMINAL');
ELSE
    DBMS_OUTPUT.PUT_LINE('YA EXISTE LA TERMINAL');
END IF;
  END EX3;

  PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER ) AS
  
CURSOR CVUELO IS
SELECT CS.NOMBRE AS COMPA,MDEL.NOMBRE AS MODELL,ASA.NOMBRE AS ORIGEN,AL.NOMBRE AS DESTINO
    FROM VUELO VU
    INNER JOIN AVION AVI
    ON VU.ID_AVION = AVI.ID
    INNER JOIN COMPAÑIA CS
    ON AVI.ID_COMPAÑIA = CS.ID
    INNER JOIN MODELO MDEL
    ON AVI.ID_MODELO = MDEL.ID
    INNER JOIN PUERTA PS
    ON VU.id_puerta_salida = PS.ID
    INNER JOIN PUERTA PL
    ON VU.id_puerta_llegada = PL.ID
    INNER JOIN TERMINAL TS
    ON PS.ID_TERMINAL = TS.ID
    INNER JOIN TERMINAL TL
    ON PL.ID_TERMINAL = TL.ID
    INNER JOIN AEROPUERTO ASA
    ON TL.ID_AEROPUERTO = ASA.ID
    INNER JOIN AEROPUERTO AL
    ON TS.ID_AEROPUERTO = AL.ID
    WHERE CPN = CS.NOMBRE;
BEGIN
    NUMER:=0;
    FOR RESULTADO IN CVUELO 
  LOOP
    DBMS_OUTPUT.PUT_LINE(RESULTADO.COMPA || ' | ' || RESULTADO.MODELL ||' | ' ||RESULTADO.ORIGEN||' | ' ||RESULTADO.DESTINO);
    NUMER := NUMER + 1;
  END LOOP;
 DBMS_OUTPUT.PUT_LINE('La compañia ha volado '||numer||' veces');
  END EX2;
END PAQEX;
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);

我想在创建包后尝试包中的每个过程。由于该错误,它们作为独立程序工作,但不在包中。为什么不接受set serveroutput on 命令?

【问题讨论】:

如果您将所有代码作为一个脚本运行,那么您将在每个 END PAQEX 之后的一行中单独缺少一个 / - 用于规范和正文。 SETEXECUTE 是客户端命令,不是包的一部分,因此请与工作表分开运行。您似乎正在使用 SQL Developer;不知道你为什么也用 PL/SQL Developer 标记?) 这个包分为body和head所以我不知道那是不是一个单独的脚本 如果您现在在包正文编辑器中 - 而不是工作表 - 并单击编译按钮以获取该错误,然后删除 SET 和 EXECUTE 命令。 (并且不要添加斜线)。一切都与上下文有关...... @AlexPoole 所以为了查看我的包的每个过程的输出,我必须同时删除执行和服务器输出?对不起,如果我听起来很愚蠢,但它是我们老师解释的一个新概念,我想,按照模板是我必须做的一切...... 【参考方案1】:

有两种方法可以创建这个包;或者来自一个脚本中所有代码的工作表,在这种情况下,它应该看起来像:

CREATE OR REPLACE 
PACKAGE PAQEX AS 
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );

END PAQEX;
/

CREATE OR REPLACE
PACKAGE BODY PAQEX AS

...
END PAQEX;
/

SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);

在每个 PL/SQL 对象(包规范和包主体)之后有一个斜杠。

或者您可以通过“新建包...”菜单命令创建或修改包,并将规范和主体代码放入相关对象中。架构浏览器将在“包”下显示“PAQEX”,如果单击该选项卡,您将看到一个带有包图标和“PAQEX”的选项卡,其中仅包含:

CREATE OR REPLACE 
PACKAGE PAQEX AS 
PROCEDURE EX3 (P_NOMBRE IN VARCHAR2, P_LUGAR IN VARCHAR2, P_NUMERO IN NUMBER);
PROCEDURE EX2(CPN IN VARCHAR2, NUMER OUT NUMBER );

END PAQEX;

以及其下的“PAQEX 主体”;如果您单击它,您将看到另一个选项卡,其中包含包图标和仅包含正文代码的“PAQEX 正文”。但是您似乎已将用于测试它的代码包含在正文中:

PACKAGE BODY PAQEX AS

...
END PAQEX;
SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);

从您包含的错误图像中,您会收到单击编译图标(cogs)时显示的错误。

您需要将测试代码与包代码分开。从包正文选项卡中删除 SETEXECUTE 行,以便:

PACKAGE BODY PAQEX AS

...
END PAQEX;

如果没有其他错误,那么应该可以编译。

然后要测试包,打开一个 SQL 工作表(右键单击连接以在上下文菜单中查看)并只输入这三个语句:

SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);
EXECUTE PAQEX.EX3('ADOLFOS','MADRID',3);

然后单击“作为脚本运行”或按 F5。 (如果您单击“运行为语句”或按 control-enter,则它将仅运行光标当前所在的命令。)

SQL Developer EXECUTE 命令只是一个匿名块的包装器,因此您还可以将这两个调用与:

SET SERVEROUTPUT ON;
BEGIN
  PAQEX.EX2('AIRBUS',0);
  PAQEX.EX3('ADOLFOS','MADRID',3);
END;
/

您还可以在查看包对象编辑器时使用“运行”图标(或按 control-F10)进行测试;它在编译(cogs)图标旁边。这使您可以从包中选择一个过程/函数并设置参数值。 从错误的图像中,您已经从对象列表中打开了包主体,它只显示了您正在单击的 boand 如果您现在在包主体编辑器中 - 而不是工作表 - 并单击编译按钮以获取该错误,然后改为删除 SET 和 EXECUTE 命令。

【讨论】:

谢谢!它只是执行 EX3 程序,但至少是一个很大的进步。我不知道我必须把它放在工作表上 你知道我的其他程序有什么问题吗?它自己工作,但不在这里:( 如果您在工作表中将这三个命令作为脚本 (F5) 而不是作为语句运行 (control-enter),那么它将执行这两个过程;脚本输出窗口将显示这一点,以及两者的输出。 现在我不知道为什么我使用 f5 得到一个未知的命令错误 :( 我也不知道。也许您选择了一个脚本片段,而它只是试图运行该片段?【参考方案2】:

用斜线结束程序:

<snip>
  END EX2;
END PAQEX;
/                                    --> this

SET SERVEROUTPUT ON;
EXECUTE PAQEX.EX2('AIRBUS',0);

【讨论】:

现在尝试,但现在错误声称:遇到符号 / 你不应该。基本上,您的所有 PL/SQL 过程都应该以斜线结尾 - 包主体、包规范、独立存储过程、匿名 PL/SQL 块、触发器……一切。因为,如果您将整个代码作为脚本运行,Oracle 将引发错误。 我使用oracle上的新打包工具创建了包,分为head和body。我读过,如果我使用脚本,这段代码不可能出错,但是我该如何解决呢? 不能评论“新打包工具”,我没用。另一方面,我已经创建包超过 25 年了,所以我想我知道如何正确创建它们。因此,做任何你认为合适的事情。

以上是关于包“set serveroutput on”导致编译错误的主要内容,如果未能解决你的问题,请参考以下文章

set serveroutput on 命令

Oracle中set serveroutput on介绍

运行pl/sql块显示结果,每次都要加set serveroutput on吗?

Mina Codec Filter对应协议实现编解码处理

项目结构包编译为exe!

为啥我用eclipse 编java 引用 import net.sf.jasperreports.engine.*;包出错呢?