代码之家  ›  专栏  ›  技术社区  ›  Anton Gogolev

更改大表pk列数据类型

  •  2
  • Anton Gogolev  · 技术社区  · 15 年前

    现在我们已经用完了 int pk列的容量(即 IDENTITY )我想这样做 bigint 但简单 ALTER TABLE 似乎无法处理这么大的一张桌子。因此,我的问题是:如何在保持实际值不变的情况下更改pk列的类型,以及是否需要更改引用表?

    4 回复  |  直到 12 年前
        1
  •  4
  •   Yannick Motton    15 年前

    除了克莱的建议,以下问题可能会有所帮助:

    要禁用引用oldTable的表上的所有约束,请尝试执行以下查询的输出:

    SELECT 'ALTER TABLE ' + OBJECT_NAME(fk.parent_object_id) + ' NOCHECK CONSTRAINT ' + fk.name
    FROM sys.foreign_keys fk
    INNER JOIN sys.foreign_key_columns AS fkc ON fk.OBJECT_ID = fkc.constraint_object_id
    WHERE OBJECT_NAME (fk.referenced_object_id) = 'oldTable'
    

    要将所有数据移动到新表中,并更改字段,请尝试以下操作:

    INSERT INTO newTable
    SELECT CONVERT(BIGINT, ID) AS ID, COL1, COL2, ..., COLN
    FROM oldTable
    

    放下旧桌子:

    DROP TABLE oldTable
    

    要将新表重命名为旧名称:

    sp_rename newTable, oldTable
    

    要重新启用引用旧表的表上的所有约束,请尝试执行以下查询的输出:

    SELECT 'ALTER TABLE ' + OBJECT_NAME(fk.parent_object_id) + ' CHECK CONSTRAINT ' + fk.name
    FROM sys.foreign_keys fk
    INNER JOIN sys.foreign_key_columns AS fkc ON fk.OBJECT_ID = fkc.constraint_object_id
    WHERE OBJECT_NAME (fk.referenced_object_id) = 'oldTable'
    

    希望有帮助…

        2
  •  3
  •   KLE rslite    15 年前

    我们要做的是:

    保存表

    1. 创建具有正确结构的新表
    2. 禁用这些表以及引用它们的表上的所有约束
    3. 将所有数据移动到新表中,并更改字段;可以批量执行。
    4. 当旧表为空时删除它
    5. 将新表重命名为旧名称
    6. 在所有表上启用所有约束(某些FK列和约束可能也需要修复…但它们不是pk,因此可以修改)

      6编辑(感谢Alexey)

    这是干净的,可以批量操作,很好理解。

        3
  •  0
  •   HLGEM    15 年前

    您还需要更改子表。毕竟,你现在也将尝试在它们中插入一个很大的int。我先换儿童桌

    这不是一个简单或短暂的过程。我建议您告诉您的用户,数据库将在一个设定的日期停止维护(您可以通过执行dev所需的时间来衡量多长时间),并在进行这些更改时将数据库重置为单用户模式。在切换到另一个表时,您不希望丢失由用户添加(或更改)到一个表的数据。如果由于某种原因您没有维护窗口(为了数据完整性,我强烈建议您这样做),那么您必须首先更改子表,以避免插入错误,如果您的a真的接近极限,并且几乎可以立即看到大的数字。

    请确保为整个数据库结构编写脚本,包括默认值、触发器、检查常量索引等,因为您希望重新创建所有内容。

    确保通过dev上的脚本来完成所有这些工作,这将使您在测试完流程后更容易执行一个prod。

        4
  •  -1
  •   Alexey Sviridov    15 年前

    我认为您只能创建一个具有更改的pk数据类型的新数据库,然后导出/导入数据,或者批量插入到新数据库中,然后重命名新数据库。当然,如果您有许多被引用的表,并且您的新pk数据类型与以前的不兼容,那么这就是实际情况。