oracle触发器报错语法,Oracle 触发器
Oracle觸發器是使用者對Oracle數據庫的對象做特定的操作時,觸發的一段PL/SQL程序代碼,叫做觸發器。觸發的事件包括對表的DML操作,用戶的DDL操作以及數據庫事件等。
一、觸發器的作用
Oracle觸發器可以根據不同的數據庫事件進行特定的調用觸發器程序塊,因此,它可以幫助開發者完成一些PL/SQL存儲過程完成不了的問題,比如操作日志的記錄、防止一些無效的操作、校驗數據的正確性、限制一些對數據庫對象的操作、提供數據同步的可行性。但是不推薦在觸發器當中寫業務邏輯程序,因為這樣對后期數據的維護將大大提高成本。
二、觸發器的類型
觸發器按照用戶具體的操作事件的類型,可以分為5種觸發器。大致如下:
1、數據操作(DML)觸發器:此觸發器是定義在Oracle表上的,當對表執行insert、update、delete操作時可以觸發該觸發器。如果按照對表中行級數據進行觸發或語句級觸發,又可以分為行級(row)觸發器,語句級觸發器,按照修改數據的前后觸發觸發器,又可以分為 after 觸發器和before觸發器之分。
2、數據定義操作(DDL)觸發器:當對數據庫對象進行create、alter、drop操作時,觸發觸發器進行一些操作記錄保存、或者限定操作。
3、用戶和系統事件觸發器:該類型的觸發器是作用在Oracle數據庫系統上,當進行數據庫事件時,觸發觸發器,一般用來記錄登錄的相關信息。
4、INSTEAD OF 觸發器:此類型的觸發器是作用在視圖上,當用戶對視圖進行操作時,觸發該觸發器把相關的操作轉換為對表進行操作。
5、復合觸發器:指的是對數據操作(DML)觸發器當中的多種類型觸發器進行復合,比如;一個觸發器當中包含著after(或before)的行級觸發器和after(或before)的語句級觸發器,來完成一些更為復雜的操作。
案例1、創建一個簡單的觸發器來校驗學生基本信息的正確性,代碼如下:create?or?replace?trigger?tr_xsjbxx_insert
before?insert?on?stuinfo
for?each?row
begin
--對性別的數據進行校驗
if?:new.SEX?not?in?('1',?'2')?then
raise_application_error(-20001,?'性別錯誤,請正確選擇。');
end?if;
end;
insert?into?STUINFO
(STUID,
STUNAME,
SEX,
AGE,
CLASSNO,
STUADDRESS,
GRADE,
ENROLDATE,
IDNUMBER)
values
('SC201801006',
'張三豐',
'3',
26,
'C201801',
'福建省廈門市XXX號',
'2018',
to_date('01-09-2018',?'dd-mm-yyyy'),
'3503021992XXXXXXXX');
結果如下:
代碼解析:這是一個DML觸發器,是對學生信息表(stuinfo)學生數據插入(insert)之前做的一個性別的校驗,當性別的值不符合規范的時候報數據錯誤。
三、DML類型觸發器
Oracle DML類型觸發器是Oracle開發過程當中最經常用到,也是最常見的觸發器,主要是對DML操作,如:insert、delete、update操作事件進行觸發。
DML類型觸發器安裝觸發的事件的前后和數據觸發的類型可以分為四類:前置行級觸發器、后置行級觸發器、前置語句級觸發器、后置語句級觸發器。
創建DML類型觸發器的語法結構如下:create?[?or?replace]?trigger?tr_name(觸發器名)
before|after
delete|?insert?|?update?[of?column1,column2...]
[or?delete?|insert|?update?of?colum1,colum2...]
on?table_name(表名)
[for?each?row]
[follows?tr_name1(其它觸發器名)]
[when?條件]
declare
--聲明部分
begin
--觸發器內容部分
end;
語法解析:
1、or replace :存在同名的觸發器就覆蓋保存。
2、trigger:創建觸發器的關鍵詞。
3、before|after表示是選擇的觸發器是數據改變之前觸發、數據改變之后觸發。
4、delete| insert | update:表示觸發器觸發的事件類型是刪除、插入或更新。
5、for each row: 表示行級觸發器、不填就是語句級觸發器
6、follows :表示觸發器的順序是跟在哪個之后。
7、when?表示觸發器語句觸發的條件
行級觸發器
行級觸發器一般用來做數據的校驗或者記錄數據的操作日志,下面是一個行級觸發器的例子:
案例1、利用行級觸發器記錄更新學生信息表時的操作記錄,代碼如下:create?or?replace?trigger?tr_stuinfo_update
before?update?on?stuinfo
for?each?row
begin
--當學生班號發生變化時,
if?:new.CLASSNO?<>?:old.CLASSNO?then
--插入操作日志表
insert?into?oplog
(LOGID,?--日志ID
TABLENAME,?--表名
COLNAME,?--列名
NEWDATA,?--改變后數據
OLDDATA,?--改變前數據
OPDATE,?--操作時間
OPERATOR)?--操作人
values
(pk_oplog_id.nextval,
'stuinfo',
'classno',
:new.classno,
:old.classno,
sysdate,
'jsq');
end?if;
end;
代碼解析:
1、這是一個學生信息表(stuinfo)update的前置行級觸發器,當修改學生的班號時,會把修改的記錄的操作信息記錄在日志表(oplog)中。
2、行級觸發器通過:new和:old來訪問變化之后的數據和變化之前的數據,update類型觸發器,新舊數據都可以訪問,delete類型觸發器,只能訪問:old值,insert類型觸發器只能訪問:new值。
建立好觸發器,我們更改一條數據看下效果,代碼如下:update?stuinfo?t?set?t.classno?=?'C201802'?where?t.stuid?=?'SC201801006';
select?*?from?oplog;
結果如下:
語句級觸發器
語句級觸發器一般是用來做特定限制語句操作的作用,比如在某一段時間內禁止某一部分語句操作,下面是一個語句級觸發器的案例:
案例2、比如今天是12月15號,我就禁止每月的15號禁止操作學生信息表(stuinfo)的插入和刪除或修改操作。代碼如下:create?or?replace?trigger?tr_stuinfo_sql
before?update?or?insert?or?delete?on?stuinfo
begin
--每月15號禁止操作學生信息表
if?to_char(sysdate,'dd')='15'?then
raise_application_error(-20001,'每月15號不能對學生信息表進行正刪改操作!');
end?if;
end;
代碼解析:
1、DML語句觸發器就是行級觸發器省略掉for each row的寫法。
2、raise_application_error是主動給客戶端拋出-20001代碼錯誤的信息。
建立好觸發器,我們更新一條數據看下效果,結果如下:
總結:
同一個對象上可以有多個DML觸發器,但是觸發器觸發的時候有先后順序,比如before型觸發器比after型觸發器先觸發,在此基礎上行級觸發器,比語句級觸發器更早觸發。同類型的觸發器的先后順序就按follows關鍵詞+觸發器名進行排序。
四、DDL類型觸發器
Oracle DDL類型觸發器主要是對于Oracle數據庫的DDL操作觸發的觸發器,主要包括create、drop、alter等DDL事件,經常利用DDL類型觸發器記錄DDL操作記錄或者限定對某個對象進行DDL操作。也可以根據對應DDL操作做對應的操作。
Oracle DDL類型觸發器的語法結構
DDL類型觸發器的編寫語法如下:create?[?or?replace]?trigger?tr_name(觸發器名)
before|after
ddl_event|database_event
on?SCHEMA(數據庫對象)|DATABASE(數據庫)
[follows?tr_name1(其它觸發器名)]
[when?條件]
declare
--聲明部分
begin
--觸發器內容部分
end;
語法解析:
1、or replace :存在同名的觸發器就覆蓋保存。
2、trigger:創建觸發器的關鍵詞。
3、before|after表示是選擇的觸發器是在進行DDL操作之前觸發還是之后觸發。
4、ddl_event:表示的DDL事件,有create(創建)、alter(修改)、drop(刪除)等常用DDL操作。
5、SCHEMA|DATABASE:表示觸發器是作用在數據庫對象上還是數據庫上。
6、follows :表示觸發器的順序是跟在哪個之后。
7、when?表示觸發器觸發的附帶條件,比如時間。
下面通過一個案例來解析Oracle DDL類型觸發器的寫法:
案例1、利用Oracle DDL類型觸發器給學生信息表(stuinfo)做一個禁止刪除、修改表結構的觸發器,代碼如下:create?or?replace?trigger?tr_stuinfo_ddl
before?alter?or?drop??on?schema
begin
--禁止對學生信息表進行刪除和修改操作
if?dictionary_obj_name?=?'STUINFO'?THEN
--修改表結構
if?sysevent?=?'ALTER'?then
--拋出錯誤
raise_application_error(-20001,
'禁止學生信息表stuinfo進行alter操作!');
end?if;
--刪除表結構
if?sysevent?=?'DROP'?then
--拋出錯誤
raise_application_error(-20001,
'禁止學生信息表stuinfo進行drop操作!');
end?if;
END?IF;
end;
執行完案例1觸發器,我們通過修改學生信息表(stuinfo)測試一下觸發器的效果,代碼如下:--修改表結構
alter?table?STUINFO?modify?stuaddress?VARCHAR2(200);
--刪除表結構
drop?table?stuinfo;
結果如下:
案例2、利用DDL類型觸發器的創建一個數據庫級別的觸發器,記錄用戶登錄數據庫的記錄信息。再次我們需要設計一個登錄記錄表,來保存用戶登錄信息,代碼如下:--?Create?table
create?table?LOGIN_LOG
(
logid?????VARCHAR2(20),
loginuser?VARCHAR2(100),
logindate?DATE
)
tablespace?USERS
pctfree?10
initrans?1
maxtrans?255
storage
(
initial?64K
minextents?1
maxextents?unlimited
);
--?Add?comments?to?the?table
comment?on?table?LOGIN_LOG
is?'登錄日志表';
--?Add?comments?to?the?columns
comment?on?column?LOGIN_LOG.logid
is?'日志id';
comment?on?column?LOGIN_LOG.loginuser
is?'登錄用戶名';
comment?on?column?LOGIN_LOG.logindate
is?'登入時間';
建立DDL類型觸發器(數據庫級):create?or?replace?trigger?tr_stuinfo_ddl_login
after??logon--數據庫系統事件
on?database
begin
--插入登錄日志表
insert?into?login_log
(LOGID,?LOGINUSER,?LOGINDATE)
values
(pk_oplog_id.nextval,sys.login_user,?sysdate);
end;
建立好案例2觸發器,我們通過登錄數據庫,然后查看下登錄日志表,查看一下效果,結果如下:
轉載本站內容時,請務必注明來自W3xue,違者必究。
總結
以上是生活随笔為你收集整理的oracle触发器报错语法,Oracle 触发器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gbase oracle mysql_项
- 下一篇: 买基金如何开户