如何对链接服务器执行存储过程?

Ian*_*oyd 8 sql-server sql-server-2008-r2

当前,我们使用以下命令对链接服务器执行存储过程:

EXECUTE [LinkedServer].[DatabaseName].[dbo].[MyProcedure]
Run Code Online (Sandbox Code Playgroud)

例如:

EXECUTE Screwdriver.CRM.dbo.GetCustomer 619
Run Code Online (Sandbox Code Playgroud)

这很好用;通过链接服务器查询工作正常。

禁用已弃用的“远程访问”功能

显然有一个鲜为人知的,很少使用的功能,称为远程访问。微软已经很少说什么这个特性,除了在这里说:

此配置选项是不推荐使用的模糊的SQL Server到SQL Server通信功能,您可能不应该使用它。

重要

在下一版本的Microsoft SQL Server中将删除此功能。不要在新的开发工作中使用此功能,请尽快修改当前使用此功能的应用程序。请改用sp_addlinkedserver

远程访问选项仅适用于使用sp_addserver添加的服务器,为了向后兼容而包含了该选项。

从SQL Server 2000联机丛书中:

在此处输入图片说明 注意提供远程服务器支持仅是为了向后兼容。必须针对SQL Server的远程实例执行存储过程的新应用程序应改用链接服务器。

我们只添加了链接服务器,从未使用过此“远程访问”功能,也从未使用过添加服务器sp_addserver

我们都很好。对?

除了关闭远程访问之外,一切都会中断

审核员提到我们应该关闭远程访问功能:

  • 这是他们剪贴板上的安全复选框
  • 微软不推荐使用
  • 几乎没有用过
  • 而且我们不使用它

应该没事吧?

Microsoft介绍了如何关闭这个很少使用的功能:

配置远程访问服务器配置选项

EXEC sp_configure 'remote access', 0 ;  
GO  
RECONFIGURE ;  
GO
Run Code Online (Sandbox Code Playgroud)

除非我们这样做:否则一切都会陷入困境:

消息7201,级别17,状态4,过程GetCustomer,第1行

无法在远程服务器“ Screwdriver”上执行过程,因为未将SQL Server配置为进行远程访问。要求系统管理员重新配置SQL Server以允许远程访问。

比失败更糟? 

为了绝对确保我使用的是链接服务器,我:

EXECUTE sp_dropserver @server='screwdriver', @dropLogins='droplogins'

EXECUTE sp_addlinkedserver N'screwdriver', N'SQL Server'
Run Code Online (Sandbox Code Playgroud)

并重新运行我的过程调用:

EXECUTE Screwdriver.CRM.dbo.GetCustomer 619
Run Code Online (Sandbox Code Playgroud)

消息7201,级别17,状态4,过程GetCustomer,第1行
无法在远程服务器“ Screwdriver”上执行过程,因为未将SQL Server配置为进行远程访问。要求系统管理员重新配置SQL Server以允许远程访问。

比失败更糟糕!

我可以使用以下命令确认该服务器链接服务器(而不是“远程”服务器):

SELECT SrvName, IsRemote 
FROM master..sysservers
WHERE SrvName = 'Screwdriver'

Srvname      IsRemote
-----------  --------
screwdriver  0
Run Code Online (Sandbox Code Playgroud)

或使用现代对象:

SELECT Name, Is_Linked
FROM sys.servers
WHERE Name = 'Screwdriver'

Name         Is_linked
-----------  --------
screwdriver  1
Run Code Online (Sandbox Code Playgroud)

总结一下

我们现在处于以下位置:

  • 我已禁用远程访问
  • 远程访问仅适用于通过以下方式添加的服务器sp_addserver
  • 它不适用于通过以下方式添加的服务器 sp_addlinkedserver
  • 我正在访问通过添加的服务器 sp_addlinkedserver

为什么不起作用?

这使我想到了一个问题:

  • 如何对链接服务器执行存储过程?

推论:

  • 如何不对添加的(即“远程”)服务器执行存储过程?

奖金Chat不休

您使用调整的远程访问配置选项sp_configure也通过用户界面公开。SSMS UI错误地描述了该功能:

在此处输入图片说明

  • 短语:允许该服务器的远程连接
  • 它应该是:允许远程连接 该服务器。

联机丛书还错误地记录功能:

允许远程连接到该服务器

从运行SQL Server实例的远程服务器控制存储过程的执行。选中此复选框与将sp_configure远程访问选项设置为1 具有相同的作用。清除该复选框将阻止从远程服务器执行存储过程。

它应该是:

允许远程连接 从该服务器

控制存储程序到运行SQL Server实例的远程服务器的执行。选中此复选框它和设置相同的效果sp_configure的远程访问为1。清除它可以防止存储过程执行选项到远程服务器。

这是有道理的,这些天微软的年轻人不记得他们从未碰过的20年过时的功能是什么。

BOL 2000中的文档

SQL Server 2000是最后一次记录此功能。为了后代和调试目的,此处复制:

配置远程服务器

远程服务器配置允许连接到Microsoft®SQL Server™的一个实例的客户端在SQL Server的另一个实例上执行存储过程,而无需建立另一个连接。客户端连接到的服务器接受客户端请求,然后代表客户端将请求发送到远程服务器。远程服务器处理该请求,并将所有结果返回到原始服务器,原始服务器又将这些结果传递给客户端。

如果要设置服务器配置以便在另一台服务器上执行存储过程,并且没有现有的远程服务器配置,请使用链接服务器而不是远程服务器。允许对链接服务器使用存储过程和分布式查询。但是,仅允许对远程服务器使用存储过程。

在此处输入图片说明 注意 提供远程服务器支持仅是为了向后兼容。必须针对SQL Server的远程实例执行存储过程的新应用程序应改用链接服务器。

也可以看看

备用标题:禁用SQL Server远程访问会破坏存储过程。

Jer*_*ert 8

好吧,当您正确时,您就是正确的,无论是否记录在案。设置remote access0(并重新启动)会导致使用四部分语法的远程存储过程调用失败,即使所有文档都表明链接服务器不应失败。即使在最新版本的 SQL Server 2017 (RTM CU12) 上也是如此,因此这不是特定于版本的。目前尚不清楚这是否是真正的限制,或者代码是否只是有问题并根据remote access功能检查阻止它,即使它在技术上可行。

涉及四部分名称 ( SELECT * FROM server.db.scheme.table) 的查询不会失败,大概是因为这仅适用于链接服务器,并且从不涉及远程访问。

作为一种解决方法,您可以将调用更改为使用EXECUTE .. AT

EXEC ('EXECUTE CRM.dbo.GetCustomer 619') AT Screwdriver
Run Code Online (Sandbox Code Playgroud)

只要链接服务器RPC Out启用了该选项(如果sp_addlinkedserver没有特殊选项添加,它将默认启用)。

不幸的EXECUTE .. AT是,当涉及参数时不太方便,因为它只支持以下?语法:

EXEC ('EXECUTE CRM.dbo.GetCustomer @Customer=?', 619) AT Screwdriver
Run Code Online (Sandbox Code Playgroud)

参数名称在这里是可选的,但我强烈建议使用它来保持可预测性。与EXECUTE-相同- 它是可选的,但它清楚地表明我们确实在运行任意查询,而不仅仅是调用存储过程。

如果你的过程有OUTPUT参数,这个普通的就行不通;EXECUTE .. AT不够聪明。您可以OUTPUT在调用中指定,但不会复制回该值。解决方法超出了本答案的范围,但它们不会很好。

可能值得为此提出建议,因为这似乎是真正应该按照文档工作的东西(如果 Microsoft 想要永久摆脱remote access,他们无论如何都需要)。