You are on page 1of 42

WelcomeSanyasiRaju

(//docs.oracle.com/en/)

Home(../../../../)/Database(../../../../en/database/database.html)/OracleDatabaseOnlineDocumentation,10gRelease2(10.2)(../../index.htm)/ApplicationDevelopment(../../nav/portal_4.htm)

DatabaseApplicationDeveloper'sGuideFundamentals
()

()()

Categories
Home(../../index.htm)

Download

9()CodingTriggers
Triggersareproceduresthatarestoredinthedatabaseandareimplicitlyrun,or()()fired,whensomethinghappens.
Traditionally,triggerssupportedtheexecutionofaPL/SQLblockwhenan INSERT, UPDATE,or DELETEoccurredonatableorview.
Triggerssupportsystemandotherdataeventson DATABASEand SCHEMA.OracleDatabasealsosupportstheexecutionofPL/SQL
orJavaprocedures.
ThischapterdiscussesDMLtriggers, INSTEAD OFtriggers,andsystemtriggers(triggerson DATABASEand SCHEMA).Topics
include:

DesigningTriggers
CreatingTriggers
CodingtheTriggerBody
CompilingTriggers
ModifyingTriggers
EnablingandDisablingTriggers
ViewingInformationAboutTriggers
ExamplesofTriggerApplications
RespondingtoSystemEventsthroughTriggers

()
()

DesigningTriggers()
Usethefollowingguidelineswhendesigningyourtriggers:

Usetriggerstoguaranteethatwhenaspecificoperationisperformed,relatedactionsareperformed.
DonotdefinetriggersthatduplicatefeaturesalreadybuiltintoOracleDatabase.Forexample,donotdefinetriggerstorejectbad
dataifyoucandothesamecheckingthroughdeclarativeintegrityconstraints.()()
Limitthesizeoftriggers.Ifthelogicforyourtriggerrequiresmuchmorethan60linesofPL/SQLcode,itisbettertoincludemost
ofthecodeinastoredprocedureandcalltheprocedurefromthetrigger.
Usetriggersonlyforcentralized,globaloperationsthatshouldbefiredforthetriggeringstatement,regardlessofwhichuseror
databaseapplicationissuesthestatement.
Donotcreaterecursivetriggers.Forexample,creatingan AFTER UPDATEstatementtriggeronthe Emp_tabtablethatitself
issuesan UPDATEstatementon Emp_tab,causesthetriggertofirerecursivelyuntilithasrunoutofmemory.
Usetriggerson DATABASEjudiciously.Theyareexecutedforeveryusereverytimetheeventoccursonwhichthetriggeris
created.

()
()

CreatingTriggers()()
Triggersarecreatedusingthe CREATE TRIGGERstatement.Thisstatementcanbeusedwithanyinteractivetool,suchas
SQL*PlusorEnterpriseManager.Whenusinganinteractivetool,asingleslash(/)onthelastlineisnecessarytoactivatethe
CREATE TRIGGERstatement.
()Thefollowingstatementcreatesatriggerforthe Emp_tabtable.

CREATEORREPLACETRIGGERPrint_salary_changes
BEFOREDELETEORINSERTORUPDATEONEmp_tab
FOREACHROW
WHEN(new.Empno>0)
DECLARE
sal_diffnumber
BEGIN
sal_diff:=:new.sal:old.sal
dbms_output.put('Oldsalary:'||:old.sal)
dbms_output.put('Newsalary:'||:new.sal)
dbms_output.put_line('Difference'||sal_diff)
END
/

ThetriggerisfiredwhenDMLoperations( INSERT, UPDATE,and DELETEstatements)areperformedonthetable.Youcanchoose


whatcombinationofoperationsshouldfirethetrigger.
Becausethetriggerusesthe BEFOREkeyword,itcanaccessthenewvaluesbeforetheygointothetable,andcanchangethe
valuesifthereisaneasilycorrectederrorbyassigningto :NEW.column_name.Youmightusethe AFTERkeywordifyouwantthe
triggertoqueryorchangethesametable,becausetriggerscanonlydothataftertheinitialchangesareappliedandthetableis
backinaconsistentstate.
Becausethetriggerusesthe FOREACHROWclause,itmightbeexecutedmultipletimes,suchaswhenupdatingordeleting
multiplerows.Youmightomitthisclauseifyoujustwanttorecordthefactthattheoperationoccurred,butnotexaminethedatafor
eachrow.
Oncethetriggeriscreated,enteringthefollowingSQLstatement:
UPDATEEmp_tabSETsal=sal+500.00WHEREdeptno=10

firesthetriggeronceforeachrowthatisupdated,ineachcaseprintingthenewsalary,oldsalary,andthedifference.
The CREATE(or CREATE OR REPLACE)statementfailsifanyerrorsexistinthePL/SQLblock.

Note:
Thesizeofthetriggercannotbemorethan32K.

Thefollowingsectionsusethisexampletoillustratethewaythatpartsofatriggerarespecified.

SeeAlso:
"ExamplesofTriggerApplications"formorerealisticexamplesof CREATE TRIGGER statements

()
()

TypesofTriggers
AtriggeriseitherastoredPL/SQLblockoraPL/SQL,C,orJavaprocedureassociatedwithatable,view,schema,orthedatabase
itself.OracleDatabaseautomaticallyexecutesatriggerwhenaspecifiedeventtakesplace,whichmaybeintheformofasystem
eventoraDMLstatementbeingissuedagainstthetable.
Triggerscanbe:

DMLtriggersontables.
INSTEAD OFtriggersonviews.

Syst()()emtrig()gerson DATABASEor SCHEMA:With DATABASE,triggersfireforeacheventforalluserswith SCHEMA,triggers


fireforeacheventforthatspecificuser.

SeeAlso:
OracleDatabaseSQLReference(../../server.102/b14200/toc.htm)forinformationontriggercreationsyntax

()

OverviewofSystemEvents
Youcancreatetriggerstobefiredonanyofthefollowing:

DMLstatements( DELETE, INSERT, UPDATE)


DDLstatements( CREATE, ALTER, DROP)
Databaseoperations( SERVERERROR, LOGON, LOGOFF, STARTUP, SHUTDOWN)

()

GettingtheAttributesofSystemEvents
Youcangetcertaineventspecificattributeswhenthetriggerisfired.
Creatingatriggeron DATABASEimpliesthatthetriggeringeventisoutsidethescopeofauser(forexample,database STARTUP
and SHUTDOWN),anditappliestoallusers(forexample,atriggercreatedon LOGONeventbytheDBA).
Creatingatriggeron SCHEMAimpliesthatthetriggeriscreatedinthecurrentuser'sschemaandisfiredonlyforthatuser.
Foreachtrigger,publicationcanbespecifiedonDMLandsystemevents.

SeeAlso:
"RespondingtoSystemEventsthroughTriggers"

()

NamingTriggers()
Triggernamesmustbeuniquewithrespecttoothertriggersinthesameschema.Triggernamesdonotneedtobeuniquewith
respecttootherschemaobjects,suchastables,views,andprocedures.Forexample,atableandatriggercanhavethesame
name(however,toavoidconfusion,thisisnotrecommended).
()

WhenIstheTriggerFired?()
()Atriggerisfiredbasedona()triggeringstatement,whichspecifies:

TheSQLstatementorthesystemevent,databaseevent,orDDLeventthatfiresthetriggerbody.Theoptionsinclude DELETE,
INSERT,and UPDATE.One,two,orallthreeoftheseoptionscanbeincludedinthetriggeringstatementspecification.
Thetable,view, DATABASE,or SCHEMAassociatedwiththetrigger.

Note:
Exactlyonetableorviewcanbespecifiedinthetriggeringstatement.Ifthe INSTEAD OF optionisused,thenthe
triggeringstatementmayonlyspecifyaviewconversely,ifaviewisspecifiedinthetriggeringstatement,thenonlythe
INSTEAD OF optionmaybeused.

Forexample,the PRINT_SALARY_CHANGEStriggerfiresafterany DELETE, INSERT,or UPDATEonthe Emp_tabtable.Anyofthe


followingstatementstriggerthe PRINT_SALARY_CHANGEStriggergiveninthepreviousexample:
DELETEFROMEmp_tab
INSERTINTOEmp_tabVALUES(...)
INSERTINTOEmp_tabSELECT...FROM...
UPDATEEmp_tabSET...
()

DoImportandSQL*LoaderFireTriggers?

INSERTtriggersfireduringSQL*Loaderconventionalloads.(Fordirectloads,triggersaredisabledbeforetheload.)

The IGNOREparameterofthe IMPcommanddetermineswhethertriggersfireduringimportoperations:

If IGNORE= N(default)andthetablealreadyexists,thenimportdoesnotchangethetableandnoexistingtriggersfire.
Ifthetabledoesnotexist,thenimportcreatesandloadsitbeforeanytriggersaredefined,soagainnotriggersfire.
If IGNORE=Y,thenimportloadsrowsintoexistingtables.Anyexistingtriggersfire,andindexesareupdatedtoaccountforthe
importeddata.

()

HowColumnListsAffectUPDATETriggers()()()()()
An UPDATEstatementmightincludealistofcolumns.Ifatriggeringstatementincludesacolumnlist,thetriggerisfiredonlywhen
oneofthespecifiedcolumnsisupdated.Ifatriggeringstatementomitsacolumnlist,thetriggerisfiredwhenanycolumnofthe
associatedtableisupdated.Acolumnlistcannotbespecifiedfor INSERTor DELETEtriggeringstatements.
Thepreviousexampleofthe PRINT_SALARY_CHANGEStriggercouldincludeacolumnlistinthetriggeringstatement.Forexample:
...BEFOREDELETEORINSERTORUPDATEOFenameONEmp_tab...

Notes:

Youcannotspecifyacolumnlistfor UPDATEwith INSTEAD OFtriggers.


Ifthecolumnspecifiedinthe UPDATE OFclauseisanobjectcolumn,thenthetriggerisalsofiredifanyoftheattributesofthe
objectaremodified.
Youcannotspecify UPDATE OFclausesoncollectioncolumns.

()

ControllingWhenaTriggerIsFired(BEFOREandAFTEROptions)()()()()()
()
The BEFOREor AFTERoptioninthe CREATE TRIGGERstatementspecifiesexactlywhentofirethetriggerbodyinrelationtothe
triggeringstatementthatisbeingrun.Ina CREATE TRIGGERstatement,the BEFOREor AFTERoptionisspecifiedjustbeforethe
triggeringstatement.Forexample,the PRINT_SALARY_CHANGEStriggerinthepreviousexampleisa BEFOREtrigger.
Ingeneral,youuse BEFOREor AFTERtriggerstoachievethefollowingresults:

Use BEFORErowtriggerstomodifytherowbeforetherowdataiswrittentodisk.
Use AFTERrowtriggerstoobtain,andperformoperations,usingtherowID.

Note:
BEFORE rowtriggersareslightlymoreefficientthan AFTER rowtriggers.With AFTER rowtriggers,affecteddata

blocksmustberead(logicalread,notphysicalread)onceforthetriggerandthenagainforthetriggeringstatement.
Alternatively,with BEFORE rowtriggers,thedatablocksmustbereadonlyonceforboththetriggeringstatementand
thetrigger.

()BEFORETriggersFiredMultipleTimes()
Ifan UPDATEor DELETEstatementdetectsaconflictwithaconcurrent UPDATE,thenOracleDatabaseperformsatransparent
ROLLBACKto SAVEPOINTandrestartstheupdate.Thiscanoccurmanytimesbeforethestatementcompletessuccessfully.Each
timethestatementisrestarted,the BEFOREstatementtriggerisfiredagain.Therollbacktosavepointdoesnotundochangestoany

packagevariablesreferencedinthetrigger.Yourpackageshouldincludeacountervariabletodetectthissituation.
()

OrderingofTriggers()

()()ArelationaldatabasedoesnotguaranteetheorderofrowsprocessedbyaSQLstatement.Therefore,donotcreatetriggersthat

dependontheorderinwhichrowsareprocessed.Forexample,donotassignavaluetoaglobalpackagevariableinarowtriggerif
thecurrentvalueoftheglobalvariableisdependentontherowbeingprocessedbytherowtrigger.Also,ifglobalpackagevariables
areupdatedwithinatrigger,thenitisbesttoinitializethosevariablesina BEFOREstatementtrigger.
Whenastatementinatriggerbodycausesanothertriggertobefired,thetriggersaresaidtobecascading.OracleDatabaseallows
upto32triggerstocascadeatanyonetime.However,youcaneffectivelylimitthenumberoftriggercascadesusingthe
initializationparameter OPEN_CURSORS,becauseacursormustbeopenedforeveryexecutionofatrigger.

()TriggerEvaluationOrder
()()()Althoughanytriggercanrunasequenceofoperationseitherinlineorbycallingprocedures,usingmultipletriggersofthe

sametypeenhancesdatabaseadministrationbypermittingthemodularinstallationofapplicationsthathavetriggersonthesame
tables.
OracleDatabaseexecutesalltriggersofthesametypebeforeexecutingtriggersofadifferenttype.Ifyouhavemultipletriggersof
thesametypeonasingletable,thenOracleDatabasechoosesanarbitraryordertoexecutethesetriggers.

SeeAlso:
OracleDatabaseConcepts(../../server.102/b14220/toc.htm)formoreinformationonthefiringorderoftriggers

Eachsubsequenttriggerseesthechangesmadebythepreviouslyfiredtriggers.Eachtriggercanseetheoldandnewvalues.The
oldvaluesaretheoriginalvalues,andthenewvaluesarethecurrentvalues,assetbythemostrecentlyfired UPDATEor INSERT
trigger.
Toensurethatmultipletriggeredactionsoccurinaspecificorder,youmustconsolidatetheseactionsintoasingletrigger(for
example,byhavingthetriggercallaseriesofprocedures).
()
()

ModifyingComplexViews(INSTEADOFTriggers)
An()updatableviewisonethatletsyouperformDMLontheunderlyingtable.Someviewsareinherentlyupdatable,butothersare
notbecausetheywerecreatedwithoneormoreoftheconstructslistedin"ViewsthatRequireINSTEADOFTriggers".
Anyviewthatcontainsoneofthoseconstructscanbemadeupdatablebyusingan INSTEADOFtrigger.()() INSTEAD OFtriggers
provideatransparentwayofmodifyingviewsthatcannotbemodifieddirectlythrough UPDATE, INSERT,and DELETEstatements.
Thesetriggersarecalled INSTEAD OFtriggersbecause,unlikeothertypesoftriggers,OracleDatabasefiresthetriggerinsteadof
executingthetriggeringstatement.Thetriggermustdeterminewhatoperationwasintendedandperform UPDATE, INSERT,or
DELETEoperationsdirectlyontheunderlyingtables.

Withan INSTEADOFtrigger,youcanwritenormal UPDATE, INSERT,and DELETEstatementsagainsttheview,andthe INSTEAD


OFtriggerworksinvisiblyinthebackgroundtomaketherightactionstakeplace.
INSTEAD OFtriggerscanonlybeactivatedforeachrow.

SeeAlso:
"FiringTriggersOneorManyTimes(FOREACHROWOption)"

Note:
The INSTEAD OFoptioncanonlybeusedfortriggerscreatedoverviews.
The BEFOREand AFTERoptionscannotbeusedfortriggerscreatedoverviews.
The CHECKoptionforviewsisnotenforcedwheninsertsorupdatestotheviewaredoneusing INSTEAD OFtriggers.
The INSTEAD OFtriggerbodymustenforcethecheck.

()
()

ViewsthatRequireINSTEADOFTriggers
()()Aviewcannotbemodifiedby UPDATE, INSERT,or DELETEstatementsiftheviewquerycontainsanyofthefollowing

constructs:

Asetoperator
A DISTINCToperator
Anaggregateoranalyticfunction
A GROUP BY, ORDERBY, MODEL, CONNECT BY,or START WITHclause
Acollectionexpressionina SELECTlist
Asubqueryina SELECTlist
Asubquerydesignated WITHREADONLY
Joins,withsomeexceptions,asdocumentedinOracleDatabaseAdministrator'sGuide(../../server.102/b14231/toc.htm)

()()()Ifaviewcontainspseudocolumnsorexpressions,thenyoucanonlyupdatetheviewwithan UPDATEstatementthatdoesnot

refertoanyofthepseudocolumnsorexpressions.
()

INSTEADOFTriggerExample
Note:
Youmayneedtosetupthefollowingdatastructuresforthisexampletowork:
CREATETABLEProject_tab(
Prj_levelNUMBER,
ProjnoNUMBER,
Resp_deptNUMBER)
CREATETABLEEmp_tab(
EmpnoNUMBERNOTNULL,
EnameVARCHAR2(10),
JobVARCHAR2(9),
MgrNUMBER(4),
HiredateDATE,
SalNUMBER(7,2),
CommNUMBER(7,2),
DeptnoNUMBER(2)NOTNULL)

CREATETABLEDept_tab(
DeptnoNUMBER(2)NOTNULL,
DnameVARCHAR2(14),
LocVARCHAR2(13),
Mgr_noNUMBER,
Dept_typeNUMBER)

Thefollowingexampleshowsan INSTEAD OFtriggerforinsertingrowsintothe MANAGER_INFOview.

CREATEORREPLACEVIEWmanager_infoAS
SELECTe.ename,e.empno,d.dept_type,d.deptno,p.prj_level,
p.projno
FROMEmp_tabe,Dept_tabd,Project_tabp
WHEREe.empno=d.mgr_no
ANDd.deptno=p.resp_dept
CREATEORREPLACETRIGGERmanager_info_insert
INSTEADOFINSERTONmanager_info
REFERENCINGNEWASnnewmanagerinformation
FOREACHROW
DECLARE
rowcntnumber
BEGIN
SELECTCOUNT(*)INTOrowcntFROMEmp_tabWHEREempno=:n.empno
IFrowcnt=0THEN
INSERTINTOEmp_tab(empno,ename)VALUES(:n.empno,:n.ename)
ELSE
UPDATEEmp_tabSETEmp_tab.ename=:n.ename
WHEREEmp_tab.empno=:n.empno
ENDIF
SELECTCOUNT(*)INTOrowcntFROMDept_tabWHEREdeptno=:n.deptno
IFrowcnt=0THEN
INSERTINTODept_tab(deptno,dept_type)
VALUES(:n.deptno,:n.dept_type)
ELSE
UPDATEDept_tabSETDept_tab.dept_type=:n.dept_type
WHEREDept_tab.deptno=:n.deptno
ENDIF
SELECTCOUNT(*)INTOrowcntFROMProject_tab
WHEREProject_tab.projno=:n.projno
IFrowcnt=0THEN
INSERTINTOProject_tab(projno,prj_level)
VALUES(:n.projno,:n.prj_level)
ELSE
UPDATEProject_tabSETProject_tab.prj_level=:n.prj_level
WHEREProject_tab.projno=:n.projno
ENDIF
END

Theactionsshownforrowsbeinginsertedintothe MANAGER_INFOviewfirsttesttoseeifappropriaterowsalreadyexistinthebase
tablesfromwhich MANAGER_INFOisderived.Theactionstheninsertnewrowsorupdateexistingrows,asappropriate.Similar
triggerscanspecifyappropriateactionsfor UPDATEand DELETE.
()

ObjectViewsandINSTEADOFTriggers
INSTEAD OFtriggersprovidethemeanstomodifyobjectviewinstancesontheclientsidethroughOCIcalls.

SeeAlso:
OracleCallInterfaceProgrammer'sGuide(../../appdev.102/b14250/toc.htm)

Tomodifyanobjectmaterializedbyanobjectviewintheclientsideobjectcacheandflushitbacktothepersistentstore,youmust
specify INSTEAD OFtriggers,unlesstheobjectviewismodifiable.Iftheobjectisreadonly,thenitisnotnecessarytodefine
triggerstopinit.
()

TriggersonNestedTableViewColumns
INSTEAD OFtriggerscanalsobecreatedovernestedtableviewcolumns.Thesetriggersprovideawayofupdatingelementsofthe

nestedtable.Theyfireforeachnestedtableelementbeingmodified.Therowcorrelationvariablesinsidethetriggercorrespondto
thenestedtableelement.Thistypeoftriggeralsoprovidesanadditionalcorrelationnameforaccessingtheparentrowthatcontains
thenestedtablebeingmodified.

Note:
Thesetriggers:
Canonlybedefinedovernestedtablecolumnsinviews.

Fireonlywhenthenestedtableelementsaremodifiedusingthe THE()or TABLE()clauses.Theydonotfirewhena


DMLstatementisperformedontheview.

Forexample,consideradepartmentviewthatcontainsanestedtableofemployees.
CREATEORREPLACEVIEWDept_viewAS
SELECTd.Deptno,d.Dept_type,d.Dept_name,
CAST(MULTISET(SELECTe.Empno,e.Empname,e.Salary)
FROMEmp_tabe
WHEREe.Deptno=d.Deptno)ASAmp_list_Emplist
FROMDept_tabd

The CAST( MULTISET..)operatorcreatesamultisetofemployeesforeachdepartment.Ifyouwanttomodifythe emplistcolumn,


whichisthenestedtableofemployees,thenyoucandefinean INSTEAD OFtriggeroverthecolumntohandletheoperation.
Thefollowingexampleshowshowaninserttriggermightbewritten:
CREATEORREPLACETRIGGERDept_emplist_tr
INSTEADOFINSERTONNESTEDTABLEEmplistOFDept_view
REFERENCINGNEWASEmployee
PARENTASDepartment
FOREACHROW
BEGIN
Theinsertonthenestedtableistranslatedtoaninsertonthebasetable:
INSERTINTOEmp_tabVALUES(
:Employee.Empno,:Employee.Empname,:Employee.Salary,:Department.Deptno)
END

Any INSERTintothenestedtablefiresthetrigger,andthe Emp_tabtableisfilledwiththecorrectvalues.Forexample:


INSERTINTOTABLE(SELECTd.EmplistFROMDept_viewdWHEREDeptno=10)
VALUES(1001,'JohnGlenn',10000)

The :department. deptnocorrelationvariableinthisexamplewouldhaveavalueof10.


()
()

FiringTriggersOneorManyTimes(FOREACHROWOption)()()()()
The FOR EACH ROWoptiondetermineswhetherthetriggerisarowtriggerorastatementtrigger.Ifyouspecify FOR EACH ROW,
thenthetriggerfiresonceforeachrowofthetablethatisaffectedbythetriggeringstatement.Theabsenceofthe FOR EACH ROW
optionindicatesthatthetriggerfiresonlyonceforeachapplicablestatement,butnotseparatelyforeachrowaffectedbythe
statement.
()Forexample,youdefinethefollowingtrigger:

Note:
Youmayneedtosetupthefollowingdatastructuresforcertainexamplestowork:
CREATETABLEEmp_log(
Emp_idNUMBER,
Log_dateDATE,
New_salaryNUMBER,
ActionVARCHAR2(20))

CREATEORREPLACETRIGGERLog_salary_increase
AFTERUPDATEONEmp_tab
FOREACHROW
WHEN(new.Sal>1000)
BEGIN
INSERTINTOEmp_log(Emp_id,Log_date,New_salary,Action)
VALUES(:new.Empno,SYSDATE,:new.SAL,'NEWSAL')
END

Then,youenterthefollowingSQLstatement:
UPDATEEmp_tabSETSal=Sal+1000.0
WHEREDeptno=20

Iftherearefiveemployeesindepartment20,thenthetriggerfiresfivetimeswhenthisstatementisentered,becausefiverowsare
affected.
Thefollowingtriggerfiresonlyonceforeach UPDATEofthe Emp_tabtable:
CREATEORREPLACETRIGGERLog_emp_update
AFTERUPDATEONEmp_tab
BEGIN
INSERTINTOEmp_log(Log_date,Action)
VALUES(SYSDATE,'Emp_tabCOMMISSIONSCHANGED')
END

SeeAlso:
OracleDatabaseConcepts(../../server.102/b14220/toc.htm)fortheorderoftriggerfiring

Thestatementleveltriggersareusefulforperformingvalidationchecksfortheentirestatement.
()

FiringTriggersBasedonConditions(WHENClause)()()()
Optionally,atriggerrestrictioncanbeincludedinthedefinitionofarowtriggerbyspecifyingaBooleanSQLexpressionina WHEN
clause.

Note:
A WHEN clausecannotbeincludedinthedefinitionofastatementtrigger.

Ifincluded,thentheexpressioninthe WHENclauseisevaluatedforeachrowthatthetriggeraffects.
Iftheexpressionevaluatesto TRUEforarow,thenthetriggerbodyisfiredonbehalfofthatrow.However,iftheexpression
evaluatesto FALSEor NOT TRUEforarow(unknown,aswithnulls),thenthetriggerbodyisnotfiredforthatrow.Theevaluationof
the WHENclausedoesnothaveaneffectontheexecutionofthetriggeringSQLstatement(inotherwords,thetriggeringstatement
isnotrolledbackiftheexpressionina WHENclauseevaluatesto FALSE).
Forexample,inthe PRINT_SALARY_CHANGEStrigger,thetriggerbodyisnotrunifthenewvalueof Empnoiszero, NULL,or
negative.Inmorerealisticexamples,youmighttestifonecolumnvalueislessthananother.
()()Theexpressionina WHENclauseofarowtriggercanincludecorrelationnames,whichareexplainedlater.Theexpressionina

WHENclausemustbeaSQLexpression,anditcannotincludeasubquery.YoucannotuseaPL/SQLexpression(includinguser
definedfunctions)inthe WHENclause.

Note:
Youcannotspecifythe WHEN clausefor INSTEAD OF triggers.

()
()

CodingtheTriggerBody()
()()()Thetriggerbodyisa CALLprocedureoraPL/SQLblockthatcanincludeSQLandPL/SQLstatements.The CALLprocedure

canbeeitheraPL/SQLoraJavaprocedurethatisencapsulatedinaPL/SQLwrapper.Thesestatementsarerunifthetriggering
statementisenteredandifthetriggerrestriction(ifincluded)evaluatesto TRUE.
ThetriggerbodyforrowtriggershassomespecialconstructsthatcanbeincludedinthecodeofthePL/SQLblock:correlation
namesandthe REFERENCEINGoption,andtheconditionalpredicates INSERTING, DELETING,and UPDATING.

Note:
The INSERTING , DELETING ,and UPDATING conditionalpredicatescannotbeusedforthe CALL proceduresthey
canonlybeusedinaPL/SQLblock.

()

Example:MonitoringLogonswithaTrigger

Note:
Youmayneedtosetupdatastructuressimilartothefollowingforcertainexamplestowork:
CONNECTsystem/manager
GRANTADMINISTERDATABASETRIGGERTOscott
CONNECTscott/tiger
CREATETABLEaudit_table(
seqnumber,
user_atVARCHAR2(10),
time_nowDATE,
termVARCHAR2(10),
jobVARCHAR2(10),
procVARCHAR2(10),
enumNUMBER)

CREATEORREPLACEPROCEDUREfoo(cVARCHAR2)AS
BEGIN
INSERTINTOAudit_table(user_at)VALUES(c)
END
CREATEORREPLACETRIGGERlogontrigAFTERLOGONONDATABASE
Justcallanexistingprocedure.TheORA_LOGIN_USERisafunction
thatreturnsinformationabouttheeventthatfiredthetrigger.
CALLfoo(ora_login_user)
/
()

Example:CallingaJavaProcedurefromaTrigger
AlthoughtriggersaredeclaredusingPL/SQL,theycancallproceduresinotherlanguages,suchasJava:
CREATEORREPLACEPROCEDUREBefore_delete(IdINNUMBER,EnameVARCHAR2)
ISlanguageJava
name'thjvTriggers.beforeDelete(oracle.sql.NUMBER,oracle.sql.CHAR)'
CREATEORREPLACETRIGGERPre_del_triggerBEFOREDELETEONTab
FOREACHROW
CALLBefore_delete(:old.Id,:old.Ename)
/

ThecorrespondingJavafileis thjvTriggers.java:
importjava.sql.*
importjava.io.*
importoracle.sql.*
importoracle.oracore.*
publicclassthjvTriggers
{
publicstatevoid
beforeDelete(NUMBERold_id,CHARold_name)
ThrowsSQLException,CoreException
{
Connectionconn=JDBCConnection.defaultConnection()
Statementstmt=conn.CreateStatement()
Stringsql="insertintologtabvalues
("+old_id.intValue()+",'"+old_ename.toString()+",BEFOREDELETE')
stmt.executeUpdate(sql)
stmt.close()
return
}
}
()

AccessingColumnValuesinRowTriggers()()()()

Withinatriggerbodyofarowtrigger,thePL/SQLcodeandSQLstatementshaveaccesstotheoldandnewcolumnvaluesofthe
currentrowaffectedbythetriggeringstatement.Twocorrelationnamesexistforeverycolumnofthetablebeingmodified:onefor
theoldcolumnvalue,andoneforthenewcolumnvalue.Dependingonthetypeoftriggeringstatement,certaincorrelationnames
mightnothaveanymeaning.

()Atriggerfiredbyan INSERTstatementhasmeaningfulaccesstonewcolumnvaluesonly.Becausetherowisbeingcreatedby

the INSERT,theoldvaluesarenull.
()Atriggerfiredbyan UPDATEstatementhasaccesstobotholdandnewcolumnvaluesforboth BEFOREand AFTERrow

triggers.
()Atriggerfiredbya DELETEstatementhasmeaningfulaccessto: oldcolumnvaluesonly.Becausetherownolongerexists

aftertherowisdeleted,the: newvaluesare NULL.However,youcannotmodify: newvaluesbecause ORA 4084israisedifyou


trytomodify: newvalues.

()()()()Thenewcolumnvaluesarereferencedusingthe newqualifierbeforethecolumnname,whiletheoldcolumnvaluesare

referencedusingthe oldqualifierbeforethecolumnname.Forexample,ifthetriggeringstatementisassociatedwiththe Emp_tab


table(withthecolumns SAL, COMM,andsoon),thenyoucanincludestatementsinthetriggerbody.Forexample:
IF:new.Sal>10000...
IF:new.Sal<:old.Sal...

()()()()Oldandnewvaluesareavailableinboth BEFOREand AFTERrowtriggers.A newcolumnvaluecanbeassignedina

BEFORErowtrigger,butnotinan AFTERrowtrigger(becausethetriggeringstatementtakeseffectbeforean AFTERrowtriggeris

fired).Ifa BEFORErowtriggerchangesthevalueof new. column,thenan AFTERrowtriggerfiredbythesamestatementseesthe


changeassignedbythe BEFORErowtrigger.
()()CorrelationnamescanalsobeusedintheBooleanexpressionofa WHENclause.Acolon( :)mustprecedethe oldand new

qualifierswhentheyareusedinatriggerbody,butacolonisnotallowedwhenusingthequalifiersinthe WHENclauseorthe
REFERENCINGoption.
()
()

()Example:ModifyingLOBColumnswithaTrigger
YoucantreatLOBcolumnsthesameasothercolumns,usingregularSQLandPL/SQLfunctionswith CLOBcolumns,andcallsto
the DBMS_LOBpackagewith BLOBcolumns:
droptabletab1
createtabletab1(c1clob)
insertintotab1values('<h1>HTMLDocumentFragment</h1><p>Sometext.')
createorreplacetriggertrg1
beforeupdateontab1
foreachrow
begin
dbms_output.put_line('OldvalueofCLOBcolumn:'||:OLD.c1)
dbms_output.put_line('ProposednewvalueofCLOBcolumn:'||:NEW.c1)
Previously,wecouldn'tchangethenewvalueforaLOB.
Now,wecanreplaceit,orconstructanewvalueusingSUBSTR,INSTR...
operationsforaCLOB,orDBMS_LOBcallsforaBLOB.
:NEW.c1:=:NEW.c1||to_clob('<hr><p>Standardfooterparagraph.')
dbms_output.put_line('FinalvalueofCLOBcolumn:'||:NEW.c1)
end
/
setserveroutputon
updatetab1setc1='<h1>DifferentDocumentFragment</h1><p>Differenttext.'
select*fromtab1
()

INSTEADOFTriggersonNestedTableViewColumns()
Inthecaseof INSTEAD OFtriggersonnestedtableviewcolumns,the newand oldqualifierscorrespondtothenewandold
nestedtableelements.Theparentrowcorrespondingtothisnestedtableelementcanbeaccessedusingthe parentqualifier.The
parentcorrelationnameismeaningfulandvalidonlyinsideanestedtabletrigger.

()

AvoidingNameConflictswithTriggers(REFERENCINGOption)()()()()
The REFERENCINGoptioncanbespecifiedinatriggerbodyofarowtriggertoavoidnameconflictsamongthecorrelationnames
andtablesthatmightbenamed oldor new.Becausethisisrare,thisoptionisinfrequentlyused.
()Forexample,assumeyouhaveatablenamed newwithcolumns field1(number)and field2(character).Thefollowing

CREATE TRIGGERexampleshowsatriggerassociatedwiththe newtablethatcanusecorrelationnamesandavoidnaming


conflictsbetweenthecorrelationnamesandthetablename:

Note:
Youmayneedtosetupthefollowingdatastructuresforcertainexamplestowork:
CREATETABLEnew(
field1NUMBER,
field2VARCHAR2(20))

CREATEORREPLACETRIGGERPrint_salary_changes
BEFOREUPDATEONnew
REFERENCINGnewASNewest
FOREACHROW
BEGIN
:Newest.Field2:=TO_CHAR(:newest.field1)
END

Noticethatthe newqualifierisrenamedto newestusingthe REFERENCINGoption,anditisthenusedinthetriggerbody.


()

DetectingtheDML()O()per()ationThatFiredaTrigger
()IfmorethanonetypeofDMLoperationcanfireatrigger(forexample, ON INSERT OR DELETE OR UPDATE OF Emp_tab),the

triggerbodycanusetheconditionalpredicates INSERTING, DELETING,and UPDATINGtocheckwhichtypeofstatementfirethe


trigger.
Withinthecodeofthetriggerbody,youcanexecuteblocksofcodedependingonthekindofDMLoperationfiredthetrigger:
IFINSERTINGTHEN...ENDIF
IFUPDATINGTHEN...ENDIF

Thefirstconditionevaluatesto TRUEonlyifthestatementthatfiredthetriggerisan INSERTstatementthesecondcondition


evaluatesto TRUEonlyifthestatementthatfiredthetriggerisan UPDATEstatement.
()()()()()Inan UPDATEtrigger,acolumnnamecanbespecifiedwithan UPDATINGconditionalpredicatetodetermineifthenamed

columnisbeingupdated.Forexample,assumeatriggerisdefinedasthefollowing:
CREATEORREPLACETRIGGER...
...UPDATEOFSal,CommONEmp_tab...
BEGIN
...IFUPDATING('SAL')THEN...ENDIF
END

Thecodeinthe THENclauserunsonlyifthetriggering UPDATEstatementupdatesthe SALcolumn.Thisway,thetriggercan


minimizeitsoverheadwhenthecolumnofinterestisnotbeingchanged.
()

ErrorConditionsandExceptionsintheTriggerBody()()()
()Ifapredefinedoruserdefinederrorconditionorexceptionisraisedduringtheexecutionofatriggerbody,thenalleffectsofthe

triggerbody,aswellasthetriggeringstatement,arerolledback(unlesstheerroristrappedbyanexceptionhandler).Therefore,a
triggerbodycanpreventtheexecutionofthetriggeringstatementbyraisinganexception.Userdefinedexceptionsarecommonly
usedintriggersthatenforcecomplexsecurityauthorizationsorintegrityconstraints.
Theonlyexceptiontothisiswhentheeventunderconsiderationisdatabase STARTUP, SHUTDOWN,or LOGINwhentheuser
logginginis SYSTEM.Inthesescenarios,onlythetriggeractionisrolledback.
()

()TriggersonObjectTables
Youcanusethe() OBJECT_VALUEpseudocolumninatriggeronanobjecttablesince10gRelease1(10.1). OBJECT_VALUEmeans
theobjectasawhole.Thisisoneexampleofitsuse.YoucanalsocallaPL/SQLfunctionwith OBJECT_VALUEasthedatatypeofan
INformalparameter.

Hereisanexampleoftheuseof OBJECT_VALUEinatrigger.Tokeeptrackofupdatestovaluesinanobjecttable tbl,ahistory


table, tbl_history,isalsocreatedinthefollowingexample.For tbl,thevalues1through5areinsertedinto n,while miskept
at0.ThetriggerisarowleveltriggerthatexecutesonceforeachrowaffectedbyaDMLstatement.Thetriggercausestheoldand
newvaluesoftheobject tin tbltobewrittenin tbl_historywhen tblisupdated.Theseoldandnewvaluesare
: OLD.OBJECT_VALUEand: NEW.OBJECT_VALUE.Anupdateofthetable tblisdone(eachvalueof nisincreasedby1).Aselect
fromthehistorytabletocheckthatthetriggerworksisthenshownattheendoftheexample:
CREATEORREPLACETYPEtASOBJECT(nNUMBER,mNUMBER)
/
CREATETABLEtblOFt
/
BEGIN
FORjIN1..5LOOP
INSERTINTOtblVALUES(t(j,0))
ENDLOOP
END
/
CREATETABLEtbl_history(dDATE,old_objt,new_objt)
/
CREATEORREPLACETRIGGERTbl_Trg
AFTERUPDATEONtbl
FOREACHROW
BEGIN
INSERTINTOtbl_history(d,old_obj,new_obj)
VALUES(SYSDATE,:OLD.OBJECT_VALUE,:NEW.OBJECT_VALUE)
ENDTbl_Trg
/

UPDATEtblSETtbl.n=tbl.n+1
/
BEGIN
FORjIN(SELECTd,old_obj,new_objFROMtbl_history)LOOP
Dbms_Output.Put_Line(
j.d||
'old:'||j.old_obj.n||''||j.old_obj.m||
'new:'||j.new_obj.n||''||j.new_obj.m)
ENDLOOP
END
/

Theresultoftheselectshowsthatthevaluesofthecolumn nhavebeenallincreasedby1.Thevalueof mremains0.Theoutput


oftheselectis:
23MAY05old:10new:20
23MAY05old:20new:30
23MAY05old:30new:40
23MAY05old:40new:50
23MAY05old:50new:60
()

TriggersandHandlingRemoteExceptions()()
()Atriggerthataccessesaremotesitecannotdoremoteexceptionhandlingifthenetworklinkisunavailable.Forexample:

CREATEORREPLACETRIGGERExample
AFTERINSERTONEmp_tab
FOREACHROW
BEGIN
INSERTINTOEmp_tab@Remote<compilationfailshere
VALUES('x')whendblinkisinaccessible
EXCEPTION
WHENOTHERSTHEN
INSERTINTOEmp_log
VALUES('x')
END

Atriggeriscompiledwhenitiscreated.Thus,ifaremotesiteisunavailablewhenthetriggermustcompile,thenOracleDatabase
cannotvalidatethestatementaccessingtheremotedatabase,andthecompilationfails.Thepreviousexampleexceptionstatement
cannotrun,becausethetriggerdoesnotcompletecompilation.
Becausestoredproceduresarestoredinacompiledform,theworkaroundforthepreviousexampleisasfollows:
CREATEORREPLACETRIGGERExample
AFTERINSERTONEmp_tab
FOREACHROW
BEGIN
Insert_row_proc
END
CREATEORREPLACEPROCEDUREInsert_row_procAS
BEGIN
INSERTINTOEmp_tab@Remote
VALUES('x')
EXCEPTION
WHENOTHERSTHEN
INSERTINTOEmp_log
VALUES('x')
END

Thetriggerinthisexamplecompilessuccessfullyandcallsthestoredprocedure,whichalreadyhasavalidatedstatementfor
accessingtheremotedatabasethus,whentheremote INSERTstatementfailsbecausethelinkisdown,theexceptioniscaught.
()

RestrictionsonCreatingTriggers()()
CodingtriggersrequiressomerestrictionsthatarenotrequiredforstandardPL/SQLblocks.Thefollowingsectionsdiscussthese
restrictions.

()MaximumTriggerSize
Thesizeofatriggercannotbemorethan32K.

()SQLStatementsAllowedinTriggerBodies
()()()ThebodyofatriggercancontainDMLSQLstatements.Itcanalsocontain SELECTstatements,buttheymustbe SELECT...

INTO...statementsorthe SELECTstatementinthedefinitionofacursor.
()()DDLstatementsarenotallowedinthebodyofatrigger.Also,notransactioncontrolstatementsareallowedinatrigger.

ROLLBACK, COMMIT,and SAVEPOINTcannotbeused.Forsystemtriggers,{ CREATE/ ALTER/ DROP} TABLEstatementsand


ALTER... COMPILEareallowed.

Note:
Aprocedurecalledbyatriggercannotruntheprevioustransactioncontrolstatements,becausetheprocedurerunswithin
thecontextofthetriggerbody.

()()()()()Statementsinsideatriggercanreferenceremoteschemaobjects.However,payspecialattentionwhencallingremote

proceduresfromwithinalocaltrigger.Ifatimestamporsignaturemismatchisfoundduringexecutionofthetrigger,thentheremote
procedureisnotrun,andthetriggerisinvalidated.

()()()TriggerRestrictionsonLONGandLONGRAWDatatypes
LONGand LONG RAWdatatypesintriggersaresubjecttothefollowingrestrictions:

ASQLstatementwithinatriggercaninsertdataintoacolumnof LONGor LONG RAWdatatype.


Ifdatafroma LONGor LONG RAWcolumncanbeconvertedtoaconstraineddatatype(suchas CHARand VARCHAR2),thena
LONGor LONG RAWcolumncanbereferencedinaSQLstatementwithinatrigger.Themaximumlengthforthesedatatypesis
32000bytes.
Variablescannotbedeclaredusingthe LONGor LONG RAWdatatypes.
: NEWand: PARENTcannotbeusedwith LONGor LONG RAWcolumns.

()TriggerRestrictionsonMutatingTables()()()()()
A()()mutatingtableisatablethatisbeingmodifiedbyan UPDATE, DELETE,or INSERTstatement,oratablethatmightbe
updatedbytheeffectsofa DELETE CASCADEconstraint.
Thesessionthatissuedthetriggeringstatementcannotqueryormodifyamutatingtable.Thisrestrictionpreventsatriggerfrom
seeinganinconsistentsetofdata.
Thisrestrictionappliestoalltriggersthatusethe FOREACHROWclause.Viewsbeingmodifiedin INSTEAD OFtriggersarenot
consideredmutating.
Whenatriggerencountersamutatingtable,aruntimeerroroccurs,theeffectsofthetriggerbodyandtriggeringstatementare
rolledback,andcontrolisreturnedtotheuserorapplication.
Considerthefollowingtrigger:
CREATEORREPLACETRIGGEREmp_count
AFTERDELETEONEmp_tab
FOREACHROW
DECLARE
nINTEGER
BEGIN
SELECTCOUNT(*)INTOnFROMEmp_tab
DBMS_OUTPUT.PUT_LINE('Therearenow'||n||
'employees.')
END

IfthefollowingSQLstatementisentered:
DELETEFROMEmp_tabWHEREEmpno=7499

Anerrorisreturnedbecausethetableismutatingwhentherowisdeleted:
ORA04091:tableSCOTT.Emp_tabismutating,trigger/functionmaynotseeit

Ifyoudeletetheline" FOR EACH ROW"fromthetrigger,itbecomesastatementtriggerwhichisnotsubjecttothisrestriction,andthe


trigger.
Ifyouneedtoupdateamutatingtable,youcouldbypasstheserestrictionsbyusingatemporarytable,aPL/SQLtable,ora
packagevariable.Forexample,inplaceofasingle AFTERrowtriggerthatupdatestheoriginaltable,resultinginamutatingtable
error,youmightusetwotriggersan AFTERrowtriggerthatupdatesatemporarytable,andan AFTERstatementtriggerthat
updatestheoriginaltablewiththevaluesfromthetemporarytable.
Declarativeintegrityconstraintsarecheckedatvarioustimeswithrespecttorowtriggers.

SeeAlso:
OracleDatabaseConcepts(../../server.102/b14220/toc.htm)forinformationabouttheinteractionoftriggersandintegrity
constraints

Becausedeclarativereferentialintegrityconstraintsarenotsupportedbetweentablesondifferentnodesofadistributeddatabase,
themutatingtablerestrictionsdonotapplytotriggersthataccessremotenodes.Theserestrictionsarealsonotenforcedamong
tablesinthesamedatabasethatareconnectedbyloopbackdatabaselinks.Aloopbackdatabaselinkmakesalocaltableappear
remotebydefininganOracleNetpathbacktothedatabasethatcontainsthelink.
()RestrictionsonMutatingTablesRelaxed

Themutatingerror,discussedearlierinthissection,stillpreventsthetriggerfromreadingormodifyingthetablethattheparent
statementismodifying.However,startinginOracleDatabaseRelease8.1,adeleteagainsttheparenttablecausesbefore/after
statementtriggerstobefiredonce.Thatway,youcancreatetriggers(justnotrowtriggers)toreadandmodifytheparentandchild
tables.
Thisallowsmostforeignkeyconstraintactionstobeimplementedthroughtheirobviousafterrowtrigger,providingtheconstraintis
notselfreferential.Updatecascade,updatesetnull,updatesetdefault,deletesetdefault,insertingamissingparent,and
maintainingacountofchildrencanallbeimplementedeasily.Forexample,thisisanimplementationofupdatecascade:

createtablep(p1numberconstraintppkprimarykey)
createtablef(f1numberconstraintffkreferencesp)
createtriggerptafterupdateonpforeachrowbegin
updatefsetf1=:new.p1wheref1=:old.p1
end
/

Thisimplementationrequirescareformultirowupdates.Forexample,ifatablephasthreerowswiththevalues(1),(2),(3),and
tablefalsohasthreerowswiththevalues(1),(2),(3),thenthefollowingstatementupdatespcorrectlybutcausesproblemswhen
thetriggerupdatesf:
updatepsetp1=p1+1

Thestatementfirstupdates(1)to(2)inp,andthetriggerupdates(1)to(2)inf,leavingtworowsofvalue(2)inf.Thenthe
statementupdates(2)to(3)inp,andthetriggerupdatesbothrowsofvalue(2)to(3)inf.Finally,thestatementupdates(3)to(4)in
p,andthetriggerupdatesallthreerowsinffrom(3)to(4).Therelationshipofthedatainpandfislost.
Toavoidthisproblem,youmustforbidmultirowupdatestopthatchangetheprimarykeyandreuseexistingprimarykeyvalues.It
couldalsobesolvedbytrackingwhichforeignkeyvalueshavealreadybeenupdated,thenmodifyingthetriggersothatnorowis
updatedtwice.
Thatistheonlyproblemwiththistechniqueforforeignkeyupdates.Thetriggercannotmissrowsthathavebeenchangedbutnot
committedbyanothertransaction,becausetheforeignkeyconstraintguaranteesthatnomatchingforeignkeyrowsarelocked
beforetheafterrowtriggeriscalled.

()()SystemTriggerRestrictions
Dependingontheevent,differenteventattributefunctionsareavailable.Forexample,certainDDLoperationsmaynotbeallowed
onDDLevents.Check"EventAttributeFunctions"beforeusinganeventattributefunction,becauseitseffectsmightbeundefined
ratherthanproducinganerrorcondition.
Onlycommittedtriggersarefired.Forexample,ifyoucreateatriggerthatshouldbefiredafterall CREATEevents,thenthetrigger
itselfdoesnotfireafterthecreation,becausethecorrectinformationaboutthistriggerwasnotcommittedatthetimewhenthe
triggeron CREATEeventswasfired.
Forexample,ifyouexecutethefollowingSQLstatement:
CREATEORREPLACETRIGGERmy_triggerAFTERCREATEONDATABASE
BEGINnull
END

Then,trigger my_triggerisnotfiredafterthecreationof my_trigger.OracleDatabasedoesnotfireatriggerthatisnot


committed.
()ForeignFunctionCallouts

Allrestrictionsonforeignfunctioncalloutsalsoapply.
()

WhoIstheTriggerUser?
()()Thefollowingstatement,insideatrigger,returnstheownerofthetrigger,notthenameofuserwhoisupdatingthetable:

SELECTUsernameFROMUSER_USERS
()

PrivilegesNeededtoWorkwithTriggers()()
()()()Tocreateatriggerinyourschema,youmusthavethe CREATE TRIGGERsystemprivilege,andeither:

Ownthetablespecifiedinthetriggeringstatement,or
Havethe ALTERprivilegeforthetableinthetriggeringstatement,or
Havethe ALTER ANY TABLEsystemprivilege

Tocreateatriggerinanotheruser'sschema,ortoreferenceatableinanotherschemafromatriggerinyourschema,youmust
havethe CREATE ANY TRIGGERsystemprivilege.Withthisprivilege,thetriggercanbecreatedinanyschemaandcanbe
associatedwithanyuser'stable.Inaddition,theusercreatingthetriggermustalsohave EXECUTEprivilegeonthereferenced

procedures,functions,orpackages.
Tocreateatriggeron DATABASE,youmusthavethe ADMINISTER DATABASE TRIGGERprivilege.Ifthisprivilegeislaterrevoked,
thenyoucandropthetrigger,butnotalterit.
Theobjectprivilegestotheschemaobjectsreferencedinthetriggerbodymustbegrantedtothetriggerownerexplicitly(not
througharole).Thestatementsinthetriggerbodyoperateundertheprivilegedomainofthetriggerowner,nottheprivilegedomain
oftheuserissuingthetriggeringstatement.Thisissimilartotheprivilegemodelforstoredprocedures.
()
()

CompilingTriggers()()
TriggersaresimilartoPL/SQLanonymousblockswiththeadditionofthe: newand: oldcapabilities,buttheircompilationis
different.APL/SQLanonymousblockiscompiledeachtimeitisloadedintomemory.Compilationinvolvesthreestages:

1. Syntaxchecking:PL/SQLsyntaxischecked,andaparsetreeisgenerated().
2. Semanticchecking:Typecheckingandfurtherprocessingontheparsetree.
3. Codegeneration:Thepcodeisgenerated.()

Triggers,incontrast,arefullycompiledwhenthe CREATE TRIGGERstatementisentered,andthepcodeisstoredinthedata


dictionary.Hence,firingthetriggernolongerrequirestheopeningofasharedcursortorunthetriggeraction.Instead,thetriggeris
executeddirectly.
Iferrorsoccurduringthecompilationofatrigger,thenthetriggerisstillcreated.IfaDMLstatementfiresthistrigger,thentheDML
statementfails.(RuntimethattriggererrorsalwayscausetheDMLstatementtofail.)Youcanusethe SHOW ERRORSstatementin
SQL*PlusorEnterpriseManagertoseeanycompilationerrorswhenyoucreateatrigger,oryoucan SELECTtheerrorsfromthe
USER_ERRORSview.
()

DependenciesforTriggers()
Compiledtriggershavedependencies.Theybecomeinvalidifadependedonobject,suchasastoredprocedureorfunctioncalled
fromthetriggerbody,ismodified.Triggersthatareinvalidatedfordependencyreasonsarerecompiledwhennextinvoked.
Youcanexaminethe ALL_DEPENDENCIESviewtoseethedependenciesforatrigger.Forexample,thefollowingstatementshows
thedependenciesforthetriggersinthe SCOTTschema:
SELECTNAME,REFERENCED_OWNER,REFERENCED_NAME,REFERENCED_TYPE
FROMALL_DEPENDENCIES
WHEREOWNER='SCOTT'andTYPE='TRIGGER'

Triggersmaydependonotherfunctionsorpackages.Ifthefunctionorpackagespecifiedinthetriggerisdropped,thenthetrigger
ismarkedinvalid.Anattemptismadetovalidatethetriggeronoccurrenceoftheevent.Ifthetriggercannotbevalidated
successfully,thenitismarked VALID WITH ERRORS,andtheeventfails.

Note:
Thereisanexceptionfor STARTUPevents: STARTUPeventssucceedevenifthetriggerfails.Therearealsoexceptions
for SHUTDOWNeventsandfor LOGONeventsifyouloginas SYSTEM.
Becausethe DBMS_AQpackageisusedtoenqueueamessage,dependencybetweentriggersandqueuescannotbe
maintained.

()

RecompilingTriggers()
Usethe ALTER TRIGGERstatementtorecompileatriggermanually.Forexample,thefollowingstatementrecompilesthe
PRINT_SALARY_CHANGEStrigger:
ALTERTRIGGERPrint_salary_changesCOMPILE

()Torecompileatrigger,youmustownthetriggerorhavethe ALTER ANY TRIGGERsystemprivilege.

()
()

ModifyingTriggers()
Likeastoredprocedure,atriggercannotbeexplicitlyaltered:Itmustbereplacedwithanewdefinition.(The ALTER TRIGGER
statementisusedonlytorecompile,enable,ordisableatrigger.)
Whenreplacingatrigger,youmustincludethe OR REPLACEoptioninthe CREATE TRIGGERstatement.The OR REPLACEoptionis
providedtoallowanewversionofanexistingtriggertoreplacetheolderversion,withoutaffectinganygrantsmadefortheoriginal
versionofthetrigger.
Alternatively,thetriggercanbedroppedusingthe DROP TRIGGERstatement,andyoucanrerunthe CREATE TRIGGERstatement.()
()()()

Todropatrigger,thetriggermustbeinyourschema,oryoumusthavethe DROP ANY TRIGGERsystemprivilege.


()
()

DebuggingTriggers()()
Youcandebugatriggerusingthesamefacilitiesavailableforstoredprocedures.

SeeAlso:
"DebuggingStoredProcedures"(adfns_packages.htm#i1007648)

()
()

EnablingandDisablingTriggers
()()()()Atriggercanbeinoneoftwodistinctmodes:
()()Enabled.Anenabledtriggerexecutesitstriggerbodyifatriggeringstatementisenteredandthetriggerrestriction(ifany)

evaluatesto TRUE.
()()Disabled.Adisabledtriggerdoesnotexecuteitstriggerbody,evenifatriggeringstatementisenteredandthetriggerrestriction

(ifany)evaluatesto TRUE.
()

EnablingTriggers()()
Bydefault,atriggerisautomaticallyenabledwhenitiscreatedhowever,itcanlaterbedisabled.Afteryouhavecompletedthetask
thatrequiredthetriggertobedisabled,reenablethetrigger,sothatitfireswhenappropriate.
()Enableadisabledtriggerusingthe ALTER TRIGGERstatementwiththe ENABLEoption.Toenablethedisabledtriggernamed

REORDERofthe INVENTORYtable,enterthefollowingstatement:
ALTERTRIGGERReorderENABLE

()Alltriggersdefinedforaspecifictablecanbeenabledwithonestatementusingthe ALTER TABLEstatementwiththe ENABLE

clausewiththe ALL TRIGGERSoption.Forexample,toenablealltriggersdefinedforthe INVENTORYtable,enterthefollowing


statement:
ALTERTABLEInventory
ENABLEALLTRIGGERS
()

DisablingTriggers()()
Youmighttemporarilydisableatriggerif:

Anobjectitreferencesisnotavailable.
Youneedtoperformalargedataload,andyouwantittoproceedquicklywithoutfiringtriggers.
Youarereloadingdata.

()Bydefault,triggersareenabledwhenfirstcreated.Disableatriggerusingthe ALTER TRIGGERstatementwiththe DISABLE

option.
Forexample,todisablethetriggernamed REORDERofthe INVENTORYtable,enterthefollowingstatement:
ALTERTRIGGERReorderDISABLE

()Alltriggersassociatedwithatablecanbedisabledwithonestatementusingthe ALTER TABLEstatementwiththe DISABLE

clauseandthe ALL TRIGGERSoption.Forexample,todisablealltriggersdefinedforthe INVENTORYtable,enterthefollowing


statement:
ALTERTABLEInventory
DISABLEALLTRIGGERS
()
()

ViewingInformationAboutTriggers()
Thefollowingdatadictionaryviewsrevealinformationabouttriggers:

USER_TRIGGERS
ALL_TRIGGERS
DBA_TRIGGERS

Thenewcolumn, BASE_OBJECT_TYPE,specifieswhetherthetriggerisbasedon DATABASE, SCHEMA,table,orview.Theold


column, TABLE_NAME,isnullifthebaseobjectisnottableorview.
Thecolumn ACTION_TYPEspecifieswhetherthetriggerisacalltypetriggeroraPL/SQLtrigger.
Thecolumn TRIGGER_TYPEincludestwoadditionalvalues: BEFORE EVENTand AFTER EVENT,applicableonlytosystemevents.
Thecolumn TRIGGERING_EVENTincludesallsystemandDMLevents.

SeeAlso:
OracleDatabaseReference(../../server.102/b14237/toc.htm)foracompletedescriptionofthesedatadictionaryviews

Forexample,assumethefollowingstatementwasusedtocreatethe REORDERtrigger:

Caution:
Youmayneedtosetupdatastructuresforcertainexamplestowork:

()CREATEORREPLACETRIGGERReorder

AFTERUPDATEOFParts_on_handONInventory
FOREACHROW
WHEN(new.Parts_on_hand<new.Reorder_point)
DECLARE
xNUMBER
BEGIN
SELECTCOUNT(*)INTOx
FROMPending_orders
WHEREPart_no=:new.Part_no
IFx=0THEN
INSERTINTOPending_orders
VALUES(:new.Part_no,:new.Reorder_quantity,
sysdate)
ENDIF
END

Thefollowingtwoqueriesreturninformationaboutthe REORDERtrigger:

SELECTTrigger_type,Triggering_event,Table_name
FROMUSER_TRIGGERS
WHERETrigger_name='REORDER'
TYPETRIGGERING_STATEMENTTABLE_NAME

AFTEREACHROWUPDATEINVENTORY
SELECTTrigger_body
FROMUSER_TRIGGERS
WHERETrigger_name='REORDER'
TRIGGER_BODY

DECLARE
xNUMBER
BEGIN
SELECTCOUNT(*)INTOx
FROMPending_orders
WHEREPart_no=:new.Part_no
IFx=0
THENINSERTINTOPending_orders
VALUES(:new.Part_no,:new.Reorder_quantity,
sysdate)
ENDIF
END
()
()

ExamplesofTriggerApplications()
YoucanusetriggersinanumberofwaystocustomizeinformationmanagementinOracleDatabase.Forexample,triggersare
commonlyusedto:

Providesophisticatedauditing
Preventinvalidtransactions
Enforcereferentialintegrity(eitherthoseactionsnotsupportedbydeclarativeintegrityconstraintsoracrossnodesinadistributed
database)
Enforcecomplexbusinessrules
Enforcecomplexsecurityauthorizations
Providetransparenteventlogging
Automaticallygeneratederivedcolumnvalues
Enablebuildingcomplexviewsthatareupdatable
Tracksystemevents

Thissectionprovidesanexampleofeachofthesetriggerapplications.Theseexamplesarenotmeanttobeusedexactlyaswritten:
Theyareprovidedtoassistyouindesigningyourowntriggers.

()AuditingwithTriggers:Example()()
TriggersarecommonlyusedtosupplementthebuiltinauditingfeaturesofOracleDatabase.Althoughtriggerscanbewrittento
recordinformationsimilartothatrecordedbythe AUDITstatement,triggersshouldbeusedonlywhenmoredetailedaudit
informationisrequired.Forexample,usetriggerstoprovidevaluebasedauditingforeachrow.
Sometimes,the AUDITstatementisconsideredasecurityauditfacility,whiletriggerscanprovidefinancialauditfacility.
Whendecidingwhethertocreateatriggertoauditdatabaseactivity,considerwhatOracleDatabase'sauditingfeaturesprovide,
comparedtoauditingdefinedbytriggers,asshowninTable91.
()()Table91ComparisonofBuiltinAuditingandTriggerBasedAuditing

AuditFeature

Description

DMLandDDLAuditing

Standardauditingoptionspermit
auditingofDMLandDDLstatements
regardingalltypesofschemaobjects
andstructures.Comparatively,triggers
permitauditingofDMLstatements
enteredagainsttables,andDDL
auditingat SCHEMAor DATABASElevel.

CentralizedAuditTrail

Alldatabaseauditinformationis
recordedcentrallyandautomatically
usingtheauditingfeaturesofOracle
Database.

DeclarativeMethod

Auditingfeaturesenabledusingthe
standardOracleDatabasefeaturesare
easiertodeclareandmaintain,andless
pronetoerrors,whencomparedto
auditingfunctionsdefinedbytriggers.

AuditingOptionscanbeAudited

Anychangestoexistingauditing
optionscanalsobeauditedtoguard
againstmaliciousdatabaseactivity.

SessionandExecutiontimeAuditing

Usingthedatabaseauditingfeatures,
recordscanbegeneratedonceevery
timeanauditedstatementisentered
( BY ACCESS)oronceforeverysession
thatentersanauditedstatement( BY
SESSION).Triggerscannotauditby
sessionanauditrecordisgenerated
eachtimeatriggerauditedtableis
referenced.

AuditingofUnsuccessfulDataAccess

Databaseauditingcanbesettoaudit
whenunsuccessfuldataaccessoccurs.
However,unlessautonomous
transactionsareused,anyaudit
informationgeneratedbyatriggeris
rolledbackifthetriggeringstatementis
rolledback.Formoreinformationon
autonomoustransactions,referto
OracleDatabaseConcepts
(../../server.102/b14220/toc.htm).

SessionscanbeAudited

Connectionsanddisconnections,as
wellassessionactivity(physicalI/Os,
logicalI/Os,deadlocks,andsoon),can
berecordedusingstandarddatabase
auditing.

()()Whenusingtriggerstoprovidesophisticatedauditing, AFTERtriggersarenormallyused.Byusing AFTERtriggers,auditing

informationisrecordedafterthetriggeringstatementissubjectedtoanyapplicableintegrityconstraints,preventingcaseswherethe
auditprocessingiscarriedoutunnecessarilyforstatementsthatgenerateexceptionstointegrityconstraints.
Choosingbetween AFTERrowand AFTERstatementtriggersdependsontheinformationbeingaudited.Forexample,rowtriggers
providevaluebasedauditingforeachtablerow.Triggerscanalsorequiretheusertosupplya"reasoncode"forissuingtheaudited
SQLstatement,whichcanbeusefulinbothrowandstatementlevelauditingsituations.
()Thefollowingexampledemonstratesatriggerthatauditsmodificationstothe Emp_tabtableforeachrow.Itrequiresthata

"reasoncode"bestoredinaglobalpackagevariablebeforetheupdate.Thisshowshowtriggerscanbeusedtoprovidevalue
basedauditingandhowtousepublicpackagevariables.

Note:
Youmayneedtosetupthefollowingdatastructuresfortheexamplestowork:

CREATEORREPLACEPACKAGEAuditpackageAS
ReasonVARCHAR2(10)
PROCEDURESet_reason(ReasonVARCHAR2)
END
CREATETABLEEmp99(
EmpnoNOTNULLNUMBER(4),
EnameVARCHAR2(10),
JobVARCHAR2(9),
MgrNUMBER(4),
HiredateDATE,
SalNUMBER(7,2),
CommNUMBER(7,2),
DeptnoNUMBER(2),
BonusNUMBER,
SsnNUMBER,
Job_classificationNUMBER)
CREATETABLEAudit_employee(
OldssnNUMBER,
OldnameVARCHAR2(10),
OldjobVARCHAR2(2),
OldsalNUMBER,
NewssnNUMBER,
NewnameVARCHAR2(10),
NewjobVARCHAR2(2),
NewsalNUMBER,
ReasonVARCHAR2(10),
User1VARCHAR2(10),
SystemdateDATE)

CREATEORREPLACETRIGGERAudit_employee
AFTERINSERTORDELETEORUPDATEONEmp99
FOREACHROW
BEGIN
/*AUDITPACKAGEisapackagewithapublicpackage
variableREASON.REASONcouldbesetbythe
applicationbyacommandsuchasEXECUTE
AUDITPACKAGE.SET_REASON(reason_string).Notethata
packagevariablehasstateforthedurationofa
sessionandthateachsessionhasaseparatecopyof
allpackagevariables.*/
IFAuditpackage.ReasonISNULLTHEN
Raise_application_error(20201,'Mustspecifyreason'
||'withAUDITPACKAGE.SET_REASON(Reason_string)')
ENDIF
/*IftheprecedingconditionalevaluatestoTRUE,the
userspecifiederrornumberandmessageisraised,
thetriggerstopsexecution,andtheeffectsofthe
triggeringstatementarerolledback.Otherwise,a
newrowisinsertedintothepredefinedauditing
tablenamedAUDIT_EMPLOYEEcontainingtheexisting
andnewvaluesoftheEmp_tabtableandthereasoncode
definedbytheREASONvariableofAUDITPACKAGE.Note
thatthe"old"valuesareNULLiftriggering
statementisanINSERTandthe"new"valuesareNULL
ifthetriggeringstatementisaDELETE.*/
INSERTINTOAudit_employeeVALUES
(:old.Ssn,:old.Ename,:old.Job_classification,:old.Sal,
:new.Ssn,:new.Ename,:new.Job_classification,:new.Sal,
auditpackage.Reason,User,Sysdate)
END

Optionally,youcanalsosetthereasoncodebackto NULLifyouwantedtoforcethereasoncodetobesetforeveryupdate.The
followingsimple AFTERstatementtriggersetsthereasoncodebackto NULLafterthetriggeringstatementisrun:

CREATEORREPLACETRIGGERAudit_employee_reset
AFTERINSERTORDELETEORUPDATEONEmp_tab
BEGIN
auditpackage.set_reason(NULL)
END

()()NoticethattheprevioustwotriggersarebothfiredbythesametypeofSQLstatement.However,the AFTERrowtriggerisfired

onceforeachrowofthetableaffectedbythetriggeringstatement,whilethe AFTERstatementtriggerisfiredonlyonceafterthe
triggeringstatementexecutioniscompleted.
Thisnexttriggeralsousestriggerstodoauditing.Ittrackschangesmadetothe Emp_tabtableandstoresthisinformationin
AUDIT_TABLEand AUDIT_TABLE_VALUES.

Note:
Youmayneedtosetupthefollowingdatastructuresfortheexampletowork:
CREATETABLEAudit_table(
SeqNUMBER,
User_atVARCHAR2(10),
Time_nowDATE,
TermVARCHAR2(10),
JobVARCHAR2(10),
ProcVARCHAR2(10),
enumNUMBER)
CREATESEQUENCEAudit_seq
CREATETABLEAudit_table_values(
SeqNUMBER,
DeptNUMBER,
Dept1NUMBER,
Dept2NUMBER)

CREATEORREPLACETRIGGERAudit_emp
AFTERINSERTORUPDATEORDELETEONEmp_tab
FOREACHROW
DECLARE
Time_nowDATE
TerminalCHAR(10)
BEGIN
getcurrenttime,andtheterminaloftheuser:
Time_now:=SYSDATE
Terminal:=USERENV('TERMINAL')
recordnewemployeeprimarykey
IFINSERTINGTHEN
INSERTINTOAudit_table
VALUES(Audit_seq.NEXTVAL,User,Time_now,
Terminal,'Emp_tab','INSERT',:new.Empno)
recordprimarykeyofthedeletedrow:
ELSIFDELETINGTHEN
INSERTINTOAudit_table
VALUES(Audit_seq.NEXTVAL,User,Time_now,
Terminal,'Emp_tab','DELETE',:old.Empno)
forupdates,recordtheprimarykey
oftherowbeingupdated:
ELSE
INSERTINTOAudit_table
VALUES(audit_seq.NEXTVAL,User,Time_now,
Terminal,'Emp_tab','UPDATE',:old.Empno)
andforSALandDEPTNO,recordoldandnewvalues:
IFUPDATING('SAL')THEN
INSERTINTOAudit_table_values
VALUES(Audit_seq.CURRVAL,'SAL',
:old.Sal,:new.Sal)
ELSIFUPDATING('DEPTNO')THEN
INSERTINTOAudit_table_values
VALUES(Audit_seq.CURRVAL,'DEPTNO',
:old.Deptno,:new.DEPTNO)
ENDIF
ENDIF
END

()IntegrityConstraintsandTriggers:Examples
()()Triggersanddeclarativeintegrityconstraintscanbothbeusedtoconstraindatainput.However,triggersandintegrityconstraints

havesignificantdifferences.
Declarativeintegrityconstraintsarestatementsaboutthedatabasethatarealwaystrue.Aconstraintappliestoexistingdatainthe
tableandanystatementthatmanipulatesthetable.

SeeAlso:
Chapter6,"MaintainingDataIntegrityinApplicationDevelopment"(adfns_constraints.htm#g1023643)

Triggersconstrainwhatatransactioncando.Atriggerdoesnotapplytodataloadedbeforethedefinitionofthetriggertherefore,it
isnotknownifalldatainatableconformstotherulesestablishedbyanassociatedtrigger.
AlthoughtriggerscanbewrittentoenforcemanyofthesamerulessupportedbyOracleDatabase'sdeclarativeintegrityconstraint
features,triggersshouldonlybeusedtoenforcecomplexbusinessrulesthatcannotbedefinedusingstandardintegrityconstraints.
ThedeclarativeintegrityconstraintfeaturesprovidedwithOracleDatabaseofferthefollowingadvantageswhencomparedto
constraintsdefinedbytriggers:
Centralizedintegritychecks.Allpointsofdataaccessmustadheretotheglobalsetofrulesdefinedbytheintegrityconstraints
correspondingtoeachschemaobject.
Declarativemethod.Constraintsdefinedusingthestandardintegrityconstraintfeaturesaremucheasiertowriteandarelessprone
toerrors,whencomparedwithcomparableconstraintsdefinedbytriggers.
Whilemostaspectsofdataintegritycanbedefinedandenforcedusingdeclarativeintegrityconstraints,triggerscanbeusedto
enforcecomplexbusinessconstraintsnotdefinableusingdeclarativeintegrityconstraints.Forexample,triggerscanbeusedto
enforce:

UPDATE SET NULL,and UPDATEand DELETE SET DEFAULTreferentialactions.

Referentialintegritywhentheparentandchildtablesareondifferentnodesofadistributeddatabase.
()Complexcheckconstraintsnotdefinableusingtheexpressionsallowedina CHECKconstraint.

()ReferentialIntegrityUsingTriggers()()
Therearemanycaseswherereferentialintegritycanbeenforcedusingtriggers.Note,however,youshouldonlyusetriggerswhen
thereisnodeclarativesupportfortheactionyouareperforming.
Whenusingtriggerstomaintainreferentialintegrity,declarethe PRIMARY(or UNIQUE) KEYconstraintintheparenttable.If
referentialintegrityisbeingmaintainedbetweenaparentandchildtableinthesamedatabase,thenyoucanalsodeclarethe
foreignkeyinthechildtable,butdisableitthispreventsthecorresponding PRIMARY KEYconstraintfrombeingdropped(unless
the PRIMARY KEYconstraintisexplicitlydroppedwiththe CASCADEoption).
Tomaintainreferentialintegrityusingtriggers:

Atriggermustbedefinedforthechildtablethatguaranteesvaluesinsertedorupdatedintheforeignkeycorrespondtovaluesin
theparentkey.
Oneormoretriggersmustbedefinedfortheparenttable.Thesetriggersguaranteethedesiredreferentialaction( RESTRICT,
CASCADE,or SET NULL)forvaluesintheforeignkeywhenvaluesareupdatedordeletedintheparentkey.Noactionisrequired
forinsertsintotheparenttable(nodependentforeignkeysexist).

()()Thefollowingsectionsprovideexamplesofthetriggersnecessarytoenforcereferentialintegrity.The Emp_taband Dept_tab

tablerelationshipisusedintheseexamples.
Severalofthetriggersincludestatementsthatlockrows( SELECT... FOR UPDATE).Thisoperationisnecessarytomaintain
concurrencyastherowsarebeingprocessed.
()

ForeignKeyTriggerforChildTable
()Thefollowingtriggerguaranteesthatbeforean INSERTor UPDATEstatementaffectsaforeignkeyvalue,thecorrespondingvalue
existsintheparentkey.Themutatingtableexceptionincludedinthefollowingexampleallowsthistriggertobeusedwiththe
UPDATE_SET_DEFAULTand UPDATE_CASCADEtriggers.Thisexceptioncanberemovedifthistriggerisusedalone.

()CREATEORREPLACETRIGGEREmp_dept_check

BEFOREINSERTORUPDATEOFDeptnoONEmp_tab
FOREACHROWWHEN(new.DeptnoISNOTNULL)
Beforearowisinserted,orDEPTNOisupdatedintheEmp_tab
table,firethistriggertoverifythatthenewforeign
keyvalue(DEPTNO)ispresentintheDept_tabtable.
DECLARE
DummyINTEGERtobeusedforcursorfetch
Invalid_departmentEXCEPTION
Valid_departmentEXCEPTION
Mutating_tableEXCEPTION
PRAGMAEXCEPTION_INIT(Mutating_table,4091)
Cursorusedtoverifyparentkeyvalueexists.If
present,lockparentkey'srowsoitcan'tbe
deletedbyanothertransactionuntilthis
transactioniscommittedorrolledback.
CURSORDummy_cursor(DnNUMBER)IS
SELECTDeptnoFROMDept_tab
WHEREDeptno=Dn
FORUPDATEOFDeptno
BEGIN
OPENDummy_cursor(:new.Deptno)
FETCHDummy_cursorINTODummy
Verifyparentkey.Ifnotfound,raiseuserspecified
errornumberandmessage.Iffound,closecursor
beforeallowingtriggeringstatementtocomplete:
IFDummy_cursor%NOTFOUNDTHEN
RAISEInvalid_department
ELSE
RAISEvalid_department
ENDIF
CLOSEDummy_cursor
EXCEPTION
WHENInvalid_departmentTHEN
CLOSEDummy_cursor
Raise_application_error(20000,'InvalidDepartment'
||'Number'||TO_CHAR(:new.deptno))
WHENValid_departmentTHEN
CLOSEDummy_cursor
WHENMutating_tableTHEN
NULL
END
()

UPDATEandDELETERESTRICTTriggerforParentTable()()
Thefollowingtriggerisdefinedonthe DEPT_TABtabletoenforcethe UPDATEand DELETE RESTRICTreferentialactiononthe
primarykeyofthe DEPT_TABtable:

CREATEORREPLACETRIGGERDept_restrict
BEFOREDELETEORUPDATEOFDeptnoONDept_tab
FOREACHROW
BeforearowisdeletedfromDept_tabortheprimarykey
(DEPTNO)ofDept_tabisupdated,checkfordependent
foreignkeyvaluesinEmp_tabrollbackifanyarefound.
DECLARE
DummyINTEGERtobeusedforcursorfetch
Employees_presentEXCEPTION
employees_not_presentEXCEPTION
Cursorusedtocheckfordependentforeignkeyvalues.
CURSORDummy_cursor(DnNUMBER)IS
SELECTDeptnoFROMEmp_tabWHEREDeptno=Dn
BEGIN
OPENDummy_cursor(:old.Deptno)
FETCHDummy_cursorINTODummy
Ifdependentforeignkeyisfound,raiseuserspecified
errornumberandmessage.Ifnotfound,closecursor
beforeallowingtriggeringstatementtocomplete.
IFDummy_cursor%FOUNDTHEN
RAISEEmployees_presentdependentrowsexist
ELSE
RAISEEmployees_not_presentnodependentrows
ENDIF
CLOSEDummy_cursor
EXCEPTION
WHENEmployees_presentTHEN
CLOSEDummy_cursor
Raise_application_error(20001,'EmployeesPresentin'
||'Department'||TO_CHAR(:old.DEPTNO))
WHENEmployees_not_presentTHEN
CLOSEDummy_cursor
END

Caution:
Thistriggerdoesnotworkwithselfreferentialtables(tableswithboththeprimary/uniquekeyandtheforeignkey).Also,
thistriggerdoesnotallowtriggerstocycle(suchas,AfiresBfiresA).()

()

UPDATEandDELETESETNULLTriggersforParentTable:Example()()
Thefollowingtriggerisdefinedonthe DEPT_TABtabletoenforcethe UPDATEand DELETE SET NULLreferentialactiononthe
primarykeyofthe DEPT_TABtable:
CREATEORREPLACETRIGGERDept_set_null
AFTERDELETEORUPDATEOFDeptnoONDept_tab
FOREACHROW
BeforearowisdeletedfromDept_tabortheprimarykey
(DEPTNO)ofDept_tabisupdated,setallcorresponding
dependentforeignkeyvaluesinEmp_tabtoNULL:
BEGIN
IFUPDATINGAND:OLD.Deptno!=:NEW.DeptnoORDELETINGTHEN
UPDATEEmp_tabSETEmp_tab.Deptno=NULL
WHEREEmp_tab.Deptno=:old.Deptno
ENDIF
END
()

DELETECascadeTriggerforParentTable:Example
Thefollowingtriggeronthe DEPT_TABtableenforcesthe DELETE CASCADEreferentialactionontheprimarykeyofthe DEPT_TAB
table:

CREATEORREPLACETRIGGERDept_del_cascade
AFTERDELETEONDept_tab
FOREACHROW
BeforearowisdeletedfromDept_tab,deleteall
rowsfromtheEmp_tabtablewhoseDEPTNOisthesameas
theDEPTNObeingdeletedfromtheDept_tabtable:
BEGIN
DELETEFROMEmp_tab
WHEREEmp_tab.Deptno=:old.Deptno
END

Note:
Typically,thecodefor DELETE CASCADE iscombinedwiththecodefor UPDATE SET NULL or UPDATE SET
DEFAULT toaccountforbothupdatesanddeletes.

()

UPDATECascadeTriggerforParentTable:Example
()()Thefollowingtriggerensuresthatifadepartmentnumberisupdatedinthe Dept_tabtable,thenthischangeispropagatedto
dependentforeignkeysinthe Emp_tabtable:

Generateasequencenumbertobeusedasaflagfor
determiningifanupdatehasoccurredonacolumn:
CREATESEQUENCEUpdate_sequence
INCREMENTBY1MAXVALUE5000
CYCLE
CREATEORREPLACEPACKAGEIntegritypackageAS
UpdateseqNUMBER
ENDIntegritypackage
CREATEORREPLACEPACKAGEBODYIntegritypackageAS
ENDIntegritypackage
createflagcol:
ALTERTABLEEmp_tabADDUpdate_idNUMBER
CREATEORREPLACETRIGGERDept_cascade1BEFOREUPDATEOFDeptnoONDept_tab
DECLARE
DummyNUMBER
BeforeupdatingtheDept_tabtable(thisisastatement
trigger),generateanewsequencenumberandassign
ittothepublicvariableUPDATESEQofauserdefined
packagenamedINTEGRITYPACKAGE:
BEGIN
SELECTUpdate_sequence.NEXTVAL
INTODummy
FROMdual
Integritypackage.Updateseq:=Dummy
END
CREATEORREPLACETRIGGERDept_cascade2AFTERDELETEORUPDATE
OFDeptnoONDept_tabFOREACHROW
ForeachdepartmentnumberinDept_tabthatisupdated,
cascadetheupdatetodependentforeignkeysinthe
Emp_tabtable.Onlycascadetheupdateifthechildrow
hasnotalreadybeenupdatedbythistrigger:
BEGIN
IFUPDATINGTHEN
UPDATEEmp_tab
SETDeptno=:new.Deptno,
Update_id=Integritypackage.Updateseqfrom1st
WHEREEmp_tab.Deptno=:old.Deptno
ANDUpdate_idISNULL
/*onlyNULLifnotupdatedbythe3rdtrigger
firedbythissametriggeringstatement*/
ENDIF
IFDELETINGTHEN
BeforearowisdeletedfromDept_tab,deleteall
rowsfromtheEmp_tabtablewhoseDEPTNOisthesameas
theDEPTNObeingdeletedfromtheDept_tabtable:
DELETEFROMEmp_tab
WHEREEmp_tab.Deptno=:old.Deptno
ENDIF
END
CREATEORREPLACETRIGGERDept_cascade3AFTERUPDATEOFDeptnoONDept_tab
BEGINUPDATEEmp_tab
SETUpdate_id=NULL
WHEREUpdate_id=Integritypackage.Updateseq
END

Note:
Becausethistriggerupdatesthe Emp_tab table,the Emp_dept_check trigger,ifenabled,isalsofired.Theresulting
mutatingtableerroristrappedbythe Emp_dept_check trigger.Youshouldcarefullytestanytriggersthatrequireerror
trappingtosucceedtoensurethattheyalwaysworkproperlyinyourenvironment.

()TriggerforComplexCheckConstraints:Example()()
()Triggerscanenforceintegrityrulesotherthanreferentialintegrity.Forexample,thistriggerperformsacomplexcheckbefore

allowingthetriggeringstatementtorun.

Note:
Youmayneedtosetupthefollowingdatastructuresfortheexampletowork:
CREATETABLESalgrade(
GradeNUMBER,
LosalNUMBER,
HisalNUMBER,
Job_classificationNUMBER)

CREATEORREPLACETRIGGERSalary_check
BEFOREINSERTORUPDATEOFSal,JobONEmp99
FOREACHROW
DECLARE
MinsalNUMBER
MaxsalNUMBER
Salary_out_of_rangeEXCEPTION
BEGIN
/*Retrievetheminimumandmaximumsalaryforthe
employee'snewjobclassificationfromtheSALGRADE
tableintoMINSALandMAXSAL:*/
SELECTMinsal,MaxsalINTOMinsal,MaxsalFROMSalgrade
WHEREJob_classification=:new.Job

/*Iftheemployee'snewsalaryislessthanorgreater
thanthejobclassification'slimits,theexceptionis
raised.Theexceptionmessageisreturnedandthe
pendingINSERTorUPDATEstatementthatfiredthe
triggerisrolledback:*/
IF(:new.Sal<MinsalOR:new.Sal>Maxsal)THEN
RAISESalary_out_of_range
ENDIF
EXCEPTION
WHENSalary_out_of_rangeTHEN
Raise_application_error(20300,
'Salary'||TO_CHAR(:new.Sal)||'outofrangefor'
||'jobclassification'||:new.Job
||'foremployee'||:new.Ename)
WHENNO_DATA_FOUNDTHEN
Raise_application_error(20322,
'InvalidJobClassification'
||:new.Job_classification)
END

()ComplexSecurityAuthorizationsandTriggers():Example

Triggersarecommonlyusedtoenforcecomplexsecurityauthorizationsfortabledata.Onlyusetriggerstoenforcecomplexsecurity
authorizationsthatcannotbedefinedusingthedatabasesecurityfeaturesprovidedwithOracleDatabase.Forexample,atrigger
canprohibitupdatestosalarydataofthe Emp_tabtableduringweekends,holidays,andnonworkinghours.
()()()Whenusingatriggertoenforceacomplexsecurityauthorization,itisbesttousea BEFOREstatementtrigger.Usinga BEFORE

statementtriggerhasthesebenefits:

Thesecuritycheckisdonebeforethetriggeringstatementisallowedtorun,sothatnowastedworkisdonebyanunauthorized
statement.
Thesecuritycheckisperformedonlyonceforthetriggeringstatement,notforeachrowaffectedbythetriggeringstatement.

()Thisexampleshowsatriggerusedtoenforcesecurity.

Note:
Youmayneedtosetupthefollowingdatastructuresfortheexampletowork:
CREATETABLECompany_holidays(DayDATE)

CREATEORREPLACETRIGGEREmp_permit_changes
BEFOREINSERTORDELETEORUPDATEONEmp99
DECLARE
DummyINTEGER
Not_on_weekendsEXCEPTION
Not_on_holidaysEXCEPTION
Non_working_hoursEXCEPTION
BEGIN
/*checkforweekends:*/
IF(TO_CHAR(Sysdate,'DY')='SAT'OR
TO_CHAR(Sysdate,'DY')='SUN')THEN
RAISENot_on_weekends
ENDIF
/*checkforcompanyholidays:*/
SELECTCOUNT(*)INTODummyFROMCompany_holidays
WHERETRUNC(Day)=TRUNC(Sysdate)
/*TRUNCgetsridoftimepartsofdates:*/
IFdummy>0THEN
RAISENot_on_holidays
ENDIF
/*Checkforworkhours(8amto6pm):*/
IF(TO_CHAR(Sysdate,'HH24')<8OR
TO_CHAR(Sysdate,'HH24')>18)THEN
RAISENon_working_hours
ENDIF
EXCEPTION
WHENNot_on_weekendsTHEN
Raise_application_error(20324,'Maynotchange'
||'employeetableduringtheweekend')
WHENNot_on_holidaysTHEN
Raise_application_error(20325,'Maynotchange'
||'employeetableduringaholiday')
WHENNon_working_hoursTHEN
Raise_application_error(20326,'Maynotchange'
||'Emp_tabtableduringnonworkinghours')
END

SeeAlso:
OracleDatabaseSecurityGuide(../../network.102/b14266/apdvntro.htm#DBSEG12000)fordetailsondatabasesecurityfeatures

()TransparentEventLoggingandTriggers

Triggersareveryusefulwhenyouwanttotransparentlyperformarelatedchangeinthedatabasefollowingcertainevents.
The REORDERtriggerexampleshowsatriggerthatreorderspartsasnecessarywhencertainconditionsaremet.(Inotherwords,a
triggeringstatementisentered,andthe PARTS_ON_HANDvalueislessthanthe REORDER_POINTvalue.)

()DerivedColumnValuesandTriggers:Example()()
()()Triggerscanderivecolumnvaluesautomatically,baseduponavalueprovidedbyan INSERTor UPDATEstatement.Thistypeof

triggerisusefultoforcevaluesinspecificcolumnsthatdependonthevaluesofothercolumnsinthesamerow. BEFORErow
triggersarenecessarytocompletethistypeofoperationforthefollowingreasons:

Thedependentvaluesmustbederivedbeforethe INSERTor UPDATEoccurs,sothatthetriggeringstatementcanusethe


derivedvalues.
Thetriggermustfireforeachrowaffectedbythetriggering INSERTor UPDATEstatement.

()Thefollowingexampleillustrateshowatriggercanbeusedtoderivenewcolumnvaluesforatablewheneverarowisinsertedor

updated.

Note:
Youmayneedtosetupthefollowingdatastructuresfortheexampletowork:
ALTERTABLEEmp99ADD(
UppernameVARCHAR2(20),
SoundexnameVARCHAR2(20))

CREATEORREPLACETRIGGERDerived
BEFOREINSERTORUPDATEOFEnameONEmp99
/*BeforeupdatingtheENAMEfield,derivethevaluesfor
theUPPERNAMEandSOUNDEXNAMEfields.Usersshouldbe
restrictedfromupdatingthesefieldsdirectly:*/
FOREACHROW
BEGIN
:new.Uppername:=UPPER(:new.Ename)
:new.Soundexname:=SOUNDEX(:new.Ename)
END

()BuildingComplexUpdatableViewsUsingTriggers:Example

Viewsareanexcellentmechanismtoprovidelogicalwindowsovertabledata.However,whentheviewquerygetscomplex,the
systemimplicitlycannottranslatetheDMLontheviewintothoseontheunderlyingtables. INSTEAD OFtriggershelpsolvethis
problem.Thesetriggerscanbedefinedoverviews,andtheyfireinsteadoftheactualDML.
Consideralibrarysystemwherebooksarearrangedundertheirrespectivetitles.Thelibraryconsistsofacollectionofbooktype
objects.Thefollowingexampleexplainstheschema.
CREATEORREPLACETYPEBook_tASOBJECT
(
BooknumNUMBER,
TitleVARCHAR2(20),
AuthorVARCHAR2(20),
AvailableCHAR(1)
)
CREATEORREPLACETYPEBook_list_tASTABLEOFBook_t

Assumethatthefollowingtablesexistintherelationalschema:
TableBook_table(Booknum,Section,Title,Author,Available)

Booknum

Section

Title

Author

Available

121001

Classic

Iliad

Homer

121002

Novel

GoneWiththeWind

MitchellM

Libraryconsistsof library_table( section).


Section
Geography
Classic

Youcandefineacomplexviewoverthesetablestocreatealogicalviewofthelibrarywithsectionsandacollectionofbooksin
eachsection.
CREATEORREPLACEVIEWLibrary_viewAS
SELECTi.Section,CAST(MULTISET(
SELECTb.Booknum,b.Title,b.Author,b.Available
FROMBook_tableb
WHEREb.Section=i.Section)ASBook_list_t)BOOKLIST
FROMLibrary_tablei

Makethisviewupdatablebydefiningan INSTEAD OFtriggerovertheview.

CREATEORREPLACETRIGGERLibrary_triggerINSTEADOFINSERTONLibrary_viewFOREACHROW
BookvarBOOK_T
iINTEGER
BEGIN
INSERTINTOLibrary_tableVALUES(:NEW.Section)
FORiIN1..:NEW.Booklist.COUNTLOOP
Bookvar:=Booklist(i)
INSERTINTObook_table
VALUES(Bookvar.booknum,:NEW.Section,Bookvar.Title,Bookvar.Author,bookvar.Available)
ENDLOOP
END
/

The library_viewisanupdatableview,andany INSERTsontheviewarehandledbythetriggerthatgetsfiredautomatically.For


example:
INSERTINTOLibrary_viewVALUES('History',book_list_t(book_t(121330,'Alexander','Mirth','Y')

Similarly,youcanalsodefinetriggersonthenestedtable booklisttohandlemodificationofthenestedtableelement.

()TrackingSystemEventsUsingTriggers()()()
()

FineGrainedAccessControlUsingTriggers:Example
Systemtriggerscanbeusedtosetapplicationcontext.Applicationcontextisarelativelynewfeaturethatenhancesyourabilityto
implementfinegrainedaccesscontrol.Applicationcontextisasecuresessioncache,anditcanbeusedtostoresessionspecific
attributes.
Intheexamplethatfollows,procedure set_ctxsetstheapplicationcontextbasedontheuserprofile.Thetrigger setexpensectx
ensuresthatthecontextissetforeveryuser.

CONNECTsecdemo/secdemo
CREATEORREPLACECONTEXTExpenses_reportingUSINGSecdemo.Exprep_ctx
REM=================================================================
REMCreationofthepackagewhichimplementsthecontext:
REM=================================================================
CREATEORREPLACEPACKAGEExprep_ctxAS
PROCEDURESet_ctx
END
SHOWERRORS
CREATEORREPLACEPACKAGEBODYExprep_ctxIS
PROCEDURESet_ctxIS
EmpnumNUMBER
CountrecNUMBER
CcNUMBER
RoleVARCHAR2(20)
BEGIN
SETemp_number:
SELECTEmployee_idINTOEmpnumFROMEmployee
WHERELast_name=SYS_CONTEXT('userenv','session_user')
DBMS_SESSION.SET_CONTEXT('expenses_reporting','emp_number',Empnum)
SETROLE:
SELECTCOUNT(*)INTOCountrecFROMCost_centerWHEREManager_id=Empnum
IF(countrec>0)THEN
DBMS_SESSION.SET_CONTEXT('expenses_reporting','exp_role','MANAGER')
ELSE
DBMS_SESSION.SET_CONTEXT('expenses_reporting','exp_role','EMPLOYEE')
ENDIF
SETcc_number:
SELECTCost_center_idINTOCcFROMEmployee
WHERELast_name=SYS_CONTEXT('userenv','session_user')
DBMS_SESSION.SET_CONTEXT(expenses_reporting','cc_number',Cc)
END
END
()

CALLSyntax
CREATEORREPLACETRIGGERSecdemo.Setexpseetx
AFTERLOGONONDATABASE
CALLSecdemo.Exprep_etx.Set_otx
()
()

Respondingto()SystemEventsthroughTriggers()
Systemeventpublicationletsapplicationssubscribetodatabaseevents,justliketheysubscribetomessagesfromother
applications.Thesystemeventspublicationframeworkincludesthefollowingfeatures:

Infrastructureforpublish/subscribe,bymakingthedatabaseanactivepublisherofevents.
Integrationofdatacartridgesintheserver.Thesystemeventspublicationcanbeusedtonotifycartridgesofstatechangesinthe
server.
Integrationoffinegrainedaccesscontrolintheserver.

Bycreatingatrigger,youcanspecifyaprocedurethatrunswhenaneventoccurs.DMLeventsaresupportedontables,and
systemeventsaresupportedon DATABASEand SCHEMA.Youcanturnnotificationonandoffbyenablinganddisablingthetrigger
usingthe ALTERTRIGGERstatement.
ThisfeatureisintegratedwiththeAdvancedQueueingengine.Publish/subscribeapplicationsusethe DBMS_AQ. ENQUEUE()
procedure,andotherapplicationssuchascartridgesusecallouts.

SeeAlso:
OracleDatabaseSQLReference(../../server.102/b14200/toc.htm)
OracleStreamsAdvancedQueuingUser'sGuideandReference(../../server.102/b14257/toc.htm)fordetailsonhowto
subscribetopublishedevents

()

HowEventsArePublishedThroughTriggers
Wheneventsaredetectedbythedatabase,thetriggermechanismexecutestheactionspecifiedinthetrigger.Aspartofthisaction,
youcanusethe DBMS_AQpackagetopublishtheeventtoaqueuesothatsubscribersreceivenotifications.

Note:
Onlysystemdefineddatabaseeventscanbedetectedthisway.Youcannotdefineyourowneventconditions.

Whenaneventoccurs,thedatabasefiresalltriggersthatareenabledonthatevent,withsomeexceptions:

Ifthetriggerisactuallythetargetofthetriggeringevent,itisnotfired.Forexample,atriggerforall DROPeventsisnotfiredwhen
itisdroppeditself.
Ifatriggerhasbeenmodifiedbutnotcommittedwithinthesametransactionasthefiringevent.Forexample,recursiveDDL
withinasystemtriggermightmodifyatrigger,whichpreventsthemodifiedtriggerfrombeingfiredbyeventswithinthesame
transaction.

Youcancreatemorethanonetriggeronanobject.Whenaneventfiresmorethanonetrigger,thefiringorderisnotdefinedandso
youshouldnotrelyonthetriggersbeingfiredinaparticularorder.
()

PublicationContext
Whenaneventispublished,certainruntimecontextandattributes,asspecifiedintheparameterlist,arepassedtothecallout
procedure.Asetoffunctionscalledeventattributefunctionsareprovided.

SeeAlso:
"EventAttributeFunctions"forinformationoneventspecificattributes

Foreachsupportedsystemevent,youcanidentifyandpredefineeventspecificattributesfortheevent.Youcanchoosethe
parameterlisttobeanyoftheseattributes,alongwithothersimpleexpressions.Forcallouts,thesearepassedas INarguments.
()

ErrorHandling
Returnstatusfrompublicationcalloutfunctionsforalleventsareignored.Forexample,with SHUTDOWNevents,thedatabasecannot
doanythingwiththereturnstatus.

SeeAlso:
"ListofDatabaseEvents"fordetailsonreturnstatus

()

ExecutionModel
()Traditionally,triggersexecuteasthedefinerofthetrigger.Thetriggeractionofaneventisexecutedasthedefineroftheaction

(asthedefinerofthepackageorfunctionincallouts,orasownerofthetriggerinqueues).Becausetheownerofthetriggermust
have EXECUTEprivilegesontheunderlyingqueues,packages,orprocedure,thisbehaviorisconsistent.
()
()

EventAttributeFunctions()()()
Whenthedatabasefiresatrigger,youcanretrievecertainattributesabouttheeventthatfiredthetrigger.Youcanretrieveeach
attributewithafunctioncall.Table92describesthesystemdefinedeventattributes.

Note:
Tomaketheseattributesavailable,youmustfirstrunthe C()ATPROC.SQLscript.
Thetriggerdictionaryobjectmaintainsmetadataabouteventsthatwillbepublishedandtheircorrespondingattributes.
Inearlierreleases,thesefunctionswereaccessedthroughthe SYSpackage.Werecommendyouusethesepublic
synonymswhosenamesbeginwith ora_.

()()Table92SystemDefinedEventAttributes

Attribute
ora_client_ip_address

ora_database_name

Type
VARCHAR2

VARCHAR2(50)

Description
ReturnsIP
addressofthe
clientina
LOGONevent
whenthe
underlying
protocolis
TCP/IP

Database
name.

Example
DECLARE

v_addrVARCHAR

IF(ora_syseve

v_addr:=or
ENDIF
END

DECLARE

v_db_nameVARC
BEGIN

v_db_name:=o
END

ora_des_encrypted_password

ora_dict_obj_name

ora_dict_obj_name_list

VARCHAR2

VARCHAR(30)

BINARY_INTEGER

(name_listOUTora_name_list_t)

ora_dict_obj_ow()()()()()()ner()()()()()()

ora_dict_obj_owner_list
(owner_listOUTora_name_list_t)

VARCHAR(30)

BINARY_INTEGER

TheDES
encrypted
passwordofthe
userbeing
createdor
altered.

Nameofthe
dictionaryobject
onwhichthe
DDLoperation
occurred.

Returnthelistof
objectnamesof
objectsbeing
modifiedinthe
event.

Ownerofthe
dictionaryobject
onwhichthe
DDLoperation
occurred.

Returnsthelist
ofobjectowners
ofobjectsbeing

IF(ora_dict_obj

INSERTINTOev

VALUES(ora_
ENDIF

INSERTINTOeven

VALUES('Chang

ora_d

IF(ora_sysevent

THENnumber_mo

ora_dict_
ENDIF

INSERTINTOeven

VALUES('objec

ora_d

modifiedinthe
event.

IF(ora_sysevent

THENnumber_of

ora_dict_ob
ENDIF

ora_dict_obj_type

ora_grantee

VARCHAR(20)

BINARY_INTEGER

(user_listOUTora_name_list_t)

ora_instance_num

NUMBER

Typeofthe
dictionaryobject
onwhichthe
DDLoperation
occurred.

Returnsthe
granteesofa
granteventin
theOUT
parameter
returnsthe
numberof
granteesinthe
returnvalue.

Instance
number.

INSERTINTOeven

VALUES('This

ora_d

IF(ora_sysevent

number_of_user
ENDIF

IF(ora_instance

INSERTINTOev
ENDIF

ora_is_alter_column

BOOLEAN

(column_nameINVARCHAR2)

ora_is_creating_nested_table()

BOOLEAN

Returnstrueif
thespecified
columnis
altered.

Returnstrueif
thecurrent
eventiscreating
anestedtable

IF(ora_sysevent

ora_dict_obj

alter_column:=
ENDIF

IF(ora_sysevent

ora_dict_obj

ora_is_creat

INSERTINTOev

VALUES('An
ENDIF

ora_is_drop_column

BOOLEAN

(column_nameINVARCHAR2()()()()()()())

ora_is_servererror

BOOLEAN

Returnstrueif
thespecified
columnis
dropped.

Returns TRUEif
givenerrorison
errorstack,
FALSE

otherwise.

ora_login_user

ora_partition_pos

VARCHAR2(30)

BINARY_INTEGER

IF(ora_sysevent

ora_dict_obj

drop_column:=
ENDIF

IF(ora_is_serve

INSERTINTOeve

VALUES('Serv
ENDIF

Loginuser
name.

SELECTora_login

Inan

Retrieveora_

INSTEADOF

triggerfor
CREATETABLE,

theposition
withintheSQL
textwhereyou
couldinserta
PARTITION

clause.

FROMdual

sql_textvari

v_n:=ora_parti

v_new_stmt:=SU

||''

||''

ora_privilege_list

BINARY_INTEGER

(privilege_list
OUTora_name_list_t)

ora_revokee

BINARY_INTEGER

(user_listOUTora_name_list_t)

Returnsthelist
ofprivileges
beinggranted
bythegrantee
orthelistof
privileges
revokedfrom
therevokeesin
the OUT
parameter
returnsthe
numberof
privilegesinthe
returnvalue.

Returnsthe
revokeesofa
revokeeventin
the OUT

IF(ora_sysevent

ora_sysevent

number_of_priv

ora_privileg
ENDIF

IF(ora_sysevent

number_of_users

parameter
returnsthe
numberof
revokeesinthe
returnvalue.

ora_server_error

ora_server_error_depth

ora_server_error_msg

NUMBER

BINARY_INTEGER

VARCHAR2

(positioninbinary_integer)

ora_server_error_num_params

BINARY_INTEGER

(positioninbinary_integer)

ora_server_error_param
(positioninbinary_integer,
paraminbinary_integer)

Givenaposition
(1fortopof
stack),itreturns
theerror
numberatthat
positiononerror
stack

Returnsthe
totalnumberof
errormessages
ontheerror
stack.

Givenaposition
(1fortopof
stack),itreturns
theerror
messageatthat
positiononerror
stack

Givenaposition
( 1fortopof

INSERTINTOeven

VALUES('tops

ora_s

n:=ora_server_

Thisvalueis

INSERTINTOeven

VALUES('tops

ora_s

n:=ora_server_

stack),itreturns
thenumberof
stringsthat
havebeen
substitutedinto
theerror
messageusing
aformatlike
%s.

VARCHAR2

Givenaposition
( 1fortopof
stack)anda
parameter
number,returns
thematching
substitution
value( %s, %d,
andsoon)in
theerror
message.

Forexample,

message:"Exp

param:=ora_ser

ora_sql_txt

BINARY_INTEGER

(sql_textoutora_name_list_t)

ora_sysevent

VARCHAR2(20)

ora_with_grant_option()

BOOLEAN

Returnsthe
SQLtextofthe
triggering
statementinthe
OUTparameter.
Ifthestatement
islong,itis
brokeninto
multiplePL/SQL
tableelements.
Thefunction
returnvalue
showsthe
numberof
elementsarein
thePL/SQL
table.

Systemevent
firingthetrigger:
Eventnameis
sameasthatin
thesyntax.

Returnstrueif
theprivileges
aregrantedwith
grantoption.

sql_textora_nam

v_stmtVARCHAR2(
...

n:=ora_sql_txt

FORiIN1..nLO

v_stmt:=v_st
ENDLOOP

INSERTINTOeven

VALUES('text

||v_

INSERTINTOeven

VALUES(ora_sy

IF(ora_sysevent

ora_with_gra

INSERTINTOev

VALUES('wit
ENDIF

space_error_info

BOOLEAN

(error_numberOUTNUMBER,
error_typeOUTVARCHAR2,
object_ownerOUTVARCHAR2,
table_space_nameOUT
VARCHAR2,
object_nameOUTVARCHAR2,
sub_object_nameOUTVARCHAR2)

Returnstrueif
theerroris
relatedtoan
outofspace
condition,and
fillsinthe OUT
parameterswith
information
abouttheobject
thatcausedthe
error.

IF(space_error_

DBMS_OUTPUT.PU

'
ENDIF

()
()

()ListofDatabaseEvents
Thissectiondescribesimportantsystemeventsandclientevents.
()

SystemEvent()()()()s
Systemeventsarerelatedtoentireinstancesorschemas,notindividualtablesorrows.Triggerscreatedonstartupandshutdown
eventsmustbeassociatedwiththedatabaseinstance.Triggerscreatedonerrorandsuspendeventscanbeassociatedwitheither
thedatabaseinstanceoraparticularschema.
Table93containsalistofsystemmanagerevents.
()()Table93SystemManagerEvents

Event
STARTUP

WhenFired?

Conditions

Restrictions

Transaction

Whenthedatabaseis
opened.

None
allowed

Nodatabase
operations
allowedin
thetrigger.

Startsa
separate
transaction
andcommits
itafterfiring
thetriggers.

Return

AttributeFunctions
ora_sysevent
ora_login_user
ora_instance_num
ora_database_name

status
ignored.

SHUTDOWN

Justbeforetheserver
startstheshutdownofan
instance.

None
allowed

Thisletsthecartridge
shutdowncompletely.For
abnormalinstance
shutdown,thiseventmay
notbefired.

()DB_ROLE_CHANGE

SERVERERROR

Whenthedatabaseis
openedforthefirsttime
afterarolechange.

Nodatabase
operations
allowedin
thetrigger.
Return
status
ignored.

None
allowed

Whentheerror eno

ERRNO=

occurs.Ifnoconditionis
given,thenthiseventfires
wheneveranerroroccurs.

eno

Thetriggerdoesnotfire
on ORA1034,

Return
status
ignored.

Dependson
theerror.
Return
status
ignored.

Startsa
separate
transaction
andcommits
itafterfiring
thetriggers.

Startsa
separate
transaction
andcommits
itafterfiring
thetriggers.

Startsa
separate
transaction
andcommits
itafterfiring
thetriggers.

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_server_error
ora_is_servererror
space_error_info

ORA1403, ORA1422,
ORA1423,and
ORA4030becausethey

arenottrueerrorsorare
tooserioustocontinue
processing.Italsofailsto
fireon ORA18and
ORA20becausea
processisnotavailableto
connecttothedatabase
torecordtheerror.

()

ClientEvents()()()()
Clienteventsaretheeventsrelatedtouserlogon/logoff,DML,andDDLoperations.Forexample:
CREATEORREPLACETRIGGEROn_Logon
AFTERLOGON
ONThe_user.Schema
BEGIN
Do_Something
END

The LOGONand LOGOFFeventsallowsimpleconditionson UIDand USER.Allothereventsallowsimpleconditionsonthetypeand


nameoftheobject,aswellasfunctionslike UIDand USER.
The LOGONeventstartsaseparatetransactionandcommitsitafterfiringthetriggers.Allothereventsfirethetriggersintheexisting
usertransaction.
The LOGONand LOGOFFeventscanoperateonanyobjects.Forallotherevents,thecorrespondingtriggercannotperformanyDDL
operations,suchas DROPand ALTER,ontheobjectthatcausedtheeventtobegenerated.
TheDDLallowedinsidethesetriggersisaltering,creating,ordroppingatable,creatingatrigger,andcompileoperations.
IfaneventtriggerbecomesthetargetofaDDLoperation(suchas CREATETRIGGER),itcannotbefiredlaterduringthesame
transaction
Table94containsalistofclientevents.
()()Table94ClientEvents

Event

WhenFired?

AttributeFunctions

BEFOREALTER

Whenacatalogobjectisaltered.

ora_sysevent
ora_login_user

AFTERALTER

ora_instance_num
ora_database_name
ora_dict_obj_type
ora_dict_obj_name
ora_dict_obj_owner
ora_des_encrypted_password
(forALTERUSERevents)
ora_is_alter_column
(forALTERTABLEevents)
ora_is_drop_column
(forALTERTABLEevents)

BEFOREDROP

Whenacatalogobjectisdropped.

ora_sysevent
ora_login_user

AFTERDROP

ora_instance_num
ora_database_name
ora_dict_obj_type
ora_dict_obj_name
ora_dict_obj_owner

BEFOREANALYZE

Whenananalyzestatementisissued

ora_sysevent
ora_login_user

AFTERANALYZE

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner

BEFOREASSOCIATESTATISTICS

Whenanassociatestatisticsstatementis
issued

AFTERASSOCIATESTATISTICS

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner
ora_dict_obj_name_list
ora_dict_obj_owner_list

BEFOREAUDIT
AFTERAUDIT

Whenanauditornoauditstatementis
issued

ora_sysevent
ora_login_user
ora_instance_num

BEFORENOAUDIT

ora_database_name

AFTERNOAUDIT

BEFORECOMMENT

Whenanobjectiscommented

ora_sysevent
ora_login_user

AFTERCOMMENT

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner

BEFORECREATE

Whenacatalogobjectiscreated.

ora_sysevent
ora_login_user

AFTERCREATE

ora_instance_num
ora_database_name
ora_dict_obj_type
ora_dict_obj_name
ora_dict_obj_owner
ora_is_creating_nested_table
(forCREATETABLEevents)

WhenmostSQLDDLstatementsareissued.
Notfiredfor ALTERDATABASE,
CREATECONTROLFILE, CREATEDATABASE,

BEFOREDDL
AFTERDDL

andDDLissuedthroughthePL/SQL
procedureinterface,suchascreatingan
advancedqueue.

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner

BEFOREDISASSOCIATESTATISTICS

Whenadisassociatestatisticsstatementis
issued

AFTERDISASSOCIATESTATISTICS

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner
ora_dict_obj_name_list
ora_dict_obj_owner_list

BEFOREGRANT

Whenagrantstatementisissued

ora_sysevent
ora_login_user

AFTERGRANT

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner
ora_grantee
ora_with_grant_option
ora_privileges

BEFORELOGOFF

Atthestartofauserlogoff

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name

AFTERLOGON

Afterasuccessfullogonofauser.

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_client_ip_address

BEFORERENAME

Whenarenamestatementisissued.

ora_sysevent
ora_login_user

AFTERRENAME

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_owner
ora_dict_obj_type

BEFOREREVOKE

Whenarevokestatementisissued

ora_sysevent
ora_login_user

AFTERREVOKE

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner
ora_revokee
ora_privileges

AFTERSUSPEND

AfteraSQLstatementissuspended
becauseofanoutofspacecondition.The
triggershouldcorrecttheconditionsothe
statementcanberesumed.

ora_sysevent
ora_login_user
ora_instance_num
ora_database_name
ora_server_error
ora_is_servererror
space_error_info

BEFORETRUNCATE

Whenanobjectistruncated

ora_sysevent
ora_login_user

AFTERTRUNCATE

ora_instance_num
ora_database_name
ora_dict_obj_name
ora_dict_obj_type
ora_dict_obj_owner

ContactUs(http://www.oracle.com/us/corporate/contact/index.html)

YourPrivacyRights(http://www.oracle.com/us/legal/privacy/index.html)

Copyright2014,Oracleand/oritsaffiliates.Allrightsreserved.

LegalNotices(http://www.oracle.com/us/legal/index.html)

TermsofUse

AboutOracle(http://www.oracle.com/corporate/index.html)
(http://www.oracle.com/us/legal/terms/index.html)