【问题标题】:Best way to add a new column with an initial (but not default) value?添加具有初始(但不是默认)值的新列的最佳方法?
【发布时间】:2010-11-05 17:58:54
【问题描述】:

我需要在 MS SQL 2005 数据库中添加一个具有初始值的新列。但是,我不想在此列上自动创建默认约束。在我添加列的时间点,默认/初始值是正确的,但这可能会随着时间而改变。因此,将来对表的访问必须指定一个值,而不是接受默认值。

我能想到的最好的方法是:

ALTER TABLE tbl ADD col INTEGER NULL
UPDATE tbl SET col = 1
ALTER TABLE tbl ALTER COLUMN col INTEGER NOT NULL

这对于大型表(100,000 到 1,000,000 条记录)似乎有点低效。

我尝试过添加具有默认值的列,然后删除默认约束。但是,我不知道默认约束的名称是什么,并且宁愿不访问 sysobjects 并输入数据库特定的知识。

拜托,一定有更好的办法。

【问题讨论】:

    标签: sql sql-server database alter-table


    【解决方案1】:

    要添加具有默认值的列然后删除默认值,您可以命名默认值:

    ALTER TABLE tbl ADD col INTEGER NOT NULL CONSTRAINT tbl_temp_default DEFAULT 1
    ALTER TABLE tbl drop constraint tbl_temp_default
    

    这填充了值 1,但没有默认值。使用 SQL Server 2008,我运行了 alter update alter 的代码和您的代码,并且在 100,000 个小行的表上没有看到任何明显的差异。 SSMS 不会向我显示 alter table 语句的查询计划,因此我无法比较两种方法使用的资源。

    【讨论】:

    • 与@Alex 类似的解决方案,但解释更完整。
    【解决方案2】:

    我会先ALTER TABLE tbl ADD col INTEGER CONSTRAINT tempname DEFAULT 1,然后(可能在事务中)删除显式命名约束。

    【讨论】:

    • +1。 --- @Alex:我不确定是否可以在事务中执行 DDL。 --- @Adrian:你真的关心它效率低下吗?你不是每天都这样做,是吗?为了清楚起见,我通常使用您描述的方式。
    • @van,我不能 100% 确定 SqlServer'05 在这方面的局限性——PostgreSQL 确实允许您以事务方式更改表(至少使用显式的 BEGIN 和 COMMIT 事务) )。要检查 MS 是否也这样做, SELECT @@TRANCOUNT 应该会告诉你(我在文档中找不到清楚的拼写)。
    • @van & @Alex MS SQL Server 在事务中执行 DDL。
    【解决方案3】:

    另一种可能更原生的方式是:

    ALTER TABLE tbl ADD COLUMN col INTEGER NOT NULL DEFAULT 1;
    ALTER TABLE tbl ALTER COLUMN col DROP DEFAULT;
    

    我不确定这个函数存在多久,但PostgreSQL documentation 可以追溯到 7.1 版本,对于 7.1,它已经被描述了。

    【讨论】:

      【解决方案4】:

      您可以在插入触发器中执行此操作

      【讨论】:

      • 这正是我的想法。顺便说一句,你不想把它当作约束吗
      • 问题是向具有现有行的表中添加一列。添加触发器只会影响新行。我错过了什么吗?
      • 我想我误解了这个问题。当您说要添加具有初始值的列时,您的意思是您希望所有现有行都具有此值而无需更新它们吗?在这种情况下,您可以添加两列。一个是可为空的列,另一个是计算列。如果另一列为空,则计算列将返回默认值,否则将返回另一列。这在未来会变得非常复杂。我宁愿像你在你的例子中那样做。
      【解决方案5】:

      如果你在创建表的时候添加了一个默认的约束,你就不会知道它叫什么了。但是,如果您使用 ALTER TABLE 添加约束,则必须命名该约束。在这种情况下,您将能够 ALTER TABLE DROP CONSTRAINT (这适用于 T-SQL,不确定其他数据库。)

      但是,这将要求您创建带有 NULL 列的 TABLE,ALTER TABLE 添加约束,使列 NOT NULL,最后 DROP CONSTRAINT。

      我不相信插入触发器会像其他人提到的那样工作,因为您的行已经添加。

      我认为你描述的方式实际上可能是最有效和最优雅的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-11
        相关资源
        最近更新 更多