如何通过SQLCMD跨服务器查询ProductsA独有的产品ID?
跨服务器对比表数据的可行方案
方案1:文件中转数据(无额外权限要求)
利用SQLCMD的输出/读取文件功能,绕开跨会话变量失效的问题,步骤如下:
- 连接ServerA,把ProductsA的ID导出为带单引号的格式,方便后续构造查询
- 连接ServerB,读取文件内容并拼接成ID列表,查询仅存在于ProductsA中的ID(即不在ProductsB里的ID)
代码示例:
-- 导出ServerA的ProductsA的ID到临时文件 :CONNECT ServerA :OUT "C:\temp\ProductIDs.txt" SELECT CONCAT('''', ID, '''') AS ID FROM DatabaseA..ProductsA; GO :OUT stdout -- 恢复输出到控制台 -- 连接ServerB,读取文件并查询目标数据 :CONNECT ServerB DECLARE @IDs NVARCHAR(MAX); -- 读取文件内容并拼接成逗号分隔的字符串 SELECT @IDs = STRING_AGG(ID, ',') FROM ( SELECT REPLACE(BulkColumn, CHAR(13)+CHAR(10), '') AS ID FROM OPENROWSET(BULK 'C:\temp\ProductIDs.txt', SINGLE_CLOB) AS Data ) AS IDs; -- 动态执行查询,找出仅在ProductsA中的ID EXEC sp_executesql N' SELECT ID FROM [ServerA].DatabaseA..ProductsA WHERE ID NOT IN (' + @IDs + ') '; GO
注意:如果ServerB无法直接访问ServerA的表,可以换个逻辑——回到ServerA,用OPENROWSET访问ServerB的ProductsB表,对比本地ID是否存在。
方案2:链接服务器(需ServerA创建权限)
如果ServerA有创建链接服务器的权限,直接在ServerA上执行跨服务器查询,不用反复切换连接:
-- 仅需执行一次:在ServerA上创建到ServerB的链接服务器 EXEC sp_addlinkedserver @server = N'ServerB', @provider=N'SQLNCLI', @datasrc=N'ServerB'; -- 直接查询仅存在于ProductsA中的ID SELECT ID FROM DatabaseA..ProductsA WHERE ID NOT IN (SELECT ID FROM ServerB.DatabaseB..ProductsB); GO -- 用完可删除链接服务器(可选) EXEC sp_dropserver N'ServerB', N'droplogins'; GO
方案3:SQLCMD字符串变量传递(适合ID数量少的场景)
如果ProductsA的ID数量不多(总长度不超8191字符),可以把ID拼接成字符串变量,通过SQLCMD脚本传递:
-- 连接ServerA,生成定义变量的脚本文件 :CONNECT ServerA :OUT "C:\temp\SetIDsVar.sql" SELECT ':setvar ProductIDs ''' + STRING_AGG(ID, ''',''') + '''' FROM DatabaseA..ProductsA; GO :OUT stdout -- 加载变量定义 :r "C:\temp\SetIDsVar.sql" -- 连接ServerB执行查询 :CONNECT ServerB SELECT ID FROM [ServerA].DatabaseA..ProductsA WHERE ID NOT IN ($(ProductIDs)); GO
注意:ID数量多的话会触发变量长度限制,不建议用这个方案。
内容的提问来源于stack exchange,提问作者TheBatman
相关产品推荐
相关产品推荐

