大型数据库-2过程与函数_第1页
大型数据库-2过程与函数_第2页
大型数据库-2过程与函数_第3页
大型数据库-2过程与函数_第4页
大型数据库-2过程与函数_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

过程与函数块不能在数据库中。不能从其他PL/SQL块中进行调用。过程、函数、包和触发器都是带名块,可以在数据库中,可以在需要的任何地方运行。7.1

使用过程7.1.1创建过程例:--addstud.sqlCreate

or

replace

procedure

addnewstudent(p_

name

students.

_name%type,p_lastname

students.last_name%type,p_major

students.major%type)asbegininsert

into

students(id,

_name,last_name,major,current_credits)name,values

(student_sequence.nextval,p_p_lastname,p_major,0);commit;End

addnewstudent;在创建了这个块以后,

可以从另一个块中调用他,如:Beginaddnewstudent(‘david’,’dinsmore’,’music’);End;首先使用create

or

replace

procedure语句创建过程

addnewstudent。创建过程的时候,他首先被编译,然后以编译过的形式在数据库中。以后可以从其他的PL/SQL块调用这段被编译过的代码。在调用过程的时候可以传递参数一个过程调用本身就是一个PL/SQL语句。该调用不作为表达式的一部分。当调用过程的时候,控制将转给该过程的第一条可执行语句。当过程结束时,控制重新交还给紧挨着该过程调用的下一个语句。过程是一个PL/SQL块,带有部分、执行部分和异常部分,只有执行部分是必须的。]

as

|

is创建过程语法如下:create

or

replace

procedure

过程名[

参数名1 in

|out

|

in

out

类型名,参数名2

过程体创建过程是DDL语句,因此,在语句之后有一条隐含的commit语句。1.参数的模式及约束例:调用addnewstudent过程块--callproc.sqlDeclarev_new name

students.

_name%type:=‘margeret’;v_lastnmae

students.last_name%type:=‘mason’;v_major

students.major%type:=‘history’;Beginaddnewstudent(v_

name,v_lastname,v_major);End;在上面的块中v_

name,v_lastname,v_major

是实参,

p_

name,p_lastname,p_major是形参,调用时,实参的值赋给形参。形参可以有三种模式-in、out、in out。没有指定形参的模式时,形参缺省的模式是in。下例给出了每种模式之间的差异:Create

or

replace

procedure

modetest(p_inparameter innumber,p_outparameterout

number,p_inoutparameter

in

out

number)

isv_loactionvariable

number;Beginv_loactionvariable:=p_inparameter;--合法p_inparameter:=7;--

p_outparameter:=7--合法v_loactionvariable:=p_outparameter;----合法V_locationvariable:=p_inoutparameter;P_inoutparameter:=7;--合法End

modetest;**select into

和fetch

into也可以在into子句中进行赋值,这些变量也遵循同样的规则的例子。例:下面的例子是对modetest的合法调用Declarev_number1

number:=2;v_number2

number:=3;Beginmodetest(12,v_number1,v_number2);End;如果用文字替换v_variable2,就会得到下面Declarev_number1

number;Beginmodetest(12,v_number1,11);End;模式说明in当调用过程时,实参的值被传递给形参。在该过程内

部,形参被认为是只读的,不能被改变。过程结束时,实参的值不会被改变out在调用过程时,实参所拥有的任何值都会被忽略。在过程,形参被认为是只写的,只能进行赋值,不能从中数据。当过程结束时,形参的值被赋给实参。Inout这种模式是in

和out

的组合。在调用过程时,实参的值被赋给形参。在过程,形参可以被读出,也可以被赋值。当过程结束时,形参的值被赋给实参。**如果过程没有参数,在过程说明和调用时都不需要括号了。此规则对函数同样适用。2.

过程主体过程主体是一个拥有

、执行和异常部分的PL/SQL块。部分在is或as和begin之间,执行部分在begin和exception之间,异常部分在exception和end之间。过程的结构是这样的:Create

or

replace

procedure

过程名as/*

部分*/Begin/*执行部分*/Exception/*异常部分*/End

过程名;对形参的约束在调用一个过程中,不仅实参的值被传递给形参,而且对变量的限制也传递进去。因此在过程

中限制char,varchar2参数的长度,number参数的精度和刻度都是

的。如:下面的过程

的:Ceate

or

replace

procedure

parameterlenth(p_parameter1

in

out

varchar2(10),p_parameter2

in

out

number(3,2)

)asBeginp_parameter1:=‘a1bcdefghijklmn’;p_parameter2:=12.3;End

parameterlength;这个过程的正确

应该是Create

or

replace

procedure

parameterlength(p_parameter1

in

out

varchar2,p_parameter2

in

out

number)

asBeginp_parameter1:=‘bcdefghijklmnop’;p_parameter2:=12.3;End

parameterlength;对p_parameter1和p_parameter2的限制是传递给的实参的限制。例:以下代码调用过程parameterlength过程Declarev_variable1

varchar2(40);v_variable2

number(3,4);Beginparameterlength(v_variable1,v_variable2);End

;Declarev_variable1

varchar2(10);v_variable2

number(3,4);Beginparameterlength(v

_variable1,v_variable2);End

;上面的块和前面的块的唯一不同是v_variable1,parameterlength将一个长度为15的字符串赋值给p_parameter1会产生错误。**为避免发生以上的错误,请在创建过程的时候对实际参数的限制要求给予详细的文档说明。文档注释应该包括该过程要用什么样的处理和参数。%type和过程参数:取得对形参唯一限制的方法是用%

type。如果使用了%type对形参进行说明,而基准类型是受限的,则该限制将作用于形参而不是实际参数。如:Create

or

replace

procedure

parameterlength(p_parameter1

in

out

varachr2,p_parameter2

in

out

studets.current_credits%type)

asBeginp_parameter2:=12345;End

parameterlength;那么p_parameter2将被限制为精度为3。这是因为current_credits列的精度。甚至

采用足够精度的实参调用parameterlength时,处理中所采用的也是形参的精度。例:Declarev_variable1

varchar2(1);v_variable2

number;Beginparameterlength(v_variable1,v_variable2);--产生ora-6502错误。End;位置标识法和带名标识法到目前为止,实参都是通过位置和形参相对应的。假设有下面的过程

:Create

or

replace

procedure

callme(p_parametera

varchr2,p_parameterb

number,p_parameterc

boolean,p_parameterd

date)

asBeginnull;End

callme;以及象下面这样的调用块:Declarev_variable1

varchar2(10);v_

variable2

number(7,6);v_variable3

boolean;v_variable4

date;Begincallme(v_variable1,v_variable2,v_variable3,v_variable4);End;实参v_variable1与形参p_parametera对应,v_variable2与p_parameterb对应,v_variable3与p_parameterc对应,v_variable4与p_parameterd对应。这就是所谓的位置标识法。也可以使用带名标识法来调用过程Declarev_variable1

varchar2(10);v_variable2

number(7,6);v_variable3

boolean;v_variable4

date;Begincallme(p_parametera=>v_variable1,p_parameterb=>v_variable2,p_parameterc=>v_variable3,p_parameterd=>v_variable4);End;在带名标识法中形参和实参都被每个参数所包含,这样我们可以重新调整参数的顺序。如果需要的话,下面的块也可以使用相同的参数调用callme。Declarev_variable1

varchar2(10);v_variable2

number(7,6);v_variable3

boolean;v_variable4

date;Begincallme(p_parameterb=>v_variable2,p_parameterc=>v_variable3,p_parameterd=>v_variable4,p_parametera=>v_variable1);End;如果需要的话,在同一个调用中位置标识法和带名标识法可以混合使用。下面的块说明了这种方法。Declarev_variable1

varchar2(10);v_variable2

number(7,6);v_variable3

boolean;v_variable4

date;Begincallme(v_variable1,v_variable2,p_parameterc=>v_variable3,p_parameterd=>v_variable4);End;我通常使用带名标识法,因为更愿意编写简洁的代码。但是如果过程使用太多的参数(>10),则使用带名标识法更好。**使用单个记录取代太多的参数参数缺省值如果一个参数拥有缺省值,则他不必从调用环境中传入数值。如果他被传递进来数值的话,那么他所使用的是实际的值,而不是缺省的值。参数的缺省值通过以下语法说明:Parameter_name

〔mode〕parameter_type[:=|

default]initial_value例:Create

or

replace

procedure

addnewstudent(p_ name

students.

_name%type;p_lastname

students.last_name%type;p_major

students.major%type

default

‘economics’)

asBegininsert

into

students

values

(student_sequence.nextval,p_

name,p_lastname,p_major,0);End

addnewstudent;如果在调用过程中p_major没有找到实参,就用缺省值economics代替可以通过位置标识法做到这点,如:beginaddnewstudent(‘babara’,’blues’);End;或者使用带名标识法:Beginaddnewstudent(p_

name=>’babara’,p_lastname=>’blues’);End;如果使用的是位置标识法,没有相关联实际参数,而使用缺省值的所有参数都必须位于参数表的末尾。例:Create

or

replace

procedure

defaulttest(p_parametera

number

default

10,p_parameterb

varchar2

default

‘abcdef’,p_parameterc

date

default

sysdate)

asBeginDbms_output.put_line(‘a:’||p_parametera||’b:’);End

defaulttest;如果

想要仅p_parameterb使用缺省值,为p_parametera和p_parameterb指定值,则应使用带名标识法:Begindefaulttest(p_parametera=>7,p_parameterc=>’30-dec-95’);End;在使用位置标识法的时候,如果

想要p_parameterb使用缺省值,则p_parameterc也要使用缺省值。例:Begindefaulttest(7);End;7.1.2

调用过程Oracle允许在sql*plus、oracleforms和其它支持oracle的编程环境中调用过程。但是连接oracle的用户必须有对过程的执行权限。Grant

execute

on

procedurename

to

username;过程的执行权限。用于为用户赋予7.1.3

重新编译过程7.2

使用函数创建函数函数十分类似于过程,都可以在块内被或在数据库的。但是过程调用本身是一个语句,函数调用是表达式的一部分,不是语句。例:指定的班级有90%以上是满的返回true,否则返回false。Create

or

replace

function

almostfull(p_department

classes.department%type,p_course

classes.cousr%type)Return

boolean

isV_currentstudents

number;v_maxstudents

number;v_returnvalue

boolean;v_fullpercent

constant

number:=90;Beginselect

current_students,max_studentsinto

v_currentstudents,v_maxstudentsfrom

classeswhere

department=p_departmentand

course=p_course;If

(v_currentstudents/v_maxstudents*100)>v_fullpercent

thenv_returnvalue:=true;elsev_returnvalue:=false;end

if;return

v_returnvalue;End

allmostfull;可以用下面的PL/SQL块调用他Declarecursor

c_classes

isselect

department,course

from

classes;Beginfor

v_classesrecord

in

c_classes

loopifallmostfull(v_classesrecord.department,v_classesrecord.course)

theninsert

into

temp_table (char_col)

values(v_classesrecord.department

||

‘||v_classesrecord.course

||

‘is

almost

full’);end

if;end

loop;End;函数语法Create

or

replace

function

function_name[

(

argument

[in

|

out

|in

out

]

type,…)]return

return_type [is

|

as

]Fuction_body与过程类似,参数是可选的。因此可以不必在函数和函数调用时使用括号,但是,函数的返回类型是必须的。因为函数调用是表达式的一部分。Return语句Return语句用来控制将一个数值返回调用环境。其语法如下:Return

expession;Expession为要返回的值,如果没有相应的类型,那么

expression的取值将被转换为在函数定义的return子句指定的类型。在一个函数中可以有多个return语句,尽管只有一个return语句被执行。函数没有使用return语句结束是错误的。例:Create

or

replace

function

classinfo(p_department

classes.department%type,p_course

classes.course%type)Return

varchar2

isv_currentstudent

number;v_maxstudents

number;v_percentfull

number;Beginselect

current_students,max_studentsinto

v_currentstudents,v_maxstudentsfrom

classeswhere

department=p_departmentand

course=p_course;V_percentfull:=v_currentstudents/v_maxstudents*100;If

v_percentfull=100thenreturn

‘full’;Elsif

v_percentfull>80

thenreturn

‘some

room’;Elsif

v_percentfull>60

thenreturn

‘more

room’;Elsif

v_percentfull>0

thenreturn

‘lots

of

rooms’;Elsereturn

‘empty’;End

if;End

classinfo;Return语句也可以用在过程中,它不需要参数,这将使控制立即传递给调用环境。被为out或inout的形参值被传递给实参,程序从调用过程语句的下一个语句开始执行。函数样式函数与过程共

些相同的特性函数可以通过out参数返回多个数值函数代码拥有

、执行和错误处理部分函数可以接受缺省值函数可以通过位置标识法或带名标识法进行调用如果有多于一个的返回值,那么使用过程,如果仅有一个返回值,那么可以使用函数。尽管函数可以使用out参数返回多个值,但是这种风格不好。在子程序中进行异常处理如果在子程序中发生了错误就要触发一个异常情态(exception).这种异常处理可能是用户定义的或是预定义的。如果过程对于此错误没有异常处理,那么控制

会立即从该过程传递给调用环境,这遵循异常处理传

递规则。但是,在这种情况下,out

和in

out的形参没

有传递给实参。实参将拥有其在调用该过程以前的值。例:Create

or

replace

procedure

raiseerror(p_raise

in

boolean:=true;p_parametera

out

number)

asBeginp_parametera:=7;if

p_raise

thenraise

dup_val_on_index;Elsereturn;End

if;Endraiseerror;如果 从下面的块中调用raiseerrorDeclarev_tempvarnumber:=1;Begindbms_output.put_line(‘initial

value:’||

v_tempvar);raiseerror(false,v_tempvar);Dbms_output.put_line(‘value

after

successful

call:’||

v_tempvar);V_tempvar:=2;Dbms_output.put_line(‘value

before

2nd

call:’||

v_tempvar);Raiseerror(true,v_tempvar);Exceptionwhen

others

thendbms_output.put_line(‘value

afterunsuccessfulecall||v_tempvar);End;在对raiseerror的第一次调用以前,v_tempvar取值为1,第一次调用成功,v_tempvar被赋值7。然后在第二次对raiseerror调用前v_tampvar被赋值为2,第二次调用没有成功,v_tempvar

的值仍然为2。删除过程和函数删除过程和函数意味着过程和函数从数据字典中删除。删除过程的语法如下:Drop

procedure

过程名删除函数的语法如下:Drop

function

函数名例:drop

procedure

addnewstudentsDrop是一个DDL语句,因此在执行该语句的前后都会隐含地执行commit命令。7.3

子程序位置部分子程序可以被

在数据字典中,也可以在块的进行定义,此时该子程序被称作本地子程序。7.3.1内置子程序当通过create

or

replace

命令创建的子程序被

在数据库中,该子程序是以编译的形式进行 的,这就是p_code。P_code对程序的所有 都进行求值,这样,子程序就被转换为被PL/SQL引擎很容易阅读的形式。User_object视图包括了所有对象的信息,其中也包括内置子程序的信息。该信息包括对象创建的时间和最后修改的时间、对象的类型(表、序列、函数等)、以及对象的有效性。User_source视图包含了对象的源代码。

User_errors视图包含了编译器错误的信息。无效的子程序仍然

在数据库中。但是,在消除错误以前,它是不能被执行的。部分

的本地7.3.2本地子程序下面的例子说明了在PL/SQL块的子程序Declarecursor

c_allstudent

isselect

_name,last_name

from

students;v_formattedname

varchar2(50);function

fornatname(p_ name

in

varchar2

,p_lastnamein

varchar2)Return

varchar2

isBeginreturn

p_ _name

||

||

p_lastname;End

formatname;Beginfor

v_studentrecord

in

c_allstudents

loopv_formattedname:=formatname(v_studentrecord.

_name,v_studentrecord.last_name);insert

into

temp_table(char_col)values

(v_formattedname);end

loop;commit;End;Formatname仅在所 的块内可见。他的作用域为从的位置开始到块的结束。其他的块不能调用formatname,因为他对于其他块是不可见的。所有本地子程序都在

部分的尾部进行

。如果将formatname移到c_allstudent

的前面,将得到编译错误。Declarefunction

fornatname(p_ name

in

varchar2

,p_lastname

in

varchar2)Return

varchar2

isBeginreturn

p_ _name

||

||

p_lastname;End

formatname;cursor

c_allstudent

isselect

_name,last_name

from

students;v_formattedname

varchar2(50);Beginfor

v_studentrecord

in

c_allstudents

loopv_formattedname:=formatname(v_studentrecord.

_name,v_studentrecord.last_name);insert

into

temp_table(char_col)values

(v_formattedname);end

loop;commit;End;1.向前因为本地子程序的名字是一个标识符,所以应该在被之前进行

,但是对于相互交叉

的子程序,会出现问题。如:Declarev_tempval

binary_integer

:=5;procedure

a(p_counter

inout

binary_integer)

isbeginif

p_counter>0

thenb(p_counter);p_counter:=p_cpunter-1;end

if;end

a;procedure

b(p_counter

in

out

binary_integer)

isbeginp_counter:=p_counter-1;a(p_counter);end

b;Beginb(v_tempval);End;这个例子是不可能通过编译的。为了解决这个问题,可以使用向前

。这只是一个过程名和形参,这样在程序过程了。中就可以使用相互的交叉例:Declarev_tempval

binary_integer

:=5;procedure

b(p_counter

in

out

binary_integer);procedure

a(p_counter

in

out

binary_integer)isbeginif

p_counter>0

thenb(p_counter);p_counter:=p_counter-1;end

if;end

a;procedure

b(p_counter

in

out

binary_integer)isbeginp_counter:=p_counter-1;a(p_counter);end

b;Beginb(v_tempval);End;内置子程序和本地子程序内置子程序和本地子程序的行为不同,拥有不同的属性。我通常喜欢用内置子程序,他可以在数据库中,被多个块调用。子程序的大小和复杂性方面的收益也是应该考虑因素。我唯一要在某个块内将其为本地子程序的过程和函数是那些比较短小的,并且是那些从程序的特定部分才能进行调用的子程序。(即只能在所在块才能调用的子程序)。内置子程序和本地子程序的差异内置子程序本地子程序在数据库中以被编译的p_code形式 ,在调用该子程序时,不需要再编译作为包含他的块的一部分进行编译,如果该块被多次调用,则该子程序被多次编译。可以从有对该子程序拥有

execute权限的用户所提交的任何块中进行调用。仅能从包含该子程序的块中进行调用。通过将子程序和调用块分离开来,使得调用块更短小和易于理解。如果需要的话,调用块和子程序可以分别进行。该子程序和调用块是同一个,易引起误解,如果要对调用块进行修改,该子程序要重新进行编译。被编译的p_code可以通过使用DBMS_SHARED_POOL.KEEP包装过程嵌入到共享池中。这可以提高性能。本地子程序自己不能嵌插到共享池中。2.子程序依赖性在编译过程或函数的时候,他 的所有oracle对象都被记录到数据字典中。该过程是依赖于这些对象。如果在其中一个对象上执行了DDL操作,内置子程序也可能成为无效的。例:almostfull函数对表classes进行查询。allmostfull仅依赖于一个对象classes。现在假设

创建了一个调用allmostfull并将结果

到temp_table中的过程。Create

or

replace

procedure

recordfullclasses

ascursor

c_classes

isselect

department,coursefrom

classes;Beginfor

v_classesrecord

in

c_classes

loopif

almostfull(v_classesrecord.department,v_classesrecord.course)

theninsert

intotemp_table(char_col)

valuesv_classesrecord.department ||

||v_classesrecord.course

||‘is

almost

full’);end

if;end

loop;End

recordfullclasses;Recordfullclasses直接依赖于almostfull和temp_table,因此recordfullclasses间接依赖于classes。如果在classes表上执行DDL操作,则依赖于classes的所有对象都将是无效的。例

通过修改下面的列将使recordfullclasses和almostfull无效。Alter

table

classes add(student_rating

number(2));对于函数请使用:Alter

function

function_name

compile权限和内置子程序Execute权限要使用内置子程序和包,应有execute的权限。Create

or

replace

procedure

recordfullclasses

ascursor

c_classesisselect

department,coursefrom

classes;Beginfor

v_classesrecord

in

c_classes

loopif

almostfull(v_classesrecord.department,v_classesrecord.course)

theninsert

into

temp_table(char_col)

valuesv_classesrecord.department ||

||v_classesrecord.course

||

‘is

almost

full’);end

if;end

loop;End

recordfullclasses;假设recordfullclasses所依赖的对象almostfull和表classes以及表temp_table都由用户usera所拥有。

recordfullclasses也是由用户usera所拥有。如果

用以下 令授予用户b对recordfullclasses的execute权限:Grant

execute

on

recordfullclasses

to

userb;那么userb可以通过以下的块来执行recordfullclasses。Beginusera.

Recordfullclasses;End;现在假设useb也有temp_table表,useb调用usera.Recordfullclasses,那么哪一个表会被改变呢?答案是usea中的表。原因如下:子程序在其拥有者权限控制下执行既然userb调用Recordfullclasses,而Recordfullclasses由usera所拥有,这样标识符temp_table应该对属于usera,而不是userb的表进行求值。内置子程序和角色假设usea不拥有Recordfullclasses或temp_table,但是useb拥有他。然后修改了Recordfullclasses,将他显式地索引到usea中的对象。Create

or

replace

procedure

Recordfullclasses

ascursor

c_classses

is

select

department,coursefrom

usea.classes;Beginfor

v_classrecord

in

c_classes

loopif

usera.almostfull(v_classrecord.department,v_classrecord.course)

theninsert

intotemp_table(char_col)

values(v_classrecord.department||

‘||

v_classrecord.course

||‘is

almost

full’);End

if;End

loop;End

Recordfullclasses;为了能使Recordfullclasses正确编译,usera必须将关于classes的select权限和关于almostfull的execute权限赋予userb。而且,这种

必须显式地进行,不能通过角色进行。下面由usea所执行的 将使得useb.Recordfullclasses编译成功。Grant

select

on

classes

to

useb;Grant

execute

on

Recordfullclasses

to

useb;通过间接的

,比如:Create

role

usera_role;Grant

select

on

classes

to

usera_role;Grant

execute

on

Recordfullclasses

to

usera_role;Grant

usera_role

to

userb;将不能工作。所以:子程序在其拥有者的控制下执行,这些权限要显式地授予相应的拥有者,

无法通过角色进行。这条法则也适用于包和触发器。7.4

递归在使用递归的时候要

递归的位置。如果将递归调用放在一个游标的FOR循环中或者是游标的open和close之间,则在每次调用的时候都会打开一个游标,这样的结果可能会造成游标数超过oracle初始化参数open_cursor指定的最大值。例:Create

or

replace

function

rec_test(n

integer)return

integer

isBeginif

n=1

thenreturn

1;elsereturn

n*rec_test(n-1);end

if;End

rec_test;调用函数rec_testDeclareI

integer;BeginI:=rec_test(7);Dbms_output.put_line(I);End;TRIGGERSDatabase

triggers

can

be

used

to

perform

any

of

the

following:Audit

data

modificationLog

events

transparentlyEnforce

complex

business

rulesDerive

column

values

automaticallyImplement

complex

security

authorizationsMaintain

replicate

tablesTRIGGERSYou

can

associate

up

to

12

database

triggers

with

a

given

table.

A

database

trigger

has

three

parts:

atriggering

event,an

optional

triggerconstraint,and

a

triggeraction.When

an

event

occurs,

a

database

trigger

is

fired,and

an

predefinedPL/SQL

block

will

perform

thenecessary

action.TRIGGERSSYNTAX:CREATE

[OR

REPLACE]

TRIGGER

trigger_name{BEFORE|AFTER}

triggering_event

ON

table_name[FOR

EACH

ROW][WHEN

condition]DECLAREDeclaration

statementsBEGINExecutable

statementsEXCEPTIONException-handling

statementsEND;Bordoloi

andBockTRIGGERSThe

trigger_name

references

the

name

of

the

trigger.BEFORE

or

AFTER

specify

when

the

trigger

is

fired

(before

orafter

the

triggering

event).The

triggering_event

references

a

DML

statement

issued

againstthe

table

(e.g.,

INSERT,

DELETE,

UPDATE).The

table_name

is

the

name

of

the

table

associated

with

the

trigger.The

clause,

FOR

EACH

ROW,

specifies

a

trigger

is

a

rowtriggerand

firesonce

for

ea odified

row.A

WHEN

clause

specifies

the

condition

for

a

trigger

to

be

fired.Bear

inmind

that

if

you

drop

a

table,

all

the

associated

triggers

forthe

table

are

dropped

as

well.TYPES

OF

TRIGGERSTriggers

may

be

called

BEFORE

or

AFTER

the

followingevents:INSERT,

UPDATE

and

DELETE.The

before/after

options

can

be

used

to

specify

when

thetrigger

body

should

be

fired

with

respect

to

the

triggeringstatement.

If

the

user

indicates

a

BEFORE

option,

thenOracle

fires

the

trigger

before

executing

the

triggeringstatement.

On

the

other

hand,

if

an

AFTER

is

used,Oracle

fires

the

trigger

after

executing

the

triggeringstatement.TYPES

OF

TRIGGERSA

trigger

may

be

a

ROW

or

STATEMENT

type.

If

thestatement

FOR

EACH

ROW

is

present

in

the

CREATETRIGGER

clause

of

a

trigger,

the

trigger

is

a

row

trigger.A

row

trigger

is

fired

for

each

row

affected

byantriggering

statement.

A

statement

trigger,

however,

is

fired

only

once

for

thetriggering

statement,

regardless

of

the

number

of

rowsaffected

by

the

triggering

statementTYPES

OF

TRIGGERSExample:

statement

triggerCREATE

OR

REPLACE

TRIGGER

mytrig1

BEFORE

DELETE

OR

INSERTOR

UPDATE

ON

employeeBEGINIF

(TO_CHAR(SYSDATE,

'day')

IN

('sat',

'sun'))

OR(TO_CHAR(SYSDATE,'hh:mi')

NOT

BETWEEN

'08:30'

AND

'18:30')RAISE_APPLICATION_ERROR(-20500,

'table

is

secured');THENEND

IF;END;/The

above

example

shows

a

trigger

that

limits

the

DMLactions

to

the

employee

table

to

weekdays

from

8.30am

to6.30pm.

If

a

user

tries

toinsert/update/delete

a

row

in

theEBoMrdPoLloOi

aYnEd

E

table,

a

warning

message

will

be

prompted.BockBordoloi

a

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论