Adding an identity to an existing column

后端 未结 19 2097
温柔的废话
温柔的废话 2020-11-21 13:16

I need to change the primary key of a table to an identity column, and there\'s already a number of rows in table.

I\'ve got a script to clean up the IDs to ensure

19条回答
  •  花落未央
    2020-11-21 13:50

    generates a script for all tables with primary key = bigint which do not have an identity set; this will return a list of generated scripts with each table;

    SET NOCOUNT ON;
    
    declare @sql table(s varchar(max), id int identity)
    
    DECLARE @table_name nvarchar(max),
            @table_schema nvarchar(max);
    
    DECLARE vendor_cursor CURSOR FOR 
    SELECT
      t.name, s.name
    FROM sys.schemas AS s
    INNER JOIN sys.tables AS t
      ON s.[schema_id] = t.[schema_id]
    WHERE EXISTS (
        SELECT
        [c].[name]
        from sys.columns [c]
        join sys.types [y] on [y].system_type_id = [c].system_type_id
        where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
    ) and NOT EXISTS 
    (
      SELECT 1 FROM sys.identity_columns
        WHERE [object_id] = t.[object_id]
    ) and exists (
        select 1 from sys.indexes as [i] 
        inner join sys.index_columns as [ic]  ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
        where object_name([ic].[object_id]) = [t].[name]
    )
    OPEN vendor_cursor
    
    FETCH NEXT FROM vendor_cursor 
    INTO @table_name, @table_schema
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
    DELETE FROM @sql
    
    declare @pkname varchar(100),
        @pkcol nvarchar(100)
    
    SELECT  top 1
            @pkname = i.name,
            @pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
    FROM    sys.indexes AS [i]
    INNER JOIN sys.index_columns AS [ic] ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
    WHERE   i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name
    
    declare @q nvarchar(max) = 'SELECT  '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'
    
    DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
    SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
    EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT
    
    insert into  @sql(s) values ('BEGIN TRANSACTION')
    insert into  @sql(s) values ('BEGIN TRY')
    
    -- create statement
    insert into  @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')
    
    -- column list
    insert into @sql(s) 
    select 
        '  ['+[c].[name]+'] ' +
        y.name + 
    
        (case when [y].[name] like '%varchar' then
        coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
        else '' end)
    
         + ' ' +
        case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
        ( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' + 
        coalesce('DEFAULT ('+(
            REPLACE(
                REPLACE(
                    LTrim(
                        RTrim(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        REPLACE(
                                            LTrim(
                                                RTrim(
                                                    REPLACE(
                                                        REPLACE(
                                                            object_definition([c].default_object_id)
                                                        ,' ','~')
                                                    ,')',' ')
                                                )
                                            )
                                        ,' ','*')
                                    ,'~',' ')
                                ,' ','~')
                            ,'(',' ')
                        )
                    )
                ,' ','*')
            ,'~',' ')
        ) +
        case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
        +
        ')','') + ','
     from sys.columns c
     JOIN sys.types y ON y.system_type_id = c.system_type_id
      where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
     order by [c].column_id
    
    
     update @sql set s=left(s,len(s)-1) where id=@@identity
    
    -- closing bracket
    insert into @sql(s) values( ')' )
    
    insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')
    
    declare @cols nvarchar(max)
    SELECT @cols = STUFF(
        (
            select ',['+c.name+']'
            from sys.columns c
            JOIN sys.types y ON y.system_type_id = c.system_type_id
            where c.[object_id] = OBJECT_ID(@table_name)
            and [y].name != 'sysname'
            and [y].name != 'timestamp'
            order by [c].column_id
            FOR XML PATH ('')
         )
        , 1, 1, '')
    
    insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
    insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
    insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')
    
    insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')
    
    
    insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')
    
    insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')
    
    if ( @pkname is not null ) begin
        insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
        insert into @sql(s)
            select '  ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
            where constraint_name = @pkname
            GROUP BY COLUMN_NAME, ordinal_position
            order by ordinal_position
    
        -- remove trailing comma
        update @sql set s=left(s,len(s)-1) where id=@@identity
        insert into @sql(s) values ('  )')
    end
    
    insert into  @sql(s) values ('--Run your Statements')
    insert into  @sql(s) values ('COMMIT TRANSACTION')
    insert into  @sql(s) values ('END TRY')
    insert into  @sql(s) values ('BEGIN CATCH')
    insert into  @sql(s) values ('        ROLLBACK TRANSACTION')
    insert into  @sql(s) values ('        DECLARE @Msg NVARCHAR(MAX)  ')
    insert into  @sql(s) values ('        SELECT @Msg=ERROR_MESSAGE() ')
    insert into  @sql(s) values ('        RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
    insert into  @sql(s) values ('END CATCH')
    
    declare @fqry nvarchar(max)
    
    -- result!
    SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))
    
    
    SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
    PRINT 'Table: '+@table_name
    EXEC sp_executeSql @fqry
    
        FETCH NEXT FROM vendor_cursor 
        INTO @table_name, @table_schema
    END 
    CLOSE vendor_cursor;
    DEALLOCATE vendor_cursor;
    

自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题