禁用 RPC 时如何在远程服务器上删除具有多个前缀的永久表
Posted
技术标签:
【中文标题】禁用 RPC 时如何在远程服务器上删除具有多个前缀的永久表【英文标题】:How do you drop a permanent table that has multiple prefixes on a remote server when RPC is disabled 【发布时间】:2021-12-13 14:15:27 【问题描述】:在 SSMS v18 及更高版本中禁用 rpc 时,如何在远程服务器上删除具有多个前缀的永久表?
这是存储过程的一部分。
第一次尝试:
drop table if exists [remote_server_name].[remote_db_name].dbo.[test123]
错误信息:
对象名称“remote_server_name.remote_db_name.dbo.test123”包含的前缀数量超过了最大数量。最大值为 2。
在谷歌上搜索问题后,然后尝试以下方法;
第二次尝试:
EXECUTE [remote_server_name].[remote_db_name].[dbo].[sp_executesql] N'DROP TABLE [dbo].[test123]'
错误信息:
没有为 RPC 配置服务器“remote_server_name”。
第三次尝试:
drop table [remote_server_name].[remote_db_name].dbo.[test123]
错误信息:
对象名称“remote_server_name.remote_db_name.dbo.test123”包含的前缀数量超过了最大数量。最大值为 2。
【问题讨论】:
为什么不直接连接到其他服务器? 为什么你想通过链接服务器来做到这一点? 存储过程正在为不同的服务器重新编码,但正在删除的表还不能从“远程”服务器复制 你用什么技术来表示remote_server_name
,究竟是什么?这是 OPENROWSET、链接服务器还是其他?
您使用的是什么版本的 SQL Server?这些都是本地实例吗?是否有任何 Azure SQL 或 Azure SQL 托管实例实例?
您正在尝试远程调用一个过程并且您无法更改链接服务器以支持 RPC(代表remote procedure call)?这是链接服务器配置中的简单是/否。您可以使用参数化的服务器名称动态调用sp_executesql
,例如DECLARE @exec nvarchar(1000) = @server_name + N'.dbname.sys.sp_executesql'; EXEC @exec N'SELECT @@SERVERNAME, DB_NAME();';
【参考方案1】:
很遗憾,您的整个问题的前提是错误的因为您不能将DROP TABLE
与非本地数据库一起使用。虽然文档中没有明确说明这一事实,但可以从 DROP TABLE
的语法仅支持这三种变体这一事实中推断出来:
DROP TABLE [ IF EXISTS ] database_name.schema_name.table_name;
DROP TABLE [ IF EXISTS ] schema_name.table_name;
DROP TABLE [ IF EXISTS ] table_name;
以上都不允许使用 SQL Server 名称。
奇怪的是,文档确实明确表示您不能在 Azure SQL 中使用 4 部分名称(这对某些人来说可能暗示本地(非 Azure SQL)确实 支持 4 部分名称,但事实上这两个版本的 SQL Server 都不支持 4 部分名称,因此 DROP TABLE
不能用于删除远程表:
https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-table-transact-sql?view=sql-server-ver15
当
database_name
是当前数据库或database_name
是tempdb
并且object_name
以#
开头时,Azure SQL 数据库支持三部分名称格式 database_name.[schema_name].object_name
。 Azure SQL 数据库不支持四部分名称。
但是,如果您使用的是链接服务器启用了 RPC,那么您可以使用EXEC AT
。这种方法不适用于其他类型的远程服务器,例如OPENROWSET
,也不适用于服务器选项中的“RPC: False”。
EXEC ( 'DROP TABLE dbName.schema.tableName;' ) AT [LinkedServerName];
否则,您无法从PROCEDURE
中直接删除远程服务器中的表。
一种 hack-ish 方法可能会起作用,您可以使用 xp_cmdshell
(默认情况下也禁用)对任意 SQL Server 实例运行 sqlcmd.exe
(nee osql.exe
) - 尽管显然您需要超小心使用这种方法(您还需要可信安全 (SSPI) 工作,否则您需要在某处硬编码 DDL 特权用户的密码,这在生产系统中应避免使用)。
【讨论】:
以上是关于禁用 RPC 时如何在远程服务器上删除具有多个前缀的永久表的主要内容,如果未能解决你的问题,请参考以下文章
C ++中的远程过程调用(RPC):当端点被硬编码时,多个客户端可以监听一个服务器吗?
GWT:客户端过程和 rpc 请求总是被多次调用,具有多个线程 id