在这里,我们使用 SQL 2005 的代码。它很大,很hacky,但它可以工作(除非您有一个由其他两个主键组合而成的主键)。
如果有人可以使用 MrTelly 更快的 id 添加来重写它(这不需要为每个更新的行从游标构建 sql),那么我会将其标记为已接受的答案。(如果我没有注意到新答案,请对此表示赞同 - 然后我会注意到 :))
BEGIN TRAN
SET NOCOUNT ON;
DECLARE @newLowId INT
SET @newLowId = 1000000
DECLARE @sql VARCHAR(4000)
--**** SELECT ALL TABLES WITH IDENTITY COLUMNS ****
DECLARE tables SCROLL CURSOR
FOR
SELECT '[' + SCHEMA_NAME(schema_id) + '].[' + t.name + ']', c.name
FROM sys.identity_columns c
INNER JOIN sys.objects t
on c.object_id = t.object_id
WHERE t.type_Desc = 'USER_TABLE'
OPEN tables
DECLARE @Table VARCHAR(100)
DECLARE @IdColumn VARCHAR(100)
CREATE Table #IdTable(
id INT IDENTITY(1,1),
s CHAR(1)
)
FETCH FIRST FROM tables
INTO @Table, @IdColumn
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT('
****************** '+@Table+' ******************
')
--Reset the idtable to the 'low' id mark - remove this line if you want all records to have distinct ids across the database
DELETE FROM #IdTable
DBCC CHECKIDENT('#IdTable', RESEED, @newLowId)
--**** GENERATE COLUMN SQL (for inserts and deletes - updating identities is not allowed) ****
DECLARE tableColumns CURSOR FOR
SELECT column_name FROM information_schema.columns
WHERE '[' + table_schema + '].[' + table_name + ']' = @Table
AND column_name <> @IdColumn
OPEN tableColumns
DECLARE @columnName VARCHAR(100)
DECLARE @columns VARCHAR(4000)
SET @columns = ''
FETCH NEXT FROM tableColumns INTO @columnName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @columns = @columns + @columnName
FETCH NEXT FROM tableColumns INTO @columnName
IF @@FETCH_STATUS = 0 SET @columns = @columns + ', '
END
CLOSE tableColumns
DEALLOCATE tableColumns
--**** GENERATE FOREIGN ROW UPDATE SQL ****
DECLARE foreignkeys SCROLL CURSOR
FOR
SELECT con.name,
'[' + SCHEMA_NAME(f.schema_id) + '].[' + f.name + ']' fTable, fc.column_name ,
'[' + SCHEMA_NAME(p.schema_id) + '].[' + p.name + ']' pTable, pc.column_name
FROM sys.foreign_keys con
INNER JOIN sysforeignkeys syscon
ON con.object_id = syscon.constid
INNER JOIN sys.objects f
ON con.parent_object_id = f.object_id
INNER JOIN information_schema.columns fc
ON fc.table_schema = SCHEMA_NAME(f.schema_id)
AND fc.table_name = f.name
AND fc.ordinal_position = syscon.fkey
INNER JOIN sys.objects p
ON con.referenced_object_id = p.object_id
INNER JOIN information_schema.columns pc
ON pc.table_schema = SCHEMA_NAME(p.schema_id)
AND pc.table_name = p.name
AND pc.ordinal_position = syscon.rkey
WHERE '[' + SCHEMA_NAME(p.schema_id) + '].[' + p.name + ']' = @Table
OPEN foreignkeys
DECLARE @FKeyName VARCHAR(100)
DECLARE @FTable VARCHAR(100)
DECLARE @FColumn VARCHAR(100)
DECLARE @PTable VARCHAR(100)
DECLARE @PColumn VARCHAR(100)
--**** RE-WRITE ALL IDS IN THE TABLE ****
SET @sql='DECLARE tablerows CURSOR FOR
SELECT CAST('+@IdColumn+' AS VARCHAR) FROM '+@Table+' ORDER BY '+@IdColumn
PRINT(@sql)
exec(@sql)
OPEN tablerows
DECLARE @rowid VARCHAR(100)
DECLARE @id VARCHAR(100)
FETCH NEXT FROM tablerows INTO @rowid
WHILE @@FETCH_STATUS = 0
BEGIN
--generate new id
INSERT INTO #IdTable VALUES ('')
SELECT @id = CAST(@@IDENTITY AS VARCHAR)
IF @rowId <> @Id
BEGIN
PRINT('Modifying '+@Table+': changing '+@rowId+' to '+@id)
SET @sql='SET IDENTITY_INSERT ' + @Table + ' ON
INSERT INTO '+@Table+' ('+@IdColumn+','+@columns+') SELECT '+@id+','+@columns+' FROM '+@Table+' WHERE '+@IdColumn+'='+@rowId
--Updating all foreign rows...
FETCH FIRST FROM foreignkeys
INTO @FKeyName, @FTable, @FColumn, @PTable, @PColumn
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = @sql + '
UPDATE '+@FTable+' SET '+@FColumn+'='+@id+' WHERE '+@FColumn+' ='+@rowId
FETCH NEXT FROM foreignkeys
INTO @FKeyName, @FTable, @FColumn, @PTable, @PColumn
END
SET @sql=@sql + '
DELETE FROM '+@Table+' WHERE '+@IdColumn+'='+@rowId
PRINT(@sql)
exec(@sql)
END
FETCH NEXT FROM tablerows INTO @rowid
END
CLOSE tablerows
DEALLOCATE tablerows
CLOSE foreignkeys
DEALLOCATE foreignkeys
--Revert to normal identity operation - update the identity to the latest id...
DBCC CHECKIDENT(@Table, RESEED, @@IDENTITY)
SET @sql='SET IDENTITY_INSERT ' + @Table + ' OFF'
PRINT(@sql)
exec(@sql)
FETCH NEXT FROM tables
INTO @Table, @IdColumn
END
CLOSE tables
DEALLOCATE tables
DROP TABLE #IdTable
--COMMIT
--ROLLBACK