【问题标题】:Rename SQL Server Schema重命名 SQL Server 架构
【发布时间】:2010-09-23 21:48:01
【问题描述】:

如何使用 SQL Server 重命名架构?

【问题讨论】:

    标签: sql sql-server sql-server-2005 schema


    【解决方案1】:

    如果您在架构中有大量对象,您可以使用类似这样的方式自动生成所有更改(它只执行表和视图,因此在运行它之前,您可能需要将其扩展为 SP, UDF 等)

    USE SandBox
    
    DECLARE @OldSchema AS varchar(255)
    DECLARE @NewSchema AS varchar(255)
    DECLARE @newLine AS varchar(2) = CHAR(13) + CHAR(10)
    
    SET @OldSchema = 'dbo'
    SET @NewSchema = 'StackOverflow'
    
    DECLARE @sql AS varchar(MAX)
    
    SET @sql = 'CREATE SCHEMA [' + @NewSchema + ']' + @newLine
    SELECT @sql = @sql + 'GO' + @newLine
    SELECT @sql = @sql + 'ALTER SCHEMA [' + @NewSchema + '] TRANSFER [' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']'
         + @newLine
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = @OldSchema
    
    SET @sql = @sql + 'DROP SCHEMA [' + @OldSchema + ']'
    
    PRINT @sql -- NOTE PRINT HAS AN 8000 byte limit - 8000 varchar/4000 nvarchar - see comments
    IF (0=1) EXEC (@sql)
    

    【讨论】:

    • 不幸的是,如果视图中包含对旧模式的引用,这将无法正常工作:(
    • @mgroves 是的,但模式中的对象不需要为同一模式中的其他对象添加前缀,因此这可能首先是一种设计味道。您可以尝试通过使用视图或 proc 代码(存储在元数据中)来寻找潜在的前缀滥用情况。通过尝试刷新所有(非确定性)SQL 模块,您可以在大规模移动后发现潜在的解析问题。
    • 如果您有很多表并且@sql 将超过varchar(max),这将不起作用。不幸的是,局部变量也不能声明为text
    • @Rian Schmits 一个模式中有多少对象? VARCHAR(MAX) 的最大存储大小为 2^31-1 字节(2,147,483,647 字节或 2GB - 1 字节)。这是一个相当大的脚本限制。
    • @Rian Schmits PRINT 有 8000 字节的限制。您需要一个自定义 PRINT SP,它将 varchar(MAX) 分解成块以将其打印出来 (blog.falafel.com/Blogs/AdamAnderson/07-02-28/…)。但是EXEC没有问题。
    【解决方案2】:

    您通过以下方式将单个对象从一个架构移动到另一个架构:

    ALTER SCHEMA NewSchema TRANSFER OldSchema.Object;
    

    【讨论】:

    • 首先你必须使用CREATE SCHEMA NewSchema
    • @littlegreen:您可以假设架构已经创建,因为用户询问如何重命名,而不是创建。
    • @Phil - 不是真的。如果其他人创建了OldSchema,并且直观的想法是重命名它而不是创建一个新的并将对象传输给它,那么就不确定用户是否知道首先创建新的模式。
    【解决方案3】:

    我结合了上面的两个代码并使用游标不受字符串变量大小的限制,单独执行命令。我假设您已经创建了新架构,并在确认一切正常后将删除旧架构。它更安全... :)

    DECLARE @OldSchema AS varchar(255)
    DECLARE @NewSchema AS varchar(255)
    
    SET @OldSchema = 'dbo'
    SET @NewSchema = 'StackOverflow'
    
    DECLARE @sql AS varchar(MAX)
    
    DECLARE @Schema AS varchar(MAX)
    DECLARE @Obj AS varchar(MAX)
    
    -- First transfer Tables and Views
    
    DECLARE CU_OBJS CURSOR FOR
        SELECT TABLE_SCHEMA, TABLE_NAME
        FROM INFORMATION_SCHEMA.TABLES
        WHERE TABLE_SCHEMA = @OldSchema
    
    OPEN CU_OBJS
    
    FETCH NEXT FROM CU_OBJS
    INTO @Schema, @Obj
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT @sql = 'ALTER SCHEMA [' + @NewSchema + '] TRANSFER [' + @OldSchema + '].[' + @Obj + ']'
        PRINT @sql
    --  EXEC (@sql)
    
        FETCH NEXT FROM CU_OBJS
        INTO @Schema, @Obj
    END
    
    CLOSE CU_OBJS
    DEALLOCATE CU_OBJS
    
    
    -- Now transfer Stored Procedures
    
    DECLARE CU_OBJS CURSOR FOR
        SELECT sys.schemas.name, sys.procedures.name
        FROM sys.procedures,sys.schemas
        WHERE sys.procedures.schema_id=sys.schemas.schema_id and sys.schemas.name = @OldSchema
    
    OPEN CU_OBJS
    
    FETCH NEXT FROM CU_OBJS
    INTO @Schema, @Obj
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT @sql = 'ALTER SCHEMA [' + @NewSchema + '] TRANSFER [' + @Schema + '].[' + @Obj + ']'
        PRINT @sql
    --  EXEC (@sql)
    
        FETCH NEXT FROM CU_OBJS
        INTO @Schema, @Obj
    END
    
    CLOSE CU_OBJS
    DEALLOCATE CU_OBJS
    

    【讨论】:

    • 我认为您在第一行 ALTER 上的参数顺序颠倒了。 @NewSchema 应该首先列出,在ALTER SCHEMA 之后,但您首先显示的是@OldSchema。否则,它工作得很好。它不会深度重命名模式(在 sp 或视图中的引用),但这些解决方案也没有。
    • @AlanMcBee 感谢您指出架构交换!让我难过了一会儿:)
    【解决方案4】:

    在 SQL server 2008 中重命名具有更多表的架构的存储过程

       IF OBJECT_ID ( 'dbo.RenameSchema', 'P' ) IS NOT NULL 
        DROP PROCEDURE dbo.RenameSchema;
       GO                         
    
    CREATE PROCEDURE dbo.RenameSchema               
    
     @OLDNAME  varchar(500),
    @NEWNAME  varchar(500)
    
    AS            
         /*check for oldschema exist or not */
         IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name =  @OLDNAME)
    
            BEGIN
    
                RETURN
    
            END
    
           /* Create the schema with new name */
          IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = @NEWNAME)
    
          BEGIN
    
              EXECUTE( 'CREATE SCHEMA ' + @NEWNAME );
    
           END                
    
         /* get the object under the old schema and transfer those objects to new schema */
         DECLARE Schema_Cursor CURSOR FOR
    
        SELECT ' ALTER SCHEMA ' + @NEWNAME + ' TRANSFER '+ SCHEMA_NAME(SCHEMA_ID)+'.'+ name  
        as ALTSQL from sys.objects WHERE type IN ('U','V','P','Fn') AND 
        SCHEMA_NAME(SCHEMA_ID) = @OLDNAME;
    
       OPEN Schema_Cursor;          
    
      DECLARE @SQL varchar(500)         
    
       FETCH NEXT FROM Schema_Cursor INTO @SQL;
    
       WHILE @@FETCH_STATUS = 0
        BEGIN
        exec (@SQL) 
        FETCH NEXT FROM Schema_Cursor INTO @SQL;
       END;
    
       CLOSE Schema_Cursor;
    
       DEALLOCATE Schema_Cursor;
    
       /* drop the old schema which should be the user schema */
       IF @OLDNAME <> 'dbo' and  @OLDNAME <> 'guest'
       BEGIN
        EXECUTE ('DROP SCHEMA ' + @OLDNAME) 
        END
       GO
    

    执行重命名架构的过程: 例子:

        EXECUTE RenameSchema 'oldname','newname'
        EXECUTE RenameSchema 'dbo','guest'  
    

    【讨论】:

      【解决方案5】:

      办理手续

      USE DatabaseName
      
      DECLARE @OldSchema AS varchar(255)
      DECLARE @NewSchema AS varchar(255)
      
      SET @OldSchema = 'ComputerLearn'
      SET @NewSchema = 'Basic'
      
      DECLARE @sql AS varchar(MAX)
      
      SET @sql = 'CREATE SCHEMA [' + @NewSchema + ']' + CHAR(13) + CHAR(10)
      
      SELECT @sql = @sql + 'ALTER SCHEMA [' + @NewSchema + '] TRANSFER [' + sys.schemas.name + '].[' + sys.procedures.name + ']'
           + CHAR(13) + CHAR(10)
      FROM sys.procedures,sys.schemas
      WHERE sys.procedures.schema_id=sys.schemas.schema_id and sys.schemas.name = @OldSchema
      
      SET @sql = @sql + 'DROP SCHEMA [' + @OldSchema + ']'
      
      PRINT @sql
      IF (0=1) EXEC (@sql)
      

      【讨论】:

      • IF (0=1) EXEC (@sql) 它总是错误的,所以我认为需要从最后一行删除 IF 部分,否则它就像魅力一样!我投了一票。
      【解决方案6】:

      这是一个简短的版本,但效果很好。

      declare @sql varchar(8000), @table varchar(1000), @oldschema varchar(1000), @newschema   varchar(1000)
      
        set @oldschema = 'old'
        set @newschema = 'dbo'
      
       while exists(select * from sys.tables where schema_name(schema_id) = @oldschema)
      
        begin
            select @table = name from sys.tables 
            where object_id in(select min(object_id) from sys.tables where  schema_name(schema_id)  = @oldschema)
      
          set @sql = 'alter schema [' + @newschema + '] transfer [' + @oldschema + '].[' + @table + ']'
      
         exec(@sql)
       end
      

      【讨论】:

      • 谢谢!就我而言,我正在转向一个新模式,并且必须首先记住 CREATE SCHEMA [newSchema]
      【解决方案7】:

      对我有用的最简单的解决方案是:
      我只有一个架构 dbo,有两个表 PopulationByCountrySTGCountryRegionSTG

      (1) 我通过执行创建了一个新模式,

      create schema stg
      

      (2)我执行了以下命令,

      ALTER SCHEMA stg TRANSFER dbo.PopulationByCountrySTG;
      ALTER SCHEMA stg TRANSFER dbo.CountryRegionSTG;
      

      全部完成。让我知道它是否适合您。谢谢各位。

      【讨论】:

        猜你喜欢
        • 2014-06-22
        • 2017-10-22
        • 1970-01-01
        • 2011-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-21
        相关资源
        最近更新 更多