在數據庫同步中我們經常會用到DBLink方式。DBLink可以將物理上存放於網絡的多個數據庫在邏輯上當成一個單一的大數據庫。開發人員無需關心數據庫的網絡分布,就能很方便的實現從不同數據庫之間讀取數據。如何在Oracle數據庫間建立DBLink我在之前的文章已有涉及,這里就不花篇幅講解了。具體請查看Oracle建立DBLink。
本篇文章主要闡述如何解決DBLink方式無法實現Blob、Clob字段數據同步的問題。在網上已經有很多牛人給出了解決方案,在參照他們的方案解決問題的過程中,發現有些小問題並沒有解決,而且也沒有人給出一個完整的解決過程。這里我把我的解決過程記錄下來,供大家參考。
首先,我們看一下DBLink為何不能實現Blob、Clob字段的同步。我在我本機Oracle數據庫中建立了DEVD數據庫的Database Link。當我們Select沒有大字段的DEVD數據庫的表的時候,數據能查詢出來。當我們查找含有大字段的表時,系統給出如下提示:
select * from JJR_TJJR_CYZGXX@DEVDBLINKJJR_TJJR_CYZGXX表中還有Blob字段。

因為Oracle不允許LOB屬性的數據進行DBLink方式的查詢的。解決此類問題有人提出使用臨時表的形式進行中轉,然后再進行數據的同步。使用這種方法確實能夠解決問題,具體解決方案如下:
1.使用子查詢來建立臨時表,實現本地臨時表復制遠程數據庫表的數據。
Create global temporary table temp on commit preserve rows as select * from JJR_TJJR_CYZGXX@DEVDBLINK為什么要用On commit preserve rows, 我之前的 Oracle用子查詢創建臨時表的問題總結中已經提到。
通過查詢temp表,我們發現所有JJR_TJJR_CYZGXX表中的數據已經同步到temp表中。
2.在本地test表中同步臨時表temp的數據,先刪除test表中數據,然后用子查詢實現數據復制。
Insert into test select * from temp通過查詢本地test表,我們看到即使含有Blob字段的表的數據已經查詢過來。
其他解決方案:
通過臨時表能夠實現含大字段表的數據同步,我們之間使用本地表是否也能達到相同的效果呢?通過實驗我們發現直接通過本地表也是能夠實現的。
首先建立test1表,結構和JJR_TJJR_CYZGXX表結構一致。通過子查詢來實現數據復制
Insert into test1 select * from JJR_TJJR_CYZGXX@DEVDBLINK通過查詢test1表我們發現數據已經復制。
--創建臨時表: create global temporary table lob2 ( line number primary key, text clob ) on commit delete rows; --插入數據: SQL> insert into lob2 select line,text from lob1@lob_link; 499 rows created. SQL> select * from lob2 where rownum<5; LINE TEXT ---------- --------------------------------------------------------------------- 5 8 type NUMBER is NUMBER_BASE; 9 subtype FLOAT is NUMBER; -- NUMBER(126) 11 subtype "DOUBLE PRECISION" is FLOAT; SQL> commit; Commit complete. SQL> select * from lob2 where rownum<5; no rows selected --提交之后數據就被刪除了,這個是臨時表的屬性。
