一、創建sqlserver鏈接服務(sqlserver鏈接oracle)
首先sqlserver 鏈接oracle可以通過兩個訪問接口:
“MSDAORA” 和“OraOLEDB.Oracle”
1、“MSDAORA”訪問接口是由Microsoft OLE DB Provider for Oracle提供的,這里建議不使用此接口進行鏈接。通過該訪問接口建立的鏈接服務器在進行查詢oracle表(帶數據類型CLOB、BLOB字段)時會報這個錯誤
“鏈接服務器""的 OLE DB 訪問接口 "MSDAORA" 返回了消息 "發生了一個 Oracle 錯誤,但無法從 Oracle 中檢索錯誤信息。"。
鏈接服務器""的 OLE DB 訪問接口 "MSDAORA" 返回了消息 "數據類型不被支持。"。
消息 7321,級別 16,狀態 2,第 1 行
准備對鏈接服務器 "" 的 OLE DB 訪問接口 "MSDAORA" 執行查詢"select * from SYS_MESSAGE"時出錯。”
鏈接服務器 "LINK2ORACLE" 的 OLE DB 訪問接口 "MSDAORA" 為列提供的元數據不一致。對象 ""CMCC"."OS2_GIS_CELL"" 的列 "ISOPENED" (編譯時序號為 20)在編譯時有 130 的 "DBTYPE",但在運行時有錯。
2、“OraOLEDB.Oracle” 訪問接口是由oracle 的Oracle Probider for OLE DB 驅動提供的。它解決了兩個數據庫類型不一致的的問題。而且如果需要使用分布式事務,必須使用它來創建鏈接服務器。后文會有詳細介紹。
在創建之前,在SQLSERVER中,鏈接服務器->訪問接口->OraOLEDB.Oracle->右鍵屬性,選中 "Allow inprocess" (中文為:允許進程內)
這一步是使我們選擇的OraOLEDB.Oracle接口打開執行操作。如未設置會報如下錯誤:
“無法初始化鏈接服務器 "null" 的 OLE DB 訪問接口 "OraOLEDB.Oracle" 的數據源對象"
使用Oracle Probider for OLE DB 驅動創建sqlserver鏈接服務器的代碼:
1 --建立數據庫鏈接服務器 2 EXEC sp_addlinkedserver 3 @server =N'OraclePolice', --要創建的鏈接服務器別名 4 @srvproduct=N'Oracle', --產品名稱 5 @provider=N'OraOLEDB.Oracle', --OLE DB 驅動名稱 6 @datasrc=N'ORCL' --數據源oracle"ora10g"network"admin"tnsnames.ora查看 7 8 EXEC sp_addlinkedsrvlogin 9 'OraclePolice', --已建立的鏈接服務器名 10 'false', -- 固定 */ 11 NULL, --為每個登陸SQL SERVER的用戶使用此鏈接服務器,則寫用戶名*/ 12 'TESTDB', --帳號(oracle) 13 'TESTDB123' --密碼 14 15 exec sp_serveroption 'OraclePolice','rpc out','true' 16 exec sp_serveroption 'OraclePolice','rpc','true' 17 --這兩個是打開rpc,rpc out的,默認為False,打開后可以支持遠程更改分布式事務。(如有分布式事務操作必須要設置)
這樣我們就建好了鏈接服務器,已經可以通過它對oracle數據庫進行查詢,這里有兩種查詢方式。
1、SELECT * FROM OraclePolice..TESTDB.TABLE_TEST
(鏈接服務器別名..Oracle名.oracle表,注意使用大寫)
這種方式可以進行操作,優點是使用簡單,一目了然,而缺點是性能太差,查詢大數據量表很慢。效率太差。
2、SELECT * FROM openquery(OraclePolice,'SELECT * FROM TABLE_TEST')
經試驗,這種查詢方式速度幾乎和在Oralce中一樣快。並且我們可以將openquery() 當做表來用。例如
insert into openquery(OraclePolice,'SELECT * FROM TABLE_TEST')
values();--向oracle數據表插入數據
SELECT * FROM openquery(OraclePolice,'SELECT * FROM TABLE_TEST')
where TEST_NAME='' (TEST_NAME為TABLE_TEST表中的字段)
故推薦這種查詢方式。
二、通過sqlserver鏈接服務器調用oracle 存儲過程
在oracle里數據庫里寫了一個測試存儲過程,需要一個傳入參數和傳出參數。
下面是創建和調用這個存儲過程的代碼:
1 -- oracle 中創建存儲過程 2 create or replace procedure A_TEST_NQ 3 ( 4 namecode varchar2, 5 namevalue out varchar2 6 ) 7 is 8 c varchar2(200); 9 begin 10 c:=''; 11 select NAME_VALUE into c FROM ALINK_SERVER_TEST WHERE NAME_CODE=namecode; 12 namevalue:=c; 13 end; 14 15 -- ---------------------------------------------- 16 -- 邪惡的分割線 17 -- ---------------------------------------------- 18 19 -- sqlserver 中調用存儲過程 20 declare @namecode varchar(200)-- 傳入參數 21 declare @namevalue varchar(5000)-- 傳出參數 22 23 set @namecode='01' 24 -- 調用存儲過程 25 EXEC('begin A_TEST_PRC(?,?);end;',@namecode,@namevalue output) at OraclePolice
這里要注意傳出參數,一定要加上Output,不然會報錯。
“鏈接服務器"OraclePolice"的 OLE DB 訪問接口 "OraOLEDB.Oracle" 返回了消息 "ORA-06502: PL/SQL: 數字或值錯誤 : 字符串緩沖區太小
ORA-06512: 在 "SACON.A_TEST_NQ", line 11
ORA-06512: 在 line 1"。
消息 7215,級別 17,狀態 1,第 6 行
無法在遠程服務器 'OraclePolice' 上執行語句。”
三、通過sqlserver鏈接服務器實現分布式事務
許許多多的同行就是在這一步中躺下的,因為這一步配置繁瑣,同時和sqlserver、oracle數據庫版本,甚至是操作系統版本等都有關,驅除睡意,和我一步步來進行配置吧。
1、首先必須安裝好
Oracle Services For Microsoft Transaction Server
(版本與你的oracle版本一致)
它是ODAC中的一部分,因為oracle本身是不支持分布式事務的,通過這個驅動開放與微軟的事務服務。 我想絕大多數人配置好MSDTC並解析好名稱后仍會報“無法啟動分布式服務”就是因為這個驅動沒裝。
消息 7391,級別 16,狀態 2,第 5 行
無法執行該操作,因為鏈接服務器 "oracletest" 的 OLE DB 訪問接口 "OraOLEDB.Oracle" 無法啟動分布式事務。
2、必須用Oracle Probider for OLE DB 驅動提供的OraOLEDB.Oracle訪問接口來創建鏈接服務。(這個可能是因為microsoft提供的訪問接口並不存在oracle事務機制,所以只能通過oracle提供的訪問接口)
3、MSDTC設置。
打開"管理工具--組件服務",依次打開"組件服務--計算機",在"我的電腦"上點擊右鍵。在MSDTC選項卡中,點擊"安全配置"按鈕,在安全配置窗口中做如下設置:
-->選中"網絡DTC訪問";
-->在客戶端管理中選中"允許遠程客戶端""允許遠程管理";
-->在事務管理通訊中選"允許入站""允許出站""不要求進行驗證";
-->保證DTC登陸賬戶為:NT Authority\NetworkService ;
4、雙方啟動MSDTC服務
MSDTC服務提供分布式事務服務,如果要在數據庫中使用分布式事務,必須
在參與的雙方服務器啟動MSDTC(Distributed Transaction Coordinator)服務。
5、打開雙方135端口
MSDTC服務依賴於RPC(Remote Procedure Call (RPC))服務,RPC使用135端口,保證RPC服務啟動,如果服務器有防火牆,保證135端口不被防火牆擋住。
6、在事務開始前加入set xact_abort ON語句
對於大多數 OLE DB 提供程序(包括 SQL Server),必須將隱式或顯示事務中的數據修改語句中的 XACT_ABORT 設置為 ON。唯一不需要該選項的情況是在提供程序支持嵌套事務時。
7、服務器名解析
在創建鏈接服務器時@server或者@datasrc設置為sql server服務器名時,需要做名稱解析,就是把服務器名解析為ip地址。
在"C:\WINDOWS\system32\drivers\etc\hosts"文件中增加一條記錄:
xxx.xxx.xxx.xxx 服務器名
8、遠程服務器上的名稱解析
分布式事務的參與服務器是需要相互訪問的,發起查詢的服務器要根據機
器名或ip查找遠程服務器的,同樣遠程服務器也要查找發起服務器,遠程服務器通過發起服務器的機器名查找服務器,所以要保證遠程服務器能夠通過發起服務器的機器名訪問到發起服務器。一般的,兩個服務器在同一網段機器名能就行很好的解析,但是也不保證都能很好的解析,所以比較保險的做法是:
在遠程服務器的在"C:\WINDOWS\system32\drivers\etc\hosts"文件中增加一條記錄:
xxx.xxx.xxx.xxx 發起服務器名
通過以上的一些列操作應該差不多了,這期間的操作你會抓狂,時而崩潰,時而暴走,筆者唯一的建議就是:將試驗、探索堅持到底,因為筆者已經證實SQLSERVER通過鏈接服務器到oracle能夠使用分布式事務。
1 -- 分布式事務測試 2 set xact_abort ON 3 begin tran 4 insert into openquery(OraclePolice,'SELECT * FROM ALINK_SERVER_TEST ') values('456000','TESTtest',''); 5 6 if @@ERROR <>0 7 rollback tran; 8 else 9 commit TRAN; 10 -- 語句執行成功