我的 PL/SQL 过程异常似乎不起作用

Posted

技术标签:

【中文标题】我的 PL/SQL 过程异常似乎不起作用【英文标题】:My PL/SQL procedure exception doesn't seem to work 【发布时间】:2020-11-09 13:10:05 【问题描述】:

我有一个包含大陆的数据库,我想创建一个向数据库添加新大陆的过程,但有例外。我尝试通过创建一个已经存在的大陆(亚洲)来执行我的包 GEST_GEO 中的过程,并且没有引发我的异常。有谁知道为什么它不起作用? (nom 是名字)

这是我的代码:

CREATE OR REPLACE PACKAGE GEST_GEO AS
Procedure ADDCONTINENT(pnom continent.nom%TYPE, psuperficie continent.superficie%TYPE);
END GEST_GEO;
/

CREATE OR REPLACE PACKAGE BODY GEST_GEO AS

-- ADDCONTINENT

Procedure ADDCONTINENT(pnom CONTINENT.NOM%TYPE, psuperficie CONTINENT.SUPERFICIE%TYPE) IS
BEGIN
    INSERT INTO CONTINENT VALUES (pnom, psuperficie);
COMMIT;
EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.PUT_LINE('The continent already exists');
    WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLCODE || '–' || SQLERRM);

END ADDCONTINENT;
END GEST_GEO;
/


execute GEST_GEO.ADDCONTINENT('Asia',99380);

执行时它只会告诉我PL/SQL procedure successfully completed

谢谢

【问题讨论】:

【参考方案1】:

DUP_VAL_ON_INDEX 假定有一个主键或唯一键,或对该列强制执行的唯一索引。如果没有,Oracle 不知道有任何“重复”的内容,因此它会插入一行。

因此,创建前面提到的东西(键/索引)。


这是一个例子:table first(注意第 2 行的主键约束):

SQL> create table continent
  2    (nom         varchar2(30) constraint pk_cont primary key,
  3     superficie  number
  4    );

Table created.

程序:注意

第 5 行 - 在 INSERT 语句中始终包含目标列名称 异常处理部分:不要输出消息 - 除非您使用的工具支持它,否则任何人都看不到缓冲区的内容。 RAISE 改为错误 不要在过程中提交;让调用者决定是否提交

所以:

SQL> create or replace procedure addcontinent
  2    (pnom continent.nom%type, psuperficie continent.superficie%type)
  3  is
  4  begin
  5    insert into continent (nom, superficie) values (pnom, psuperficie);
  6  exception
  7    when dup_val_on_index then
  8      raise_application_error(-20001, 'The continent already exists');
  9    when others then
 10      raise;
 11  end addcontinent;
 12  /

Procedure created.

测试:

SQL> exec addcontinent('Asia', 99380);

PL/SQL procedure successfully completed.

SQL> exec addcontinent('Asia', 99380);
BEGIN addcontinent('Asia', 99380); END;

*
ERROR at line 1:
ORA-20001: The continent already exists
ORA-06512: at "SCOTT.ADDCONTINENT", line 8
ORA-06512: at line 1


SQL> select * from continent;

NOM                            SUPERFICIE
------------------------------ ----------
Asia                                99380

SQL>

【讨论】:

我明白了!创建密钥是什么意思?还有其他方法,例如编写我自己的异常吗? "创建键是什么意思" - 在您的 CONTINENT 表上创建一个主键。但是,天哪,只有 5 个大洲(如果算上澳大利亚和格陵兰,则有 6 或 7 个)。你真的需要一个程序来做到这一点吗?该程序将被调用多少次,以证明这种努力是合理的?此外, dbms_output.put_line 只是写入缓冲区。由客户端程序来处理和显示该缓冲区。在 sqlplus 中,在调用过程之前设置 SERVEROUTPUT ON。 这是一个练习,这是我的教授问的,所以我真的不知道我是否可以添加主键。这就是为什么我想知道是否有其他解决方案 另一个行动诅咒。加个PK就行了,别问了。也许你的导师想看看你是否把所有东西放在一起来解决问题。当您在现场时,您不会被灌输信息,尤其是设计问题,这将是您的责任。但@EdStevens 是对的,在你完全理解之前不要停止提问 @Belayer - 您提出了一个很好的观点,即在没有具体细节的情况下,教师(希望!)希望了解学生如何解决问题。相反,在实际工作情况下,开发人员/dba 应该识别并实际反对指定如何完成某事的“要求”。规范应指定什么,而不是涉及具体实现的杂草。

以上是关于我的 PL/SQL 过程异常似乎不起作用的主要内容,如果未能解决你的问题,请参考以下文章

过程中的 PL/SQL 游标不起作用

PL/SQL NVL 和 OracleParameter 在 C# 中不起作用

条件 PL SQL 过程不起作用

从存储过程调用时,PL SQL Execute Immediate 不起作用

for循环后的最后一个过程语句在pl sql中不起作用

PL/SQL 语句的 SQL 查询不起作用