oracle資料庫表部分欄位雙向同步,利用包和觸發器實現

來源:互聯網
上載者:User

需求:資料庫裡面有兩張表,結構不完全相同,需要即時同步兩張表的部分欄位

實現方案:兩張表上分別建立觸發器進行同步,但是這樣操作會有個問題,就會導致觸發器迴圈觸發。那麼就需要在觸發器進行觸發前,進行一個判斷,如果操作是由觸發器引發的,那麼就不做操作,反之,執行觸發器定義的操作。想要實現這個,我開始考慮過在觸發器a裡面暫時使觸發器b失效,但是發現alter trigger disable不合法;然後看到有人提到在表裡面新增一個欄位,用來做標識,但是這樣需要修改表結構,雖然可以達到要求,但是總覺得不是很好,所以也沒有使用;後來通過學習oracle對象,瞭解到了包的特性,所以決定採用包的方式來實現,利用包的變數來做標識。

/*操作過程中,需要分別執行‘包’,‘函數’,‘觸發器’;一次性執行會有問題操作完成後,注意檢查‘包’,‘函數’,‘觸發器’狀態是否有效*/--建立包頭create or replace package pk_check_active is   --標識是否為觸發器引發  n number :=0;
 --擷取是否我觸發器觸發標識,1為觸發器觸發 function getactive return number;
--設定狀態 procedure setactive(n1 in number);end pk_check_active;
/*這裡的/一定不能缺少*//create or replace package body pk_check_active as function getactive return number is begin return n; end getactive; procedure setactive(n1 in number) is begin n := n1; end setactive;end pk_check_active;--擷取guid的方式,採用了8-4-4-4-12的格式create or replace function Creategs_oid return varchar2 is guid varchar(64); result varchar(64);begin guid := sys_guid(); result := substr(guid,1,8)||'-'||substr(guid,9,4)||'-'|| substr(guid,13,4)||'-'||substr(guid,17,4)||'-'||substr(guid,21,12); return (result);end Creategs_oid;--觸發表tableAcreate or replace trigger tr_cs_user after insert or update or deleteon tableA for each rowbegin if pk_check_active.getactive() =1 then pk_check_active.setactive(2); return; else pk_check_active.setactive(1); end if;if inserting then insert into tableB (gs_oid,s_username,s_password) values (Creategs_oid(),:new.name,:new.pass);elsif updating then update taableB t set t.s_username=:new.name ,t.s_password=:new.pass where t.s_username=:old.name;elsif deleting then delete from tableB t where t.s_username = :old.name;end if; pk_check_active.setactive(0);end;--擷取指定列最大值+1(也是一種id的標識方法,開始沒有做成自增欄位,所以寫觸發器的時候需要自己來實現了)create or replace function GetCSUserID return numberis result number;begin select max(userid)+1 into result from tableA;return (result);end GetCSUserID;--觸發tableBcreate or replace trigger tr_bs_user after insert or update or deleteon tableB for each row begin if pk_check_active.getactive() =1 then pk_check_active.setactive(2); return; else pk_check_active.setactive(1); end if;if inserting then insert into tableA (userid,name,pass,version,useable,remark) values (GetCSUserID(),:new.s_username,:new.s_password,'SDE.DEFAULT','0','使用者自動添加'); elsif updating then update tableA t set t.name=:new.s_username, t.pass=:new.s_password where t.name=:old.s_username;elsif deleting then delete from tableA t where t.name = :old.s_username;end if; pk_check_active.setactive(0);end;

上面的代碼,涉及到了包,觸發器,函數,預存程序。通過這個小案例,可以瞭解到常用觸發器的用法,同時還有格式化guid的方法,應該對大家還是有一些用處的。這種方式,只能對同一個使用者下的表進行同步,如果是跨使用者的情況下,這種方式是無效的。

引用"由於package的全域變數在資料庫層次上並不可見,所以每個session都可以認為是一個被執行個體化了的package對象。在session層級上對全域變數執行的賦值操作並不會被其他session看到,很好地體現了資料的封裝性。"所以說,通過包的變數來控制,必須是在一個session下。按照我的理解,如果採用ado方式,那麼一個串連就算是一個session。那麼有沒有跨session的訪問的方式呢,問了一下Google,是有解決方式,不過我測試了沒成功,就不賣弄了,在參考文章裡面會提到。

 

參考內容:http://www.2cto.com/database/201203/123813.html

http://www.cnblogs.com/huyong/archive/2011/04/27/2030466.html

http://blog.chinaunix.net/uid-186431-id-84823.html

http://www.cnblogs.com/tukzer/archive/2010/12/08/1900047.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.