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