【问题标题】:SQL Server Reset Identity Increment for all tablesSQL Server 重置所有表的标识增量
【发布时间】:2011-01-22 19:29:52
【问题描述】:

基本上我需要将所有表的标识增量重置为其原始值。 这里我尝试了一些代码,但是失败了。

http://pastebin.com/KSyvtK5b

链接中的实际代码:

USE World00_Character
GO

-- Create a cursor to loop through the System Ojects and get each table name
DECLARE TBL_CURSOR CURSOR
-- Declare the SQL Statement to cursor through
FOR ( SELECT Name FROM Sysobjects WHERE Type='U' )

-- Declare the @SQL Variable which will hold our dynamic sql
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = '';
-- Declare the @TblName Variable which will hold the name of the current table
DECLARE @TblName NVARCHAR(MAX);

-- Open the Cursor
OPEN TBL_CURSOR

-- Setup the Fetch While that will loop through our cursor and set @TblName
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- Do this while we are not at the end of the record set
WHILE (@@FETCH_STATUS <> -1)
BEGIN
-- Appeand this table's select count statement to our sql variable
SET @SQL = @SQL + ' ( SELECT '''+@TblName+''' AS Table_Name,COUNT(*) AS Count FROM '+@TblName+' ) UNION';

-- Delete info
EXEC('DBCC CHECKIDENT ('+@TblName+',RESEED,(SELECT IDENT_SEED('+@TblName+')))');

-- Pull the next record
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- End the Cursor Loop
END

-- Close and Clean Up the Cursor
CLOSE TBL_CURSOR
DEALLOCATE TBL_CURSOR

-- Since we were adding the UNION at the end of each part, the last query will have
-- an extra UNION. Lets  trim it off.
SET @SQL = LEFT(@SQL,LEN(@SQL)-6);

-- Lets do an Order By. You can pick between Count and Table Name by picking which
-- line to execute below.
SET @SQL = @SQL + ' ORDER BY Count';
--SET @SQL = @SQL + ' ORDER BY Table_Name';

-- Now that our Dynamic SQL statement is ready, lets execute it.
EXEC (@SQL);
GO

错误信息:

Error: Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '('.

如何修复该 SQL 或将所有表的身份重置为其原始身份?

【问题讨论】:

    标签: sql identity reset


    【解决方案1】:

    我们在工作时计划停电,不知出于什么原因,我的一些表在其身份列中增加了 1000。 我修改了此代码以创建一个选择字符串列表,以显示与当前标识相比列的当前值。 然后我将这些行复制并粘贴到另一个选择中。

        SELECT 
            Replace(CurrentValue,'FROM',','+ CAST(IDENT_CURRENT(TABLE_SCHEMA+'.'+TABLE_NAME)AS VARCHAR) + ' AS Current_Identity FROM')
        FROM 
            INFORMATION_SCHEMA.TABLES T left join (select 'UNION SELECT ''DBCC CHECKIDENT(''''['+TABLE_SCHEMA+'].'+TABLE_NAME+''''', RESEED, ''+CAST( MAX('+COLUMN_NAME+') as VARCHAR)+'')'' as DBCC_String,MAX('+COLUMN_NAME+') as CurrentValue FROM [' + TABLE_SCHEMA+'].'+TABLE_NAME as CurrentValue,TABLE_SCHEMA+'.'+TABLE_NAME as TTABLE
            from INFORMATION_SCHEMA.COLUMNS
            where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1 
            ) as TT on T.TABLE_SCHEMA+'.'+T.TABLE_NAME = TT.TTABLE
        WHERE 
            OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), 'TableHasIdentity') = 1
        AND TABLE_TYPE = 'BASE TABLE'
        ORDER BY T.TABLE_SCHEMA, T.TABLE_NAME  
    

    然后将选中的列复制到里面

        select DBCC_String,CurrentValue,Current_Identity from
        (
         *Paste Here and delete the first "UNION"*
        ) as T where CurrentValue < Current_Identity
    

    然后您可以从 Table修改你需要的表

    【讨论】:

      【解决方案2】:

      (I'm reposting my answer from this other SO page)

      也许最简单的方法(这听起来很疯狂,而且看起来代码很臭)就是像这样运行 DBCC CHECKIDENT 两次:

      -- sets all the seeds to 1
      exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED, 1)'
      
      -- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
      exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'
      

      完成。

      如果需要,您可以再次运行它以查看所有种子的设置:

      -- run it again to display what the seeds are now set to
      exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'
      

      这只是利用文档评论的一种创造性方式:

      如果表的当前标识值小于最大值 存储在标识列中的标识值,使用 标识列中的最大值。

      【讨论】:

        【解决方案3】:

        如果您的表包含数据,则使用此命令时要小心,所有新插入都会导致重复错误

        exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED,1)'
        

        为了解决你需要在此之后运行的问题

        exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED)'
        

        如果数据存在,这会将种子重置为最后一个列标识

        【讨论】:

          【解决方案4】:

          另一种使用sp_MSForEachTable并在重置前检查表是否具有标识值的方法:

          EXEC sp_MSForEachTable '
           Print ''?''
           IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1
            DBCC CHECKIDENT (''?'', RESEED, 0)
           else
            Print ''Table does not have an identity value''
          '
          

          注意:如果您希望标识值从 1 开始,则 DBCC 命令应使用 CHECKIDENT (''?'', RESEED, 0) 而不是 CHECKIDENT (''?'', RESEED, 1),如某些答案所示。引用MS SQL Server documentation:

          以下示例强制在 将 AddressType 表中的 AddressTypeID 列的值设置为 10。 因为表已有行,插入的下一行将使用 11 作为值,即为 列值加 1

          USE AdventureWorks2012;
          GO
          DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
          GO
          

          【讨论】:

          • 完美,我只加了一个`? ` 在 print 语句中,所以我知道哪个表没有身份。
          【解决方案5】:

          您是否有很多没有种子和增量为 1 的表?

          如果没有(默认情况下,所有表都有),请使用以下代码:

          exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED, 1)'
          

          MSforeachtable 是一个未记录但非常方便的存储过程,它对数据库中的所有表执行给定的命令。

          如果您需要绝对准确,请使用此语句 - 它会生成一个 SQL 语句列表,以将所有表重新设置为原始 SEED 值:

          SELECT 
              IDENT_SEED(TABLE_NAME) AS Seed,
              IDENT_INCR(TABLE_NAME) AS Increment,
              IDENT_CURRENT(TABLE_NAME) AS Current_Identity,
              TABLE_NAME,
              'DBCC CHECKIDENT(' + TABLE_NAME + ', RESEED, ' + CAST(IDENT_SEED(TABLE_NAME) AS VARCHAR(10)) + ')'
          FROM 
              INFORMATION_SCHEMA.TABLES
          WHERE 
              OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
              AND TABLE_TYPE = 'BASE TABLE'
          

          获取输出中的最后一列,然后执行这些语句,您就完成了! :-)

          (灵感来自 Pinal Dave 的 blog post

          【讨论】:

          • 好吧,我有 80 个默认种子 101 的表,然后像 50 个 10001 和另外 50 个 1。所以我尝试在 SQL 中进行循环,但会尝试使用 PHP 进行循环,这可能是更容易。
          • @DanSpd:用您最终且绝对准确的方式更新了我的答案! :-) 享受吧。
          • 非常感谢。让我的工作更轻松 :) 爱你们
          • 如果不是所有表都有标识列,您可能需要修改 MSforeachtable 调用:"exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED, 1)', @whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id AND is_identity = 1)'"
          • 这是一个很好的答案,快速简单,但最有可能将身份重置为从 2 开始,如果表中已经有行已被删除(通常情况下),那么您需要使用 0 而不是 1 作为种子值,您可以在此处找到有关此问题的更多信息 stackoverflow.com/questions/472578/…
          【解决方案6】:

          使用下面的代码,

          CREATE TABLE #tmptable
          (
              [seednvalue] int not null,
              [tablename] [nvarchar] (100) NULL
          ) 
          
          
          declare @seedvalue AS INT
          DECLARE @tablename AS VARCHAR(100)
          
          Declare #tablesIdentityCursor CURSOR
              for 
              SELECT 
              IDENT_CURRENT(TABLE_NAME)+1 AS Current_Identity,
              TABLE_NAME
              FROM INFORMATION_SCHEMA.TABLES
              WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
              AND TABLE_TYPE = 'BASE TABLE'  --AND TABLE_NAME='test11'
          
          delete from #tmptable
          Open #tablesIdentityCursor
          FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
          WHILE @@FETCH_STATUS = 0 BEGIN
          
              Insert into #tmptable Select @seedvalue , @tablename   
              DBCC CHECKIDENT (@tablename, reseed, @seedvalue) 
              FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
          END
          CLOSE #tablesIdentityCursor
          DEALLOCATE #tablesIdentityCursor
          SELECT * FROM #tmptable
          DROP TABLE #tmptable
          

          【讨论】:

            【解决方案7】:

            要只为带有标识列的表重新设置种子,您可以使用下一个脚本。 它还利用了sp_MSforeachtable,但考虑了正确的表格。

            EXEC sp_MSforeachtable '
            IF (SELECT COUNT(1) 
                FROM INFORMATION_SCHEMA.TABLES 
                WHERE TABLE_TYPE = ''BASE TABLE'' 
                AND ''[''+ TABLE_SCHEMA + ''].['' + TABLE_NAME + '']'' = ''?'' 
                AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), ''TableHasIdentity'') = 1) > 0 
            BEGIN
                DBCC CHECKIDENT (''?'', RESEED, 1)
            END'
            

            【讨论】:

              【解决方案8】:

              处理 Schema 的细微变化更好...

              SELECT 
                  IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS Seed,
                  IDENT_INCR(TABLE_SCHEMA+'.'+TABLE_NAME) AS Increment,
                  IDENT_CURRENT(TABLE_SCHEMA+'.'+TABLE_NAME) AS Current_Identity,
                  TABLE_SCHEMA+'.'+TABLE_NAME,
                  'DBCC CHECKIDENT('''+TABLE_SCHEMA+'.'+TABLE_NAME+''', RESEED, '+CAST(IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS VARCHAR(10))+')'
              FROM 
                  INFORMATION_SCHEMA.TABLES
              WHERE 
                  OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), 'TableHasIdentity') = 1
              AND TABLE_TYPE = 'BASE TABLE'
              ORDER BY TABLE_SCHEMA, TABLE_NAME   
              

              【讨论】:

                【解决方案9】:

                对 marc_s 的回答稍作调整。

                exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED)'
                

                ? 周围的那些单引号性格很重要。该语句将导致 SQL Server 自动重新计算每个表的下一个标识值。

                【讨论】:

                • 这并没有将 IDENTITY 重置为我的原始起始值。它似乎根本没有改变它。当仅使用表名作为参数运行 CHECKIDENT 时,它报告的“当前身份”编号与以前相同。指定第三个参数就可以了。我正在运行 SQL Server 2012。
                【解决方案10】:

                一个简单的方法可能是使用 sp_MSforeachtable 命令,这是一个未记录但相对广为人知的命令,可以查看您的表。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-01-07
                  • 2010-10-14
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-04-14
                  • 2022-01-08
                  • 1970-01-01
                  • 2020-05-10
                  相关资源
                  最近更新 更多