共計 3374 個字符,預計需要花費 9 分鐘才能閱讀完成。
SQL Server 中怎么實時同步更新遠程數據庫,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
1. 訪問異地數據庫
在 ServerA 中創(chuàng)建指向 ServerB 的鏈接服務器,并做好賬號映射。addlinkedserver 存儲過程創(chuàng)建一個鏈接服務器,參數詳情參見官方文檔。第 1 個參數 LNK_ServerA 是自定義的名稱;第 2 參數產品名稱,如果是 SQL Server 不用提供;第 3 個參數是驅動類型;第 4 個參數是數據源,這里寫 SQL Server 服務器地址
exec sp_addlinkedserver LNK_ServerB_DatabaseB , , SQLNCLI , 172.16.8.101
配置鏈接服務器后,默認使用同一本地賬號登陸遠程數據庫,如果賬號有不同,還需要進行賬號映射。sp_addlinkedsrvlogin 參數詳情參見官方文檔。第 1 個參數同上;第 2 個參數 false 即使用后面參數提供的用戶密碼登陸;第 3 個參數 null 使所有本地賬號都可以使用后面的用戶密碼來登陸鏈接服務器,如果第 3 個參數設置為一個本地 SQL Server 登陸用戶名,那么只有這個用戶才可以使用遠程賬號登陸鏈接服務器;最后兩個是登錄遠程服務器的用戶和密碼。
exec sp_addlinkedsrvlogin LNK_ServerB_DatabaseB , false ,null, user , password
如果要刪除以上配置可以如下
exec sp_droplinkedsrvlogin LNK_ServerB_DatabaseB ,nullexec sp_dropserver LNK_ServerB_DatabaseB , droplogins
上面的配置在 SQL Server Management Studio 管理器里 Server Objects 下 LinkedServers 可以查詢到,如果一切鏈接正常,可以直接打開鏈接服務器上的庫表
值得注意的是以上兩個存儲過程不能出現在觸發(fā)器代碼中,而是事先在服務器 ServerA 中運行完成配置,否則觸發(fā)器隱式事務的要求會報錯“The procedure sys.sp_addlinkedserver cannot be executed within a transaction.”
2. 配置分布式事務
SQL Server 的觸發(fā)器是隱式使用事務的,鏈接服務器是遠程服務器,需要在本地服務器和遠程服務器之間開啟分布式事務處理,否則會報“The partner transaction manager has disabled its support for remote/network transactions”的錯誤。我在 ServerA 和 ServerB 中都開啟分布式事務協(xié)調器,并進行適當配置,以支持分布式事務。ServerA 和 ServerB 都是 Windows Server 2012 R2,其他版本服務器類似。
(1)首先在 Services.msc 中確認 Distributed Transaction Coordinator 已經開啟,其他版本的服務器不一定默認安裝,需要安裝 windows features 的方式先進行該特性的安裝。
(2)在服務器管理工具 Administrative Tools 中找到 Component Services,在 Local DTC 中屬性 Security 選項卡中配置如下,打開相關安全設置,完成后會重啟服務,也有文檔稱需要重啟服務器,但是至少 2012 R2 不用。
(3)配置防火墻,Inbound 和 Outbound 都打開
3. 數據庫字段 text, ntext 的處理
業(yè)務中表 TableA 中有一個 Content 字段是 text 類型,同步到 TableB 時需要對內容做一些替換處理。對于 text 類型是一個過時的類型,微軟官方建議用 (N)VARCHAR(MAX) 替換,可查閱這里。今后設計時可以考慮,這里我們考慮對 text 進行處理。
但是在觸發(fā)器中,inserted 和 deleted 表都是不允許對 text/ntext/image 類型進行處理的,這里我們采用一個曲線救國的辦法,從數據庫中把記錄讀取到臨時表中,然后通過 textptr 和 patindex 函數和 updatetext 命令完成字符串替換處理
if exists(select * from tempdb..sysobjects where id=object_id( tempdb..#temp_tablea)) drop table #temp_tableaselect * into #temp_tablea from TableA where ID = @IDdeclare @s varchar(200),@d varchar(200)select @s= = /_target/ ,@d= = /_replacement/ declare @p varbinary(16),@postion int,@l intselect @p=textptr(Content),@l=len(@s),@postion=patindex(% +@s+ % ,Content)+1 from #temp_tableawhile @postion 1begin updatetext #temp_tablea.Content @p @postion @l @d select @postion=patindex(% +@s+ % ,Content)+1 from #temp_tableaend
4. 執(zhí)行遠程數據庫操作
當配置鏈接服務器時,我們可以直接訪問遠程數據庫表了,如下
insert into LNK_ServerB_DatabaseB.DatabaseB.dbo.TableB ...update LNK_ServerB_DatabaseB.DatabaseB.dbo.TableB set ...
但簡陋的 SQL 編輯器往往會對語法報錯,另外為方便編程,我們希望通過 exec sp_executesql 的方式獲得更多的靈活性。其實 exec 就可以直接執(zhí)行 sql 語句,但如果有返回值就比較困難了。如下,從遠程服務器上通過 ID 查詢表 TableB 后返回 Name,sp_executesql 存儲過程可以使用 output 關鍵字定義變量為返回變量,其中 @Name output 為返回變量,@ID 則是傳入變量。
declare @sql nvarchar(500), @Name nvarchar(50),@ID nvarchar(40)set @SQL=N select @Name=Name from LNK_ServerB_DatabaseB.DatabaseB.dbo.TableB where ID=@ID exec sp_executesql @SQL,N @Name nvarchar(50) output,@ID nvarchar(40) ,@Name output,@ID
另外 exec 直接執(zhí)行 sql 語句,本質上是執(zhí)行拼接后的 sql 字符串,有時將變量拼接進字符串會困難的多(到底需要幾個單引號),而 sp_executesql 則清晰多了
declare @SQL nvarchar(500),@Name nvarchar(50),@Count int,@ID nvarchar(40)set @Name=N Cat set @Count=0set @ID=N {00000000-0000-0000-0000-000000000000} set @SQL=N update TableA set Name= +@Name+ , Count= +@Count+ where ID= +@ID+ exec(@SQL)set @SQL=N update TableA set Name=@Name,Count=@Count where ID=@ID exec sp_executesql @SQL, N @Name nvarchar(50),@Count int,@ID nvarchar(40) ,@Name,@Count,@ID
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業(yè)資訊頻道,感謝您對丸趣 TV 的支持。