在同樣是SQLserver數據庫跨庫訪問時,只需要以下方法
declare @rowcount int set @rowcount = 0 set @rowcount =(select COUNT(*) from sys.servers where name = 'ITSV2') if @rowcount <= 0 begin exec sp_addlinkedserver 'ITSV2', ' ', 'SQLOLEDB', '192.168.0.222,8989' --IP,端口號 end exec sp_addlinkedsrvlogin 'ITSV2','false',null, 'sa', 'sa1234' --數據庫鏈接賬號、密碼 --select * from [ITSV2].數據庫.dbo.表
做項目的時候遇到數據對接問題,需要從其他地方同步數據到本項目,本項目是使用sqlserver數據庫,而對方使用的是postgresql數據庫。
一、下載安裝postgresql ODBC驅動
在PostgreSql官網下載ODBC驅動,網址:https://www.postgresql.org/ftp/odbc/versions/msi/
本數據庫所在的服務器是64位,我找最新版本的64位的
下載下來為 psqlodbc_x64.msi
在網上有人下載使用的的另一個,這個是收費的,但是有免費使用期。
下載好后放在本項目數據庫所在服務器上,安裝,直接點下一步就好了,
二、ODBC添加數據源
找到控制面板--管理工具--數據源(ODBC)--系統DSN
找到postgresql-完成 ,然后輸入對方的數據庫信息,點擊測試,顯示連接成功。說明和對方的數據庫可以連接了。
三、數據庫添加dblink,連接對方postgresql,查詢數據
1、在數據庫中添加linkedserver
execute sp_addlinkedserver @server='sourceDB', --被訪問的服務器別名,可以自己定義 @srvproduct='Any', @provider='MSDASQL', @datasrc='PostgreSQL35W' --被訪問的服務器地址(IP地址,端口號\服務器名稱) --PostgreSQL35W 上面第二步設置的名稱 --創建本地用戶與遠程服務器中用戶之間的映射 execute sp_addlinkedsrvlogin @rmtsrvname='sourceDB', --被訪問的服務器別名 , @useself='false', --是否通過模擬本地登錄名或顯式提交登錄名和密碼來連接到遠程服務器 @locallogin=null, --本地登錄 @rmtuser='user01', --對方數據庫用戶名 @rmtpassword='123456' --對方數據庫密碼
2、select * from sys.servers 查到剛才添加的,說明添加成功。
--顯示的linkedserver --select * from sys.servers
--同步數據后 可以關閉連接, --刪除運行本地與遠程之間的用戶映射 --execute sys.sp_droplinkedsrvlogin @rmtsrvname='sourceDB',@locallogin=null --刪除鏈接服務器 --execute sys.sp_dropserver @server='sourceDB'
3、查詢數據
此處可能會遇到的問題:
(1)對方postgresql版本可能較低,需要查詢語句中字段、表名都需要加雙引號,如果不加會出錯,提示不存在表
錯誤信息:
鏈接服務器"sourceDB"的 OLE DB 訪問接口 "MSDASQL" 返回了消息 "ERROR: relation "lgs_purchaseorder" does not exist;
No query has been executed with that handle"。
消息 7350,級別 16,狀態 2,第 114 行
無法從鏈接服務器 "sourceDB" 的 OLE DB 訪問接口"MSDASQL"獲取列信息。
(2)報以下錯誤,一般在查找數字列的時候出現,這個是所查出的數字精度比較大,而sqlserver 查出所表示的精度沒有那么大
解決方法可以是不查數字列,或者是將該數字列轉換成字符串表達
SELECT * from openquery(sourceDB,'select "OrderNo","ItemNo","PartNo","Qty" from "LGS_PurchaseOrder" order by "OrderNo" desc limit 100') --查詢報以下錯誤
消息 7356,級別 16,狀態 1,第 112 行
鏈接服務器 "sourceDB" 的 OLE DB 訪問接口 "MSDASQL" 為列提供的元數據不一致。
對象 "select "OrderNo","ItemNo","PartNo","Qty" from "LGS_PurchaseOrder" order by "OrderNo" desc limit 100"
的列 "Qty" (編譯時序號為 4)在編譯時有 6 的 "SCALE",但在運行時有 8。
調整:將數字列調整為字符串
SELECT * from openquery(sourceDB,'select "OrderNo","ItemNo","PartNo",cast("Qty" as char(30)) from "LGS_PurchaseOrder" order by "OrderNo" desc limit 100')
結果:調整后就可以查出數據,就可以拿對方數據庫得數據做自己的業務邏輯操作了。
(3) 如何在存儲過程中用openquery加參數化查詢
一般的加寫死的參數方法為
SELECT * from openquery(sourceDB, 'select "OrderNo","ItemNo","PartNo","WindowTime","CloseTime" from "LGS_PurchaseOrder" where "WindowTime" > ''2019-12-18 16:00:00.0000000'' ');
如果需要把條件換成參數,下面這樣是不行的,會提示語法錯誤,
--DECLARE @nowdate NVARCHAR(50) --SET @nowdate = '2018-08-18 16:00:09.0000000' SELECT * from openquery(sourceDB, 'select "OrderNo","ItemNo","PartNo","WindowTime","CloseTime" from "LGS_PurchaseOrder" where "WindowTime" > '''+@nowdate+''' limit 100')
正確的解決方法是用exec執行方式,如下
DECLARE @b VARCHAR(50) DECLARE @sql varchar(500) DECLARE @nowdate NVARCHAR(50) SET @nowdate = '2019-12-18 16:00:09.0000000' SET @sql ='select * from openquery (sourceDB,''select "OrderNo","ItemNo","PartNo","WindowTime","CloseTime" from "LGS_PurchaseOrder" where "WindowTime"> '''''+@nowdate+''''''')'; EXEC(@sql)