【问题标题】:Create synonym to all tables in a different database with a script使用脚本为不同数据库中的所有表创建同义词
【发布时间】:2011-04-03 22:10:18
【问题描述】:

是否有一种简单的方法可以为不同数据库中的所有表创建同义词?

谢谢

编辑: 我有许多存储过程将一些表模式硬编码到选择查询中。当我将架构复制到新服务器时,SP 失败,因为架构不存在。我对目标服务器几乎没有控制权,我不想更改所有 SP,所以我认为同义词可能是一个很好的解决方案。

【问题讨论】:

  • 不回答我的数据库设置问题。当您访问任一数据库时,连接字符串是否与数据库/目录相同?主机名/IP 和端口是否相同?
  • 如果 SP 因缺少架构而失败,为什么不创建缺少的架构?但是 SP 可以在新设置中运行 - 表存在等吗?
  • 说来话长。该开发旨在建立在零售应用程序的基础上,该应用程序使用在设置时选择的自己的自定义模式。因此,我继承的扩展使用了 SP,它引用了诸如retailProduct.table1 之类的东西。问题是这个模式从开发到生产是不同的。所以我很好奇为每个retailProduct.tablex 创建一个同义词是否更好。如果扩展数据是在单独的数据库中创建的,那将是链接服务器的确切情况。但事实并非如此。表和 SP 与零售产品集成到同一个数据库中。
  • 自定义模式会很好......如果设置迭代所有引用以保持它们同步。仍然没有得到关于设置的明确答案,但听起来链接服务器不是解决方案......

标签: sql-server synonym


【解决方案1】:

另一个数据库是在单独的服务器(或实例)上,还是该实例拥有两个数据库?

如果这是单个实例,并且两个数据库都在上面 - 使用三个名称表示法:

SELECT *
  FROM database1.dbo.table_X
  JOIN database2.dbo.table_Y ...

如果另一个数据库存在于单独的 SQL Server 实例上(您可以在一个盒子上拥有多个 SQL Server),或者该数据库存在于另一个盒子/VM 上的 SQL Server 实例上 - 创建一个Linked Server 实例.然后你使用四种名称表示法:

SELECT *
  FROM database1.dbo.table_X
  JOIN linked_server_name.database2.dbo.table_Y

【讨论】:

  • 这里不完全是场景,请看我的编辑。抱歉,我应该更明确一点。
【解决方案2】:

您可以在原始数据库上运行这样的查询,然后在新数据库上运行输出结果。

select 'create synonym syn_' + t.name + ' for [' + DB_NAME() + '].[' + s.name + '].[' + t.name + ']' 
    from sys.tables t
        inner join sys.schemas s
            on t.schema_id = s.schema_id
    where t.type = 'U'

例如,对 Master 数据库运行此命令会产生:

create synonym syn_spt_fallback_db for [master].[dbo].[spt_fallback_db]
create synonym syn_spt_fallback_dev for [master].[dbo].[spt_fallback_dev]
create synonym syn_spt_fallback_usg for [master].[dbo].[spt_fallback_usg]
create synonym syn_spt_monitor for [master].[dbo].[spt_monitor]
create synonym syn_spt_values for [master].[dbo].[spt_values]
create synonym syn_MSreplication_options for [master].[dbo].[MSreplication_options]

【讨论】:

  • 这个答案+1。 @Joe Stefanelli,你会在哪里运行这些生成的 SQL?
  • 知道了,在你想要同义词的数据库下运行它们。
【解决方案3】:

创建一个类似这样的存储过程:

CREATE PROCEDURE SynonymUpdate
   @Database nvarchar(256), -- such as 'linkedserver.database' or just 'database'
   @Schema sysname -- such as 'dbo'
AS
CREATE TABLE #Tables (
   TableID int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED,
   Table_Name sysname
)
DECLARE
   @SQL nvarchar(4000),
   @ID int
SET @SQL = N'SELECT Table_Name FROM ' + @Database + '.INFORMATION_SCHEMA.TABLES WHERE Table_Schema = @TableSchema'
INSERT #Tables EXEC sp_executesql @SQL, N'@TableSchema sysname', @Schema
SELECT @ID = MAX(TableID) FROM #Tables
WHILE @ID > 0 BEGIN
   SELECT @SQL = 'CREATE SYNONYM ' + Table_Name + ' FOR ' + @Database + '.' + @Schema + '.' + Table_Name FROM #Tables WHERE TableID = @ID
   PRINT @SQL
   --EXEC sp_executesql @SQL
   SET @ID = @ID - 1
END

然后像这样运行它:

EXEC SynonymUpdate 'Database' , 'dbo'

请注意,您必须以具有创建同义词权限的用户身份运行它。如果您希望没有这些权限的用户运行它,在 SQL 2000 中没有运气,在 SQL 2005 中您可以在其中放置一个 EXECUTE AS 子句。

【讨论】:

  • +1 表示这种 SP 方法。 @ErikE,当您再次调用它以反映新更新时,您会遇到问题。即,只要您想更改同义词,就需要使用 DROP 和 CREATE;
  • @xpt 绝对正确。 DROP 如果已经存在则需要。读者练习。
  • 为忙碌的读者添加了 drop 声明:P SELECT @SQL = 'IF EXISTS ( SELECT * FROM sys.synonyms WHERE name = ''' + Table_Name + ''' AND OBJECT_ID(base_object_name) IS NOT NULL ) DROP SYNONYM ' + Table_Name + ' CREATE SYNONYM ' + Table_Name + ' FOR ' + @Database + '.' + @Schema + '.' + Table_Name FROM #Tables WHERE TableID = @ID
  • @kuklei 看来您无论如何都想删除同义词,而不仅仅是如果 base_object_name 存在?
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多