今天在項目中遇到一個比較棘手的問題,需要用到觸發(fā)器。在編寫觸發(fā)器和調(diào)試過程中遇到下列問題,在此記錄一下:
創(chuàng)新互聯(lián)公司10多年企業(yè)網(wǎng)站制作服務;為您提供網(wǎng)站建設,網(wǎng)站制作,網(wǎng)頁設計及高端網(wǎng)站定制服務,企業(yè)網(wǎng)站制作及推廣,對發(fā)電機維修等多個方面擁有多年的營銷推廣經(jīng)驗的網(wǎng)站建設公司。
由于之前寫的觸發(fā)器都能正常運行,就沒有涉及到觸發(fā)器的調(diào)試,今天發(fā)現(xiàn)觸發(fā)器沒起作用,需要調(diào)試,竟不知道在哪兒調(diào)試。在網(wǎng)上借鑒一些別人的經(jīng)驗(),記錄一下。在PL/SQL中,觸發(fā)器的調(diào)試方法如下:
1,選中要調(diào)試的觸發(fā)器,右擊,然后勾選 Add debug information,只有勾選這個按鈕后,調(diào)試才能進入到斷點。
2,選中觸發(fā)器,點擊 Edit,到Edit 界面,在要調(diào)試的行號前面單擊,或者右鍵,添加斷點。
3,在菜單的新建中選擇“測試窗口”,打開一個如下塊,在begin和end中間添加能觸發(fā)觸發(fā)器的語句
4,按F9或者點擊調(diào)試菜單中的開始菜單,進入運行調(diào)試狀態(tài)(后面的紅框是單步進入)
5,點擊運行圖標跳到觸發(fā)器中斷點位置
6,鼠標放到變量上可以顯示變量值。
7,如果有異常,就彈出相關異常信息。
調(diào)試的時候發(fā)現(xiàn)new對象的日期格式為中文,而后面又需要yyyy-mm-dd 的格式來作為查詢條件。所以就在賦值的時候轉換一下。
在select into 給變量賦值的時候,select 查詢出來的集合為空,導致報錯ORA-01403,解決方案就是將這一段用begin end 包裹起來,拋出改異常的時候給變量一個默認值。如下圖:
1.引言 本人在做一個大型的MIS系統(tǒng)(前臺用powerbuild工具 后臺用oracle數(shù)據(jù)庫)時 常碰到一些有關數(shù)據(jù)冗長性 批量刪除和動態(tài)信息方面的問題 由此發(fā)現(xiàn)數(shù)據(jù)庫觸發(fā)器簡單易用 現(xiàn)將有關開發(fā)和應用中的一些體會總結成文 供同行參考 2.觸發(fā)器的概念和類型 數(shù)據(jù)庫觸發(fā)器(database triggers)是響應插入 更新或刪除等數(shù)據(jù)庫事件而執(zhí)行的過程 它定義了當一些數(shù)據(jù)庫相關事件發(fā)生時應采取的動作 可用于管理復雜的完整性約束 或監(jiān)控對表的修改 或通知其它程序 表已發(fā)生修改 它的類型有 語句級觸發(fā)器 以及行級觸發(fā)器 前者可以在語句執(zhí)行前或執(zhí)行后被觸發(fā) 后者在每個觸發(fā)語句影響的行觸發(fā)一次 還有before和after觸發(fā)的命令 在insert update 和delete之前或之后執(zhí)行 引用新舊值進行處理 如果需通過觸發(fā)器設定插入行中的某列值 則為了訪問 新(new) 值 需使用一個觸發(fā)器before insert 使用after insert則不行 Instead of 觸發(fā)器命令 使用它告訴oracle應執(zhí)行什么操作 以上四種大類合成 種小類(略) 各種觸發(fā)器的執(zhí)行順序如下 ⑴ 如果有 最先執(zhí)行語句級before觸發(fā)器 ⑵ 每個insert delete update影響的行 ①如果有 最先執(zhí)行行級before ②執(zhí)行行的delete或update ③如果有 執(zhí)行行級after觸發(fā)器 ⑶ 如果有 執(zhí)行語句級after觸發(fā)器 3.使用數(shù)據(jù)庫觸發(fā)器管理數(shù)據(jù)冗余性 為了數(shù)據(jù)分析和制作報表的需要 用戶在數(shù)據(jù)模型中加入了冗余數(shù)據(jù) 應使用觸發(fā)器 以保證數(shù)據(jù)的完整性 冗余數(shù)據(jù)可以用規(guī)定的 for each row選項的before update觸發(fā)器進行管理 update 命令可放在觸發(fā)器中對所有需要更新的冗余數(shù)據(jù)進行更新 如客戶表和訂單表 訂單表包括客戶的訂單和客戶表的冗余信息 客戶表(customer)的表結構:客戶號(cu_no) 客戶名(cu_name) 客戶地址(cu_address) 訂單表(order)的表結構:訂單號(or_no) 客戶號(or_no) 客戶名(cu_name) 客戶地址(cu_address) 當客戶基表中的數(shù)據(jù)被更新時更新訂單中的冗余列 語法如下 create or replace trigger bj_customer before update on customer for each row begin update order set cu_no=:new cu_no cu_name=:new cu_name cu_address=:new cu_addess where cu_no=:old cu_no end; 4.用觸發(fā)器完成數(shù)據(jù)復制 如果需求非常有限 可以用數(shù)據(jù)觸發(fā)器從一個數(shù)據(jù)庫中向另一個數(shù)據(jù)庫復制數(shù)據(jù) 如果數(shù)據(jù)復制需求僅與數(shù)據(jù)的插入有關 當一條記錄插入到一個數(shù)據(jù)庫中的某個基表中時 用戶還希望把這條記錄插入到一個遠程數(shù)據(jù)庫中 需用create database link語句創(chuàng)建一條到遠程數(shù)據(jù)庫的連接 一旦創(chuàng)建了一條數(shù)據(jù)庫連接后 就可以在基表上創(chuàng)建一個after insert觸發(fā)器 以把每一條記錄插入到遠程數(shù)據(jù)庫中 ( )在腳本中創(chuàng)建數(shù)據(jù)庫連接(database link)bj_ysd_remote基表作為數(shù)據(jù)庫基表 Bj_ysd_local代表本地數(shù)據(jù)庫上的源基表 Creat database link remote(連接名) Connect to bj(帳戶) indentified by bj(密碼) Using : ; ( )復制記錄 create or replace trigger trig_ysd(觸發(fā)器名) after insert on bj_ysd_local for each row begin insert into bj_ysd_remote@dblink remote value(:new x :new x ……)/*x x 代表字段名*/ end; ( )刪除記錄 create or replace trigger trig_ysd_del after delete on bj_ysd_local for each row begin delete from bj_ysd_remote@dblink remote where x =:old x end; 5.用數(shù)據(jù)庫觸發(fā)器完成瀑布式刪除操作 在某些情況下 當要刪除一條記錄時 該記錄是與外鍵有關的另外一張基表上的記錄時 這個刪除操作必須在模型中進行傳遞 否則會出現(xiàn)大量的冗長數(shù)據(jù) 仍以cumstomer 和order基表為例 當從customer中刪除一個客戶時 order基表中所有相關記錄也應當刪除 Create or replace trigger trig_cust Before delete on customer For each row Begin Delete from order Where cu_no=old cu_no End; 6.用觸發(fā)器完成動態(tài)數(shù)據(jù)的操作 在涉及如何實現(xiàn)動態(tài)庫存的問題時 可用觸發(fā)器解決 倉庫有驗收 出庫 調(diào)撥 報廢 退料 讓售等這些數(shù)據(jù)必須與以前的庫存相加減 才能完成動態(tài)庫存操作 本文僅以驗收單觸發(fā)器為例 其它的結構雷同 它們涉及到兩個基表 bi-_ysd(驗收單) Bj_kcb(當前庫存表) 前者的表結構(rq(日期) ysdh(驗收單號) bjbm(備件編碼) yssl(驗收數(shù)量) ysdj(驗收單價)) 后者的表結構為(bjbm(備件編碼) dqkcl(當前庫存量) dqkcje(當前庫存金額))觸發(fā)器如下 create or replace trigger trig_ysd after insert or update or delete on bj_ysd for each row declare rq varchar ( );rq varchar ( ); /*限于篇幅 yssl yssl ysdj ysdj bjbm bjbm ii聲明略*/ if inserting or updating then rq :=:new rq;bjbm :=:new bjbm;yssl :=:new yssl; ysdj :=:new ysdj; select count(*) into ii from bj_dqkcb where bjbm=bjbm ; if ii= then insert into bj_dqkcb(bjbm dqkcl dqkcje) value(bjbm yssl ysdj ); else update bj_dqkcb set dqkcl=dqkcl+yssl ; dqkcje=dqkcje+yssl *ysdj ; end if end if if deleting or updating then rq :=:old rq;bjbm :=:old bjbm;yssl :=:old yssl; ysdj :=:old ysdj; update bj_dqkcb set dqkcb=dqkcl yssl ; dqkcje=dqkcje yssl *ysdj end if; end ; 7.結束語 數(shù)據(jù)庫觸發(fā)器在數(shù)據(jù)庫開發(fā) MIS開發(fā)上有很廣泛的應用 但經(jīng)驗表明 使用過多的觸發(fā)器將降低整個數(shù)據(jù)庫的性能 如果數(shù)據(jù)庫觸發(fā)器寫得不好 它會很快破壞數(shù)據(jù)庫的性能 因此 在適當?shù)臅r候使用恰當?shù)挠|發(fā)器顯得非常重要 lishixinzhi/Article/program/Oracle/201311/18819
你可以建一個異常,在出現(xiàn)某種情況的時候,進入異常,就會退出觸發(fā)器了。
trigger的觸發(fā)條件是insert or update,他跟字段名無關,所以當你2個一起執(zhí)行的時候,就會出現(xiàn)這樣的情況:update 表534的時候,觸發(fā)trigger:hjx_formtable534_inser
533也跟著update;接著觸發(fā)hjx_formtable533_update,這時又把534也update了。從此走上死循環(huán)的不歸路。。。。。。
其實可以這樣(我不知道你哪個table1,哪個table2)。table1的trigger設置為affer,那么另外一個trigger設置為before,這樣理論上應該可以同時觸發(fā)2個 trigger而不會存在循環(huán)問題,我才下班,還沒來得及試驗,不好意思
表都已經(jīng)刪除了 觸發(fā)器肯定是失效了,辦法就是把創(chuàng)建觸發(fā)器的腳本保留下來,創(chuàng)建表的時候重建觸發(fā)器即可
--禁用
alter table [tablename]
disable all trigger
--恢復
alter table [tablename]
enable all trigger
如果你想禁用數(shù)據(jù)庫中所有的觸發(fā)器,那你只能寫存儲過程實現(xiàn),找出所有的表,然后逐一禁用