如何在不允许null的Postgresql数据库中添加列?


243

我使用以下查询(已针对Internet进行了清理)将新的“ NOT NULL”列添加到我的Postgresql数据库中:

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

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

ERROR:  column "mycolumn" contains null values

我很沮丧 我要去哪里错了?

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

Answers:


400

您必须设置一个默认值。

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;

1
不错的解决方案。由于某种原因,我无法访问在线postgres文档,以了解其语法。
肖恩·布莱特

4
@SeanBright,您可以执行以下操作来离线访问Postgres doc man ALTER_TABLE :)
allan.simon 2015年

@ allan.simon我以前从未使用过PostgreSQL,也没有在任何地方安装它。
肖恩·布莱特

2
需要说明的是:仅在更新现有行时才需要默认值,这就是为什么可以在之后立即删除默认值的原因。更改表后,所有现有行均已更新(显然,这可能需要一些时间)
MSalters

2
如果要使用另一列来计算现有行的初始值,则此方法将无效。j_random_hacker的答案可以做到这一点,从而使其更强大。
jpmc26

82

正如其他人观察到的那样,您必须创建可为空的列或提供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;

7
即使在事务中,也必须立即执行NOT NULL,因此必须首先添加列,填充值,然后再添加NOT NULL -就像这个答案一样。(在postgres 9.6上进行测试)
贝尼·切尔尼亚夫斯基-帕斯金

48

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


7
如何做到这一点的例子真的很好。否则,Luc的解决方案似乎更加完整并可以使用。
维克多·法拉兹达吉

5

您要么需要定义一个默认值,要么执行Sean所说的并在没有null约束的情况下添加它,直到在现有行中填写它为止。



1

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

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


3
我不是-1,但我认为这样做可能会有一些细微的困难-例如,我敢打赌即使重命名后现有索引,触发器和视图仍将继续引用原始表,因为我认为它们存储了表的名称(不会改变)而不是名称。
j_random_hacker,2009年

1
是的,我应该指出,新表应该是原始表的精确副本,包括添加索引等。太简短了,我不好。这样做的原因是,在可能处于活动状态的桌子上执行ALTER也有一些困难,有时您需要登台。
alphadogg

例如,使用DEFAULT方法,您可以将该默认值添加到每一行。不知道这样做时Postgres如何锁定表格。或者,如果列顺序很重要,则不能仅使用ALTER命令添加列。
alphadogg

公平地说,ALTER TABLE确实根据PostgreSQL文档锁定了该表,但是如果该表确实处于活动状态,则您的非事务处理方法可能会丢失更改。另外,我建议依赖列顺序的所有代码都将损坏(当然,这可能超出了您的控制范围)。
j_random_hacker

2
如果该表由外键索引引用,则该方法也特别有问题,因为这些索引也必须全部重新创建。
Aryeh Leib Taurog

0

该查询将自动更新null

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

-6

这为我工作::)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;

2
NOT NULL您的查询没有任何限制。当然可以了。
西尔万
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.