Oracle 常用命令舉例
基本語法
% type用法
%rowtype用法
TYPE用法
游標的使用
for 循環
loop循環
while循環
if / else 的用法
case 的用法
錯誤定義
error的設定
exception用法
存儲過程及函數
procedure 的建立和調用
function的建立和調用
參數的調用(in 模式為按址調用,out / in out模式為按值調用。NOCOPY 強行轉換成按址調用)。
軟件包及封裝
軟件包(PACKAGE)的建立和調用
軟件包的全局結構
封裝函數的純度
查看源代碼及建立用戶、用戶的權限
源代碼的查看
建立用戶及登陸
授予權限和權限收回
依賴
直接依賴
查看依賴
包之間調用
觸發器
建立簡單的觸發器
觸發器分類
稍復雜的觸發器
條件謂詞
觸發器中不可使用Commit
系統觸發器舉例(LOGON)
instead of 觸發器
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
1. % type用法,提取% type所在字段的類型
declare
myid dept.id % type;
myname dept.name % type;
begin
select id,name into myid,myname from dept;
dbms_output.put_line(myid);
dbms_output.put_line(myname);
end;
/
2. %rowtype用法,提取%rowtype所在的字段的類型
declare
type type_dept is table of dept % rowtype
index by binary_integer;
tb type_dept;
begin
tb(1).id:='001';
tb(2).id:='001';
dbms_output.put_line(tb.COUNT);
end;
/
3. TYPE用法,相當於結構體
declare
lv_order_date DAte:=sysdate;
lv_last_txt varchar2(5) default '001';
lv_last varchar2(10) not null:='us';
TYPE type_test is record(
myid dept.id % type,
myname dept.name % type);
rec type_test;
begin
lv_order_date:=sysdate;
dbms_output.put_line(lv_last);
select id,name into rec from dept;
dbms_output.put_line(rec.myid);
dbms_output.put_line(rec.myname);
end;
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
/
4. 游標的使用
declare
g_id char(10):='002';
find_not char(1):='N';
cursor cur is
select * from dept;
TYPE type_dept is record(
cur指向表
myid dept.id % type,
myname dept.name % type,
myaddr dept.addr % type);
rect type_dept;
begin
open cur;
loop
fetch cur into rect;
exit when cur% NOTFOUND;
提取cur指向的記錄到rect結構中
if rect.myid=g_id then
find_not:='Y';
dbms_output.put_line('Find it!!');
dbms_output.put_line('DEPT ID:' || rect.myid);
dbms_output.put_line('NAME:' || rect.myname);
dbms_output.put_line('ADDR:' || rect.myaddr);
end if;
end loop;
close cur;
if find_not='N' then
dbms_output.put_line('no record');
end if;
end;
/
5. for 循環
begin
for i in 1..5 loop
dbms_output.put_line(i);
end loop;
end;
/
6. loop循環
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
declare
v number:=1;
begin
loop
dbms_output.put_line(v);
exit when v>5;
v:=v+1;
end loop;
end;
/
7. while循環
declare
v number:=1;
begin
while v<5 loop
dbms_output.put_line(v);
v:=v+1;
end loop;
end;
/
8. error的設定
declare
v1 number:=90;
begin
if v1=10 then dbms_output.put_line('v1 is 10');
elsif v1=20 then dbms_output.put_line('v2 is 20');
else goto err;
dbms_output.put_line('normal end');
<<err>>
dbms_output.put_line('error found');
end if;
end;
/
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
9. exception用法
declare
ex Exception;
begin
Update dept set name='Edison'
where id='100';
if SQL%NOTFOUND Then
Raise ex;
end if;
Exception
When ex then
dbms_output.put_line('update failed.');
end;
/
declare
type rc_dept is record (
myid dept.id%type,
myname dept.name%type,
myaddr dept.addr%type
);
tb rc_dept;
begin
select id,name,addr into tb from dept where id=:gb_id;
dbms_output.put_line('id:' || tb.myid);
dbms_output.put_line('name:' || tb.myname);
dbms_output.put_line('addr:' || tb.myaddr);
exception
when NO_DATA_FOUND then
dbms_output.put_line('no record is found');
when TOO_MANY_ROWS then
dbms_output.put_line('too many rows are selected');
when OTHERS then
dbms_output.put_line('undefine error');
dbms_output.put_line('error coede: ' || SQLCODE);
dbms_output.put_line('error message:' || SQLERRM);
end;
/
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
declare
type rc_dept is record (
myid dept.id%type,
myname dept.name%type,
myaddr dept.addr%type
);
tb rc_dept;
begin
begin
select id,name,addr into tb from dept where id=:gb_id;
內層錯誤捕捉其始點,在此之前發生的錯誤由外層進行捕捉。
dbms_output.put_line('id:'|| tb.myid);
dbms_output.put_line('name:' || tb.myname);
dbms_output.put_line('addr:'|| tb.myaddr);
exception
when NO_DATA_FOUND then
dbms_output.put_line('no record is found, occur in inner.');
end;
exception
when TOO_MANY_ROWS then
dbms_output.put_line('too many rows are selected, occur in outer.');
內層的錯誤捕捉到后,外層的錯誤就不捕捉了。否則由外層捕獲錯誤。
when OTHERS then
dbms_output.put_line('undefine error');
dbms_output.put_line('error coede: ' || SQLCODE);
dbms_output.put_line('error message:' || SQLERRM);
end;
/
10. if / else 的用法
declare
v1 number:=90;
begin
if v1=10 then dbms_output.put_line('v1 is 10');
elsif v1=20 then dbms_output.put_line('v2 is 20');
else dbms_output.put_line('v2 is others');
end if;
end;
/
11. case 的用法
declare
v number:=10;
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
begin
case :v
when 10 then dbms_output.put_line('v is 10');
when 20 then dbms_output.put_line('v is 20');
else dbms_output.put_line('v is not 10 and 20');
end case;
end;
/
12. procedure 的建立和調用
create or replace procedure test_sp
(test in number, outtest out number)
is
begin
參數的聲明不要對它的大小進行定義。IN表示傳入的參數,不能修改,OUT表示傳出的參數。
if test>10 then
printsomthing ('test is over 10!!');
else
begin
outtest:=test;
printsomthing (outtest);
end;
過程調用過程的參數調用格式注意,不加“:”
end if;
end;
/
create or replace procedure printsomthing
(print in number)
is
begin
dbms_output.put_line(print);
end;
/
create or replace procedure printsomthing
(print in char)
is
begin
dbms_output.put_line(print);
end;
/
exec test_sp(:test,:outtest); 外部執行的時候注意參數調用方式要加“:”
存儲過程可以重載,符合C++的重載規則。
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
13. function的建立和調用
create or replace function test(t in number) return number
is
Function的建立,需要返回值,但不需要說明大小。
begin
if t>10 then
dbms_output.put_line(t);
elsif t<10 then
dbms_output.put_line(t);
end if;
return t;
end;
/
注意:調用的方法,不能以procedure那樣獨立進行調用。函數是表達式的一部分(有返回值)。
exec test(1); 錯誤
exec :tt:=test(2); 正確
Tips:建議使用return模式,而不是使用out模式。
procedure 中也能用return,這里的return只表示當前procedure的中斷。
參數如同procedure一樣,不能修改in的參數
create or replace function test(t in number) return number
is
begin
if t>10 then
t:=t+10;
dbms_output.put_line(t);
elsif t<10 then
dbms_output.put_line(t);
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PLS-00363: 表達式 'T' 不能用作賦值目標
5/3 PL/SQL: Statement ignored
end if;
return t;
end;
/
多路return
create or replace function test(t in number) return number
is
begin
if t<10 then
return 1;
elsif t>=10 then
return 2;
end if;
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
end;
/
function中調用procedure
create or replace function test(t in number) return number
is
begin
printnumber(t);
return t;
end;
/
create or replace procedure printnumber
(print in number)
is
begin
dbms_output.put_line(print);
end;
/
14. 參數的調用(in 模式為按址調用,out / in out模式為按值調用。NOCOPY 強行轉換成按址調用。
create or replace procedure test_nocopy_sp(p_in in number, p_out in out nocopy number)
is
begin
p_out:=5;
if p_in=1 then
raise no_data_found;
強行拋出一個異常,以顯示參數的結果。
end if;
end;
/
create or replace procedure run_nocopy_sp
is
lv_test_num number;
begin
lv_test_num:=1;
test_nocopy_sp(1,lv_test_num);
exception
when others then
因為test_nocopy_sp這個過程的第二個參數是nocopy的,也就是傳址的,所以修改了lv_test_num,為5。
如果test_nocopy_sp這個過程的第二個參數不是nocopy,那么就是傳值,lv_test_num不被修改,仍然為1。
dbms_output.put_line('error happened'|| lv_test_num);
end;
/
error happened 5
error happened 1
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
15. 軟件包(package)的建立(包含了函數的重載)
軟件包聲明
create or replace package test_package
is
procedure test_sp
(test in number, outtest out number);
只聲明過程、函數的原型。
procedure printsomthing
(print in number);
函數printsomething的重載
procedure printsomthing
(print in char);
function test
(t in number) return number;
end;
/
軟件包體的建立
create or replace package body test_package
is
procedure test_sp
無begin
(test in number, outtest out number)
is
begin
if test>10 then
printsomthing ('test is over 10!!');
else
begin
outtest:=test;
printsomthing (test);
end;
end if;
end test_sp;
end 的注意
procedure printsomthing
(print in number)
is
begin
dbms_output.put_line(print);
end printsomthing;
procedure printsomthing
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
(print in char)
is
begin
dbms_output.put_line(print);
end printsomthing;
function test(t in number) return number
is
begin
if t>10 then
dbms_output.put_line(t);
elsif t<10 then
dbms_output.put_line(t);
end if;
return t;
end test;
end;
/
具體寫體的時候和以前一樣寫,只不過不用寫create or replace,在end最后還要緊跟過程或函數名。
執行結果
SQL> var test1 number;
SQL> exec test_package.test_sp(20,:test1);
test is over 10!!
PL/SQL 過程已成功完成。
SQL> exec test_package.test_sp(1,:test1);
1
PL/SQL 過程已成功完成。
SQL> exec :test1:=test_package.test(20);
20
調用方法就是在前面加個包名,其余注意點和過程或函數相同。
調用方法就是在前面加個包名,其余注意點和過程或函數相同。
PL/SQL 過程已成功完成。
SQL> print test1;
TEST1
----------
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
20
16. 軟件包全局結構
create or replace package test_global
is
global_v number(3):=0;
procedure setValue(p1 in number);
包的全局變量
end;
/
create or replace package body test_global
is
procedure setValue(p1 in number)
is
begin
global_v:=p1;
dbms_output.put_line(global_v);
修改全局變量並輸出
end setValue;
end;
/
建立2個會話:
exec test_global.setValue(20);
exec test_global.setValue(10);
2個會話分別維護自己的全局變量。互不影響。
17. 封裝函數的純度
create or replace package test_global
is
global_v number(3):=0;
function setValue(p1 in number) return number;
pragma restrict_references(setValue,WNPS);
end;
/
create or replace package body test_global
指定純度。
WNDS Writes No Database State
函數不休改任何數據庫表
RNDS Reads No Database State
函數不讀取任何表
WNPS Writes No Package State
函數不修改任何封裝變量
RNPS Reads No Package State
函數不讀取任何封裝變量
is
function setValue(p1 in number) return number
is
begin
global_v:=p1;
違反了WNPS的約束。
PACKAGE BODY TEST_GLOBAL 出現錯誤:
LINE/COL ERROR
PLS-00452: 子程序 'SETVALUE' 違反了它的相關注記
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
dbms_output.put_line(global_v);
return global_v;
end setValue;
end;
/
18. 源代碼的查看
SQL> desc user_source
名稱 是否為空? 類型
----------------------------------------- -------- -------------------
NAME VARCHAR2(30)
TYPE VARCHAR2(12)
LINE NUMBER
TEXT VARCHAR2(4000)
存放源代碼的字段
SQL> select text from user_source where name='TEST';
注意:name一定要大寫。
TEXT
--------------------------------------------------------------
function test(t in number) return number
is
begin
if t>10 then
dbms_output.put_line(t);
elsif t<10 then
dbms_output.put_line(t);
end if;
return t;
end;
已選擇10行。
SQL> select rownum,text from user_source where name='TEST';
顯示行號
19. 建立用戶及登陸
SQL> create user MascotZhuang IDENTIFIED BY MascotZhuang;
用戶已創建
密碼
用戶名
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
SQL> grant create session to MascotZhuang; 賦予能夠連上數據庫的權力
授權成功。
如果沒有這一句會發生以下錯誤:
ERROR:
ORA-01045: user MASCOTZHUANG lacks CREATE SESSION privilege; logon denied
C:\>sqlplus "MascotZhuang/MascotZhuang"
連接到:
Oracle9i Enterprise Edition Release 9.0.1.1.1 - Production
With the Partitioning option
JServer Release 9.0.1.1.1 – Production
注意:
如果以 MascotZhuang/MascotZhuang as sysdba
登陸,相當於/ as sysdba登陸。
通過show user可以看到user還是sys,而不是MascotZhuang
SQL>
20. 授權和收回權限
授予全部權限
SQL> grant all on test_package to MascotZhuang;
授權成功。
授予特定權限
SQL> grant execute on test_package to MascotZhuang;
授權成功。
收回權限
SQL> revoke all on test_package from MascotZhuang;
撤銷成功。
創建的用戶使用包
SQL> var test1 number;
SQL> set serveroutput on
SQL> exec :test1:=sys.test_package.test(20);
20
PL/SQL 過程已成功完成。
SQL>
21. 直接依賴性
create or replace procedure test_dependency
(p_print char)
is
begin
printsomething(p_print);
end;
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
/
當創建這個procedure的時候,會發現一下錯誤。
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PLS-00201: 必須說明標識符 'PRINTSOMETHING'
5/3 PL/SQL: Statement ignored
因為這個時候,printsomething這個procedure還沒有創建。換句話說,test_dependency依賴於printsomething。所以在printsomething創建之前,test_dependency是無效的。
SQL> select status from user_objects where object_name='TEST_DEPENDENCY';
STATUS
-------
INVALID
因此,必須創建printsomething這個過程。
create or replace procedure printsomething
(p_print char)
is
begin
dbms_output.put_line(p_print);
end;
/
這時候,test_denpendency的status還是invalid。需要進行重現編譯,才能使得status為valid。
SQL> alter procedure test_dependency compile;
SQL> select status from user_objects where object_name='TEST_DEPENDENCY';
STATUS
-------
VALID
22. 查看依賴性
SQL> select referenced_name,referenced_type from user_dependencies where name='TEST_DEPENDENCY';
REFERENCED_NAME REFERENCED_T
------------------------------ ------------
STANDARD PACKAGE
SYS_STUB_FOR_PURITY_ANALYSIS PACKAGE
PRINTSOMETHING PROCEDURE
依賴系統的PACKAGE
TEST_DEPENDENCY所依賴的procedure
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
SQL> select referenced_name,referenced_type from user_dependencies where name='PRINTSOMETHING';
REFERENCED_NAME REFERENCED_T
------------------------------ ------------
STANDARD PACKAGE
SYS_STUB_FOR_PURITY_ANALYSIS PACKAGE
依賴系統的PACKAGE
DBMS_OUTPUT PACKAGE
23. 包之間的調用
create or replace package test_global
is
global_v number(3):=0;
都有一個包的全局變量
procedure setValue(p1 in number);
procedure print(p1 in number);
end;
/
create or replace package body test_global
is
procedure setValue(p1 in number)
is
begin
global_v:=p1;
dbms_output.put_line('this is test_global,global_v is ' || global_v);
test1_global.setValue(3);
end setValue;
procedure print(p1 in number)
調用test1_global這個包中的setValue這個過程。只需加上這個包名即可。
is
begin
dbms_output.put_line('test_global, global_v is ' || global_v);
end print;
end;
/
create or replace package test1_global
is
global_v number(3):=0;
都有一個包的全局變量
procedure setValue(p1 in number);
procedure print(p1 in number);
end;
/
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
create or replace package body test1_global
is
procedure setValue(p1 in number)
is
begin
global_v:=p1;
dbms_output.put_line('this is test1_global,global_v is ' || global_v);
end setValue;
procedure print(p1 in number)
is
begin
dbms_output.put_line('test1_global, global_v is ' || global_v);
end print;
end;
/
setValue過程對全局變量賦值。但是各自的包調用各自的過程,修改各自的全局變量。
SQL> exec test_global.setValue(200);
this is test_global,global_v is 200
this is test1_global,global_v is 3
PL/SQL 過程已成功完成。
SQL> exec test_global.print(10);
test_global, global_v is 200
PL/SQL 過程已成功完成。
SQL> exec test1_global.print(10);
各自的過程修改的自己的全局變量。
各自的過程修改的自己的全局變量。
test1_global, global_v is 3
PL/SQL 過程已成功完成。
24. 建立觸發器(僅說明觸發器的工作原理)
建立一個簡單的表:
create table table_test_trigger(id char(10));
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
建立簡單的觸發器:
create or replace trigger myTrigger
after insert on table_test_trigger
觸發器觸發的時機,有記錄插入到table_test_trigger后就觸發。
begin
dbms_output.put_line('something is inserted!!');
觸發器體,觸發器處理的東西
end;
/
SQL> insert into table_test_trigger Values('01');
插入一條記錄來觸發觸發器。
something is inserted!!
觸發器被觸發。
已創建 1 行。
25. 觸發器的分類
分為:行級觸發器和語句級觸發器
行級觸發器:對於DML語句影響的每一行都觸發觸發器代碼。只適合於UPDATE和DELETE事件。
語句級觸發器:對該事件觸發一次觸發器。INSERT事件
26. 稍復雜的觸發器
第一個觸發器:
create table table_test_trigger(id char(10),name char(10));
insert into table_test_trigger values('01','a');
insert into table_test_trigger values('02','b');
insert into table_test_trigger values('03','c');
insert into table_test_trigger values('04','d');
insert into table_test_trigger values('05','e');
create or replace trigger myTrigger
after update of name on table_test_trigger
begin
dbms_output.put_line('something is inserted!!');
end;
/
SQL> update table_test_trigger set name='zz' where id='01';
something is inserted!!
這里比24 建立觸發器中多了 of name ,表示只有當UPDATE NAME這個字段后,才觸發觸發器。
觸發了觸發器。
已更新 1 行
SQL> update table_test_trigger set id='99' where name='b';
已更新 1 行。
沒有觸發觸發器。因為沒對name進行update
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
第二個觸發器:
create or replace trigger myTrigger
after update of name on table_test_trigger
for each row
when(OLD.name='a')
begin
dbms_output.put_line('somthing is inserted!');
For each row表示每行都要觸發,但要滿足for each row下面when的條件。OLD.name表示未更新前的name指,相對的有個NEW.name表示更新后的值。
end;
/
SQL> update table_test_trigger set name='zb';
somthing is inserted!
只觸發了一次,因為只有一條記錄滿足條件。
已更新5行。
第三個觸發器:
create or replace trigger myTrigger
after update of name on table_test_trigger
for each row
begin
dbms_output.put_line('somthing is inserted!');
end;
/
SQL> update table_test_trigger set name='zb';
somthing is inserted!
無條件,對於每行都觸發,這里的每行是指外部update語句影響到的每行。
這里是無條件的UPDATE,因此,表中有幾條記錄,就應該觸發幾次。
somthing is inserted!
somthing is inserted!
somthing is inserted!
somthing is inserted!
已更新5行。
27. 條件謂詞
create or replace trigger myTrigger
after update of name on table_test_trigger
for each row
begin
if UPDATING THEN
dbms_output.put_line('UPDATING!');
end if;
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
if DELETING THEN
dbms_output.put_line('DELETING!');
end if;
if INSERTING THEN
dbms_output.put_line('INSERTING!');
end if;
end;
/
SQL> update table_test_trigger set name='zb';
觸發器觸發
UPDATING!
UPDATING!
UPDATING!
UPDATING!
UPDATING!
已更新5行。
create or replace trigger myTrigger
after update of name on table_test_trigger
for each row
begin
if UPDATING('name') THEN
當name字段update的時候才觸發觸發器。
dbms_output.put_line('UPDATING!');
end if;
end;
/
SQL> update table_test_trigger set name='zb';
觸發觸發器
UPDATING!
UPDATING!
UPDATING!
UPDATING!
UPDATING!
已更新5行。
SQL> update table_test_trigger set id='99';
未觸發觸發器
已更新5行。
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
28. Trigger 中不能使用 Commit
create table test(id char(10));
create table test1(id char(10),logdate date);
create or replace trigger myTrigger
after insert on test
begin
insert into test1 values('001',sysdate);
沒有commit的觸發器
end;
/
SQL> insert into test values('001');
已創建 1 行。
SQL> select * from test1;
ID LOGDATE
---------- ----------
001 14-10月-04
SQL> rollback;
回滾后發現,兩個表的操作均被撤銷
回退已完成。
SQL> select * from test1;
未選定行
SQL> select * from test;
未選定行
create or replace trigger myTrigger
after insert on test
begin
insert into test1 values('001',sysdate);
commit;
添加了commit
end;
/
SQL> insert into test values('009');
insert into test values('009')
*
ERROR 位於第 1 行:
ORA-04092: COMMIT 不能在觸發器中
ORA-06512: 在"SCOTT.MYTRIGGER", line 3
ORA-04088: 觸發器 'SCOTT.MYTRIGGER' 執行過程中出錯
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
29. 系統觸發器舉例
create table test1(id char(10),logdate date);
create or replace trigger logon_trg
after logon on schema
Logon是系統觸發器。系統觸發器詳見書本。
begin
insert into test1 values(user,sysdate);
end;
/
再用scott/tiger重新在新連接中登陸,會發現觸發了系統觸發器。注:用sys/sas as dba登陸無效。
SQL> select * from test1;
ID LOGDATE
---------- ----------
SCOTT 14-10月-04
30. instead of 觸發器
create table test1(id char(10),name char(10));
insert into test1 values('01','ab');
create or replace view test_view
建立視圖
as select name from test1;
create or replace trigger test_trigger
instead of update on test_view
用觸發器來代替UPDATE,這就是為什么叫instead of觸發器。
for each row
begin
update test1 set name='zz';
end;
/
SQL> update test_view set name='aa';
已更新 1 行。
SQL> select * from test1;
ID NAME
---------- ----------
01 zz
Oracle9i 開發指南:PL/SQL 程序設計
清華大學出版社 ISBN 7-302-08002-x
Ben 整理 2004 年 秋
MSN: mascotzhuang@hotmail.com
31. 創建主鍵
CREATE TABLE test
( id char(10) CONSTRAINT id_pk PRIMARY KEY
主鍵設置
, name varchar2(20)
);
CREATE TABLE test
( id char(10) CONSTRAINT id_pk NOT NULL
設置不為空的設置
, name varchar2(20)
);
insert into test values('b03011117','zb');
32. 創建外鍵
CREATE TABLE test
( id char(10) CONSTRAINT id_pk PRIMARY KEY
, name varchar2(20)
);
CREATE TABLE test1
( studentID varchar2(20) CONSTRAINT studentID_pk PRIMARY KEY
, id CONSTRAINT fk_id REFERENCES test(id)
設置外鍵,也就是說,這里面的id的值受到test表中id值的限制。
);
insert into test values('b03011117','zb');
insert into test1 values('b03011117','zb');
ERROR 位於第 1 行:
違反了約束條件,出錯。
ORA-02291: 違反完整約束條件 (SCOTT.FK_ID) - 未找到父項關鍵字