在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]'
错误信息:
服务器'remote_server_name'未为RPC配置。
第三个尝试:
drop table [remote_server_name].[remote_db_name].dbo.[test123]
错误信息:
对象名称"remote_server_name.remote_db_name.dbo"。Test123 '包含的前缀数超过最大前缀数。最大为2。
不幸的是,你的整个问题的前提是错误的,因为你不能使用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://learn.microsoft.com/en-us/sql/t-sql/statements/drop-table-transact-sql?view=sql-server-ver15
Azure SQL数据库支持三部分名称格式database_name。当
database_name
为当前数据库或database_name
为tempdb
,object_name
以#
开头时为[schema_name].object_name
。Azure SQL数据库不支持四部分名称
但是,如果您使用的是启用RPC的链接服务器那么你可以使用EXEC AT
。此方法不适用于其他类型的远程服务器,例如OPENROWSET
,当"RPC: False">
EXEC ( 'DROP TABLE dbName.schema.tableName;' ) AT [LinkedServerName];
否则,您不能直接从PROCEDURE
内删除远程服务器中的表。
使用xp_cmdshell
(默认禁用)对任意SQL Server实例运行sqlcmd.exe
(neeosql.exe
)的黑客方法可能有效-尽管显然您需要对这种方法非常小心(您还需要可信安全(SSPI)工作,否则您将需要硬编码ddl特权用户的密码,这在生产系统中应该避免)。