在不删除表的情况下更新主键的数据类型

new*_*ser 3 sql-server primary-key

我创建了一个表State,我的另一个表Addresses引用了该表。

CREATE TABLE State
(
     StateId varchar(20) PRIMARY KEY NOT NULL,
     Text varchar(40) NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

我想将其主键更改为intand IDENTITY(1,1),但是,我无法删除它,因为它是另一个表的外键。如何更新它而不必重新创建所有内容?

Sol*_*zky 9

您不能更改关键字段(主要或外来)的数据类型。如果该字段用于索引,您甚至无法更改数据类型。所以...

如果这些表中没有数据(显然容易得多):

  1. 在引用 [State] 的 [Addresses] 上删除外键
  2. 将主键放在 [State] 上
  3. ALTER TABLE [State] DROP COLUMN [StateID];
  4. ALTER TABLE [State] ADD [StateID] INT IDENTITY(1, 1) NOT NULL;
  5. 在 [State] 上重新创建主键
  6. ALTER TABLE [Addresses] ALTER COLUMN [StateID] INT NOT NULL;
  7. 在引用 [State] 的 [Addresses] 上重新创建外键

如果这些表中有数据(并且您有维护时段):

  1. ALTER TABLE [State] ADD [StateID2] INT IDENTITY(1, 1) NOT NULL;
  2. ALTER TABLE [Addresses] ADD [StateID2] INT NOT NULL CONSTRAINT [DF_Addresses_StateID2] DEFAULT (0);
  3. 更新 [Addresses] 表以匹配 [State] 表中的新 ID

    UPDATE addr
    SET    addr.StateID2 = st.StateID2
    FROM   Addresses addr
    INNER JOIN [State] st
            ON st.StateID = addr.StateID
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在引用 [State] 的 [Addresses] 上删除外键
  5. 将主键放在 [State] 上
  6. sp_rename [State].[StateID] -> [StateIDold]
  7. sp_rename [State].[StateID2] -> [StateID]
  8. 在 [State].[StateID] 上重新创建主键
  9. ALTER TABLE [Addresses] DROP CONSTRAINT [DF_Addresses_StateID2];
  10. sp_rename [地址].[StateID] -> [StateIDold]
  11. sp_rename [地址].[StateID2] -> [StateID]
  12. 在引用 [State].[StateID] 的 [Addresses].[StateID] 上重新创建外键
  13. 更新存储过程或任何进程/代码插入(如果 StateID 字段可以更改,则可能更新)到 [Addresses] 表中
  14. 在确定所有数据都存在并匹配后,您可以删除 [State] 和 [Address] 表中的 [StateIDold] 字段。

如果这些表中有数据(并且您没有维护窗口):

如果没有维护窗口,那么您不仅要处理表上的争用(并且添加/删除字段需要 SCHEMA 锁),还需要更新将数据添加到 [Addresses] 的进程

  1. 使用所需结构(但没有 FK)构建两个表 [Addresses2] 和 [State2] 的副本
  2. 将数据复制到新表
  3. 确保 [Addresses] 中没有数据可以更改(这是非常临时的)
  4. 重命名当前表(例如 [Addresses] -> [AddressesOld])
  5. 重命名新表(例如 [Addresses2] -> [Addresses])
  6. 添加外键
  7. 请务必更新插入地址的代码
  8. 再次允许更改 [地址]

有关这种“无维护窗口”方法的更详细说明,请参阅我在 SQL Server Central 上写的关于它的文章(需要免费注册):Restructure 100 Million Row (or more) Tables in Seconds。SRSLY!