【问题标题】:change all synonyms to another database将所有同义词更改为另一个数据库
【发布时间】:2013-10-02 08:10:44
【问题描述】:

我有生产数据库(例如,PROD1)。它与另一个数据库有很多同义词(例如,PROD2)。

我创建了PROD2_TEST(作为PROD2 的完整副本)和PROD1_TEST(作为PROD1 的完整副本)。但结果我有PROD1_TESTPROD2 的同义词,而不是PROD2_TEST

如何自动重新创建测试数据库的所有同义词?

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    根据@artm 的建议,我稍微扩展了它以包含参数以使其更通用。这是代码

    DECLARE @newDB VARCHAR(MAX) = 'newDB',  --newDB to point the synonym to
        @linkedSrv VARCHAR(MAX) = null --if the synonym points to a linked server than specify it here like '[LinkedSrv].' (including the dot in the end)
    
    SELECT  'Drop Synonym [' + SCHEMA_NAME(schema_id) + '].[' + PARSENAME(base_object_name, 1) + '];' AS dropSynonym,
            ' CREATE SYNONYM [' + SCHEMA_NAME(schema_id) + '].[' + UPPER(PARSENAME(base_object_name, 1)) + '] FOR '
            + COALESCE(@linkedSrv, '') + '[' + @newDB + '].[' + COALESCE(PARSENAME(base_object_name, 2),
                                                                         SCHEMA_NAME(SCHEMA_ID())) + '].['
            + UPPER(PARSENAME(base_object_name, 1)) + '];' AS createSynonym
    FROM    sys.synonyms`
    

    【讨论】:

      【解决方案2】:

      出于同样的原因,我不得不这样做,这就是我使用的查询。运行查询,将结果复制粘贴到新服务器 (PROD_Test) 并运行生成的查询。如果您使用它们,它会处理不同的模式名称和多个数据库:

      SELECT 'Drop Synonym [' + SCHEMA_NAME(schema_id) + '].[' + PARSENAME(base_object_name,1) + '];CREATE SYNONYM [' + 
          SCHEMA_NAME(schema_id) + '].[' + PARSENAME(base_object_name,1) + '] FOR [' + COALESCE(PARSENAME(base_object_name,3),DB_NAME(DB_ID())) + '_Test].[' 
          + COALESCE(PARSENAME(base_object_name,2),SCHEMA_NAME(SCHEMA_ID())) + '].[' + PARSENAME(base_object_name,1) + '];'
      FROM sys.synonyms
      

      【讨论】:

      • 我使用参数使它更通用一点。我在下面添加了它。感谢@artm 的建议
      【解决方案3】:

      无法更改同义词,您必须删除并创建它们。以下文章包含为一系列表创建同义词的脚本。希望您可以修改它以满足您的需要:

      Use synonyms to abstract SQL Server objects

      您可以使用sys.synonymsview 查看所有现有的同义词。在伪代码中你想要做的是:

      • 创建一个临时表来存储同义词namebase_object_name
      • 从 sys.synonyms 中选择所有不正确的同义词到临时表中
      • 删除不正确的同义词
      • 构造语句以复制同义词,但将PROD2 更改为PROD2_TEST
      • 运行该语句

      【讨论】:

        【解决方案4】:

        这是我用来将所有同义词重新映射到同一服务器上的新数据库的东西(基于 Tobsey 的建议)

        SET NOCOUNT ON;
        
        DECLARE @db_name SYSNAME
        DECLARE @schema_name SYSNAME
        DECLARE @cmd NVARCHAR(256)
        
        SET @schema_name = N'dbo'
        SET @db_name = N'[newdb]'
        
        DECLARE @schema_id INT
        
        SELECT @schema_id = schema_id
        FROM sys.schemas
        WHERE NAME = @schema_name;
        
        DECLARE @table_list TABLE (table_name SYSNAME,dest_table_name sysname,dest_schema_name sysname)
        DECLARE @table_name SYSNAME
        declare @dest_table_name sysname 
        declare @dest_schema_name sysname 
        DECLARE @prefix NVARCHAR(50)
        DECLARE @synonym SYSNAME
        DECLARE @linked_server SYSNAME
        
        SET @linked_server = N'SERVER'
        
        
        -- create a synonym for these tables (insert each table)
        INSERT INTO @table_list (table_name,dest_table_name,dest_schema_name)
        SELECT name
        ,'['+SUBSTRING(name,CHARINDEX('.',name,CHARINDEX('.',name,0)+1)+1,LEN(name)-CHARINDEX('.',name,CHARINDEX('.',name,0)+1))+']'
        ,SUBSTRING(name,CHARINDEX('.',name,0)+1,CHARINDEX('.',name,CHARINDEX('.',name,0)+1)-CHARINDEX('.',name,0)-1)
        FROM sys.synonyms
        WHERE base_object_name LIKE '![SERVER!].![olddb!]%' ESCAPE ('!')
        ORDER BY name
        
        IF EXISTS (
                SELECT *
                FROM sys.servers
                WHERE NAME = @linked_server
                )
            -- 4 part name
            SET @prefix = @linked_server + N'.' + @db_name 
        ELSE
            -- 3 part name
            SET @prefix = @db_name 
        
        SELECT TOP 1 @table_name = table_name,@dest_table_name = dest_table_name,@dest_schema_name=dest_schema_name
        FROM @table_list
        
        WHILE @table_name IS NOT NULL
        BEGIN
            -- set the schema and name for the synonym
            SET @synonym = @schema_name+ N'.' + '['+@table_name+']'
        
            -- delete the synonym if it exists
            IF EXISTS (
                    SELECT *
                    FROM sys.synonyms
                    WHERE NAME = @table_name
                        AND schema_id = @schema_id
                    )
            BEGIN
                SET @cmd = N'drop synonym ' + @synonym
                PRINT @cmd
                --EXEC sp_executesql @cmd
            END
        
            -- create the synonym
            SET @cmd = N'create synonym ' + @synonym + N' for ' + @prefix + N'.'+ @dest_schema_name + N'.'+ @dest_table_name
        
            PRINT @cmd
            --EXEC sp_executesql @cmd
            PRINT 'GO'
        
            DELETE TOP (1)
            FROM @table_list
        
            SET @table_name = NULL
        
            SELECT TOP 1 @table_name = table_name,@dest_table_name = dest_table_name,@dest_schema_name=dest_schema_name
            FROM @table_list
        END
        GO
        

        【讨论】:

        • Insert Into @table_list 在创建临时表时搞砸了。就我而言,它变成了空的
        • 看起来我对变量很懒...您是否尝试编辑 '![SERVER!].![olddb!]%' 以匹配您的环境?
        【解决方案5】:

        对@kuklei 的答案进行了更改,以修复本地名称与它们引用的对象不同的同义词。此外,允许使用临时表一次进行多次替换(请将“插入#Replacements”部分中的值替换为您要进行的替换):

        create table #Replacements
        (
             SearchString varchar(100)
            ,OldPrefix varchar(100)
            ,NewPrefix varchar(100)
        )
        
        insert into #Replacements
        values
             ('_productiondb%','[productiondb]','[not_productiondb]') -- renamed local db
            ,('_192.168.100.1_._productdb%','[192.168.100.1].[productdb]','[productdb]') -- Moved db from remote to local
            ,('_192.168.100.1_._reportdb%','[192.168.100.1].[reportdb]','[not_reportdb]') -- renamed remote db
        
        SELECT
             dropSynonym =
                  'DROP SYNONYM ['
                + SCHEMA_NAME(schema_id)
                + '].['
                + name
                + '];'
            ,createSynonym = 
                  ' CREATE SYNONYM ['
                + SCHEMA_NAME(schema_id)
                + '].['
                + name
                + '] FOR '
                + REPLACE(base_object_name,OldPrefix,NewPrefix)
            ,synonymName =
                  '['
                + SCHEMA_NAME(schema_id)
                + '].['
                + name
                + ']'
            ,oldSynonymTarget = base_object_name
            ,newPrefix
        FROM sys.synonyms s
        left join #Replacements r
            on s.base_object_name like r.SearchString
        order by
            createSynonym
        
        drop table #Replacements
        

        【讨论】:

          猜你喜欢
          • 2018-06-12
          • 1970-01-01
          • 1970-01-01
          • 2017-06-20
          • 2023-02-05
          • 2012-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多