更改列集非空失败

时间:2013-10-23 16:49:03

标签: postgresql alter notnull enterprisedb

考虑下表,大约有10M行

CREATE TABLE user
(
  id bigint NOT NULL,
  ...
  CONSTRAINT user_pk PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
)

然后我应用了以下更改

ALTER TABLE USER ADD COLUMN BUSINESS_ID    VARCHAR2(50);
--OK
UPDATE USER SET BUSINESS_ID = ID; //~1500 sec
--OK
ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET NOT NULL;

    ERROR: column "business_id" contains null values
    SQL state: 23502

这很奇怪,因为id列(已复制到business_id列)不能包含空值,因为它是主键,但要确保我检查它

select count(*) from USER where BUSINESS_ID is null
    --0 records

我怀疑这是一个错误,只是想知道我是否遗漏了一些微不足道的事情

3 个答案:

答案 0 :(得分:18)

唯一合乎逻辑的解释是并发INSERT ..
(使用tbl代替保留字user作为表名。)

ALTER TABLE tbl ADD COLUMN BUSINESS_ID    VARCHAR2(50);
--OK
UPDATE tbl SET BUSINESS_ID = ID; //~1500 sec
--OK

 HERE

ALTER TABLE tbl ALTER COLUMN BUSINESS_ID SET NOT NULL;

要防止这种情况,请改为使用:

ALTER TABLE tbl
ADD COLUMN BUSINESS_ID VARCHAR(50) DEFAULT ''; -- or whatever is appropriate
...

然后,您可能会在某些行中使用默认值。你可能想检查一下。

或者将所有内容作为事务块运行并采取独占锁定以确保:

BEGIN;
LOCK tbl;
ALTER ...
UPDATE ...
ALTER ...
COMMIT;

答案 1 :(得分:8)

也许它想要一个默认值? Postgresql docs on ALTER

  

要添加列,请使用如下命令:

ALTER TABLE products ADD COLUMN description text;
     

新列最初填充了任何默认值(如果未指定DEFAULT子句, null )。

所以,

ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET DEFAULT="", 
                 ALTER COLUMN BUSINESS_ID SET NOT NULL;

答案 2 :(得分:0)

您无法在同一笔交易中执行此操作。添加您的列并进行更新。然后在单独的事务中设置非空约束。