1. 程式人生 > >Oracle基礎:4: sql執行錯誤時的控制方式

Oracle基礎:4: sql執行錯誤時的控制方式

在這裡插入圖片描述
多條sql執行時如果在中間的語句出現錯誤,後續會不會直接執行,如何進行設定,以及其他資料庫諸如Mysql是如何對應的,這篇文章將會進行簡單的整理和說明。

環境準備

使用Oracle的精簡版建立docker方式的demo環境,詳細可參看:

多行語句的正常執行

對上篇文章建立的兩個欄位的學生資訊表,正常新增三條資料,詳細如下:

# sqlplus system/[email protected] <<EOF
> desc student
> select * from student;
> insert into student values (1001, 'liumiaocn');
> insert into student values (1002, 'liumiao');
> insert into student values (1003, 'michael');
> commit;
> select * from student;
> EOF

SQL*Plus: Release 11.2.0.2.0 Production on Sun Oct 21 12:08:35 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL>  Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 STUID					   NOT NULL NUMBER(4)
 STUNAME					    VARCHAR2(50)

SQL> 
no rows selected

SQL> 
1 row created.

SQL> 
1 row created.

SQL> 
1 row created.

SQL> 
Commit complete.

SQL> 
     STUID STUNAME
---------- --------------------------------------------------
      1001 liumiaocn
      1002 liumiao
      1003 michael

SQL> Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
#

多行語句中間出錯時的預設動作

問題:
三行insert語句,如果中間的一行出錯,預設的狀況下第三行會不會被插入進去?

我們將第二條insert語句的主鍵故意設定重複,然後進行確認第三條資料是否會進行插入即可。

# sqlplus system/[email protected] <<EOF
desc student
delete from student;
select * from student;
insert into student values (1001, 'liumiaocn');
insert into student values (1001, 'liumiao');
insert into student values (1003, 'michael');
select * from student;
commit;> > > > >       
> EOF

SQL*Plus: Release 11.2.0.2.0 Production on Sun Oct 21 12:15:16 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL>  Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 STUID					   NOT NULL NUMBER(4)
 STUNAME					    VARCHAR2(50)

SQL> 
2 rows deleted.

SQL> 
no rows selected

SQL> 
1 row created.

SQL> insert into student values (1001, 'liumiao')
*
ERROR at line 1:
ORA-00001: unique constraint (SYSTEM.SYS_C007024) violated


SQL> 
1 row created.

SQL> 
     STUID STUNAME
---------- --------------------------------------------------
      1001 liumiaocn
      1003 michael

SQL> SQL> Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
# 

結果非常清晰地表明是會繼續執行的,在oracle中通過什麼來對其進行控制呢?

WHENEVER SQLERROR

答案很簡單,在oracle中通過WHENEVER SQLERROR來進行控制。

WHENEVER SQLERROR {EXIT [SUCCESS | FAILURE | WARNING | n | variable | :BindVariable] [COMMIT | ROLLBACK] | CONTINUE [COMMIT | ROLLBACK | NONE]}

WHENEVER SQLERROR EXIT

新增此行設定,即會在失敗的時候立即推出,接下來我們進行確認:

# sqlplus system/[email protected] <<EOF
WHENEVER SQLERROR EXIT
desc student
delete from student;
select * from student;
insert into student values (1001, 'liumiaocn');
insert into student values (1001, 'liumiao');
insert into student values (1003, 'michael');
select * from student;
commit;> > > > > > > > > 
> EOF

SQL*Plus: Release 11.2.0.2.0 Production on Sun Oct 21 12:27:15 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> SQL>  Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 STUID					   NOT NULL NUMBER(4)
 STUNAME					    VARCHAR2(50)

SQL> 
2 rows deleted.

SQL> 
no rows selected

SQL> 
1 row created.

SQL> insert into student values (1001, 'liumiao')
*
ERROR at line 1:
ORA-00001: unique constraint (SYSTEM.SYS_C007024) violated


Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
# 

WHENEVER SQLERROR CONTINUE

使用CONTINUE則和預設方式下的行為一致,出錯仍然繼續執行

# sqlplus system/[email protected] <<EOF
WHENEVER SQLERROR CONTINUE
desc student
delete from student;
select * from student;
insert into student values (1001, 'liumiaocn');
insert into student values (1001, 'liumiao');
insert into student values (1003, 'michael');
select * from student;
commit;> > > > > > > > > 
> EOF

SQL*Plus: Release 11.2.0.2.0 Production on Sun Oct 21 12:31:54 2018

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production

SQL> SQL>  Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 STUID					   NOT NULL NUMBER(4)
 STUNAME					    VARCHAR2(50)

SQL> 
1 row deleted.

SQL> 
no rows selected

SQL> 
1 row created.

SQL> insert into student values (1001, 'liumiao')
*
ERROR at line 1:
ORA-00001: unique constraint (SYSTEM.SYS_C007024) violated


SQL> 
1 row created.

SQL> 
     STUID STUNAME
---------- --------------------------------------------------
      1001 liumiaocn
      1003 michael

SQL> 
Commit complete.

SQL> Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
# 

Mysql中類似的機制

在2014年7月,mysql中使用source是否提供相關的類似機制的問題中,最終引入了Oracle此項功能在mysql中引入的建議,詳細請參看:

所以目前這只是一個sqlplus端的強化功能,並非標準,不同資料庫需要確認相應的功能是否存在。

總結

Oracle中使用WHENEVER SQLERROR進行出錯控制是否繼續,本文給出的例子非常簡單,詳細功能的使用可根據文中列出的Usage進行自行驗證和探索。

參考內容

https://docs.oracle.com/cd/E25178_01/server.1111/e16638/advisor.htm
https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12052.htm