【问题标题】:How can I add a column that doesn't allow nulls in a Postgresql database?如何在 Postgresql 数据库中添加不允许空值的列?
【发布时间】:2010-10-05 11:25:08
【问题描述】:

我正在使用以下查询(针对 Internet 进行清理)向我的 Postgresql 数据库添加一个新的“NOT NULL”列:

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL;

每次运行此查询时,我都会收到以下错误消息:

ERROR:  column "mycolumn" contains null values

我被难住了。我哪里错了?

注意:我主要使用 pgAdmin III (1.8.4),但是当我在终端中运行 SQL 时收到了同样的错误。

【问题讨论】:

    标签: sql postgresql alter-table


    【解决方案1】:

    由于表中已经存在行,ALTER 语句试图将NULL 插入到所有现有行的新创建列中。您必须将该列添加为允许NULL,然后用您想要的值填充该列,然后将其设置为NOT NULL

    【讨论】:

    • 如何做的例子真的很好。否则,Luc 的解决方案似乎更完整,可以使用。
    【解决方案2】:

    您要么需要定义一个默认值,要么按照 Sean 所说的去做,并在没有空约束的情况下添加它,直到您在现有行上填充它。

    【讨论】:

      【解决方案3】:

      或者,使用额外的列创建一个新表作为临时表,将数据复制到这个新表中,同时根据需要对其进行操作以填充不可为空的新列,然后通过两步更改名称来交换表。

      是的,它更复杂,但如果您不想在活动表上进行大更新,则可能需要这样做。

      【讨论】:

      • 我没有 -1 你,但我认为这可能存在微妙的困难——例如我敢打赌,即使在重命名之后,现有的索引、触发器和视图仍将继续引用原始表,因为我认为它们存储的是表的 relid(不会更改)而不是它的名称。
      • 是的,我应该声明新表应该是原始表的精确副本,包括添加索引等。我太简短了。这样做的原因是,在可能是实时的表上执行 ALTER 也有一些微妙的困难,有时您需要暂存它。
      • 例如,使用 DEFAULT 方法,您会将该默认值添加到每一行。不确定 Postgres 在执行此操作时如何锁定表。或者,如果列顺序很重要,您不能只使用 ALTER 命令添加列。
      • 公平地说,根据 PostgreSQL 文档,ALTER TABLE 确实锁定了表,但是如果表确实是活动的,那么您的非事务方法可能会丢失更改。另外我建议任何依赖列顺序的代码都被破坏(当然这可能超出你的控制范围)。
      • 如果表被外键索引引用,这种方法也特别成问题,因为这些索引都必须重新创建。
      【解决方案4】:

      你必须设置一个默认值。

      ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT 'foo';
      
      ... some work (set real values as you want)...
      
      ALTER TABLE mytable ALTER COLUMN mycolumn DROP DEFAULT;
      

      【讨论】:

      • @SeanBright ,您可以通过 man ALTER_TABLE 离线访问 postgres 文档 :)
      • 澄清一下:默认值只需要更新现有的行,这就是为什么它可以在之后立即删除。更改表时,所有现有行都已更新(显然,这可能需要一些时间)
      • 如果您想使用另一列来计算现有行的初始值,这将不起作用。 j_random_hacker's answer 允许这样做,使其更加健壮。
      【解决方案5】:

      如果默认值合适,指定默认值也可以。

      【讨论】:

      • 提供修改后的语法以创建具有默认值的列(用于说明)会改进答案。
      【解决方案6】:

      正如其他人所观察到的,您必须创建一个可为空的列或提供一个 DEFAULT 值。如果这不够灵活(例如,如果您需要以某种方式单独计算每一行的新值),您可以使用在 PostgreSQL 中,所有 DDL 命令都可以在事务中执行的事实:

      BEGIN;
      ALTER TABLE mytable ADD COLUMN mycolumn character varying(50);
      UPDATE mytable SET mycolumn = timeofday();    -- Just a silly example
      ALTER TABLE mytable ALTER COLUMN mycolumn SET NOT NULL;
      COMMIT;
      

      【讨论】:

      • 即使在事务中,NOT NULL 也会立即强制执行,因此必须首先添加列、填充值,然后添加 NOT NULL——就像这个答案一样。 (在 postgres 9.6 上测试)
      【解决方案7】:

      此查询将自动更新空值

      ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) DEFAULT 'whatever' NOT NULL;
      

      【讨论】:

        【解决方案8】:

        这对我有用::)

        ALTER TABLE your_table_name ADD COLUMN new_column_name int;
        

        【讨论】:

        • 您的查询没有NOT NULL 约束。当然可以。
        猜你喜欢
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-14
        • 2012-07-01
        相关资源
        最近更新 更多