使用同义词跨数据库共享存储过程

Posted

技术标签:

【中文标题】使用同义词跨数据库共享存储过程【英文标题】:Sharing stored procedure across database using synonyms 【发布时间】:2012-07-23 17:55:16 【问题描述】:

我有两个不同的 SQL Server 数据库(在同一台服务器上——如果有帮助的话),它们需要共享相同的存储过程逻辑。我试图实现的解决方案如下所示:

Database1
  Table: TestTable
  Synonym: sp_MyProc pointing at SharedDatabase.dbo.sp_MyProc

Database2
  Table: TestTable
  Synonym: sp_MyProc pointing at SharedDatabase.dbo.sp_MyProc

SharedDatabase
  Proc: sp_MyProc which runs queries against TestTable

我希望使用同义词,这样如果我在 Database1 的上下文中执行 sp_MyProc,它将使用 Database2.TestTable。如果我在 Database2 的上下文中执行 sp_MyProc,它将违反 Database2.TestTable。但是,当我通过任一同义词执行 sp_MyProc 时,它会忽略同义词的上下文并执行查找未找到的 TestTable 的本地副本。

有没有办法实现一个共享存储过程,通过同义词或其他机制对不同数据库中的不同表副本执行?

编辑 我应该提一下,就我而言,我希望使用大量现有的表和过程来执行此操作,因此任何需要修改过程或表本身的解决方案都不理想。

【问题讨论】:

这也是我要找的。​​span> 【参考方案1】:

类似这样的东西适用于过程的定义。请务必防止 SQL 注入,因为这是动态构建的。

CREATE PROCEDURE [dbo].dosomething 
  @databaseName sysname,
  @schema sysname,
  @tableName sysname
  as
  declare @cmd as nvarchar(max)
  set @cmd = N'select * from ' + quotename(@schema) + N'.' + quotename(@tableName)
  exec sp_executesql @cmd

然后像这样使用它:

  dosomething 'SampleDb', 'dbo', 'sampleTable'

【讨论】:

抱歉,我应该在我的问题中提到,我希望使用一组非常庞大且复杂的现有 proc 来执行此操作。因此,将 procs 更改为适应不是一种选择。但这是对一般问题的有效答案,所以 +1。【参考方案2】:

如果存储过程在 SharedDatabase 中,那么它将始终在 SharedDatabase 的上下文中运行。为了完成您试图集中代码的操作,我可能会传入一个参数来指定它来自哪个服务器,这样您就可以针对该特定的 TestTable 执行查询。基本上,您需要使用它们的完全限定名称来引用每个表 - 即 Database1.dbo.TestTable

USE SharedDatabase CREATE PROCEDURE [dbo].sp_MyProc @dbsource varchar(50) as if(@dbsource == 'DB1') begin select * from Database1.dbo.TestTable end else begin select * from Database2.dbo.TestTable end GO

另一种选择是在 SharedDatabase 中创建一个视图,该视图将称为 TestTableComposite,并带有一个额外的列来标识源数据的位置。然后将其作为参数传入,SharedDatabase 上的 SP 将始终位于该数据库的上下文中。

【讨论】:

这些都是选项,但并不理想,因为我正在尝试将大量现有的表/过程重构为该解决方案。这将需要大量更改和潜在的损坏。 那么为什么不直接从两个数据库运行存储的过程,而是从 SharedDatabase... 即发出 USE DATABASE1 exec sp_myproc OR USE DATABASE2 exec sp_myproc 这似乎不起作用。 proc 看不到 db1 或 db2 中的表,并因“找不到表”类型错误而失败。也许我误解了你的想法。你能扩展一下吗? 所以 - 我的意思是,一旦你连接到 SharedDatabase,发送命令“USE Database1” - 一旦你这样做了,它应该在 Database1 的上下文中运行一切...... 这不起作用,至少通过 SSMS。我最初明确选择连接到共享数据库,即使使用“使用数据库1”,它仍然会尝试在共享数据库中查找表。

以上是关于使用同义词跨数据库共享存储过程的主要内容,如果未能解决你的问题,请参考以下文章

我应该跨嵌套存储过程共享临时表吗?

在 SQL Server 上为 Oracle 存储过程使用同义词

oracle存储过程中,调用同义词报表和视图不存在。

oracle学习之第一个存储过程:打印Hello World

SQL SERVER 存储过程中如何使用传入的DB参数,实现跨库查询?

mysql存储过程中怎么进行跨库操作?