更改表在netezza中的空表上添加列不为空

时间:2015-08-11 08:39:17

标签: netezza

SYSTEM.ADMIN(ADMIN)=> create table test ( name varchar(20), age int);

CREATE TABLE

SYSTEM.ADMIN(ADMIN)=> alter table test add column dob varchar(20) NOT NULL;

错误:ALTER TABLE:列" DOB"的非空约束;不允许没有默认值

即使在空表上,我们是否必须在非空后指定默认值?

SYSTEM.ADMIN(ADMIN)=> alter table test add column dob varchar(20) NOT NULL DEFAULT '0';
ALTER TABLE

这是预期的行为吗?

2 个答案:

答案 0 :(得分:4)

您可以从头创建表而不指定默认值。

create table test ( name varchar(20)
, age int
,dob varchar(20) NOT NULL );

但是,在添加列时,postgresql(netezza)中需要指定一个默认值来填充将出现的任何空值。这是预料之中的。删除默认值的顺序如下:

 create table test ( name varchar(20), age int);
 ALTER TABLE test add column dob varchar(20) NOT NULL default 'a';
 ALTER TABLE test ALTER COLUMN dob DROP DEFAULT;

How can I add a column to a Postgresql database that doesn't allow nulls?

答案 1 :(得分:1)

此行为是预期的。在更改表时,Netezza使用版本化表方法。如果向表中添加列,则实际上会有两个不同的表版本,它们作为单个表呈现给用户。

在GROOM VERSIONS将版本再次折叠到单个基础表中之前,不会修改原始表版本(没有新的NOT NULL DEFAULT列的版本)。这里的优点是更改很快,因为它不需要扫描/更新现有行。相反,它知道为原始基础表版本中不存在的列提供DEFAULT值。

当更改表以添加具有NOT NULL属性的列时,系统需要 DEFAULT规范,以便它知道如何表示添加的列。无论表是否实际包含任何行,都需要这样做。

TESTDB.ADMIN(ADMIN)=> CREATE TABLE TEST ( NAME VARCHAR(20), AGE INT);
CREATE TABLE
TESTDB.ADMIN(ADMIN)=> insert into test values ('mine',5);
INSERT 0 1
TESTDB.ADMIN(ADMIN)=> ALTER TABLE TEST ADD COLUMN DOB VARCHAR(20) NOT NULL DEFAULT '0';
ALTER TABLE
TESTDB.ADMIN(ADMIN)=> insert into test values ('yours',50);
INSERT 0 1
TESTDB.ADMIN(ADMIN)=> select* from test;
 NAME  | AGE | DOB
-------+-----+-----
 yours |  50 | 0
 mine  |   5 | 0
(2 rows)

好消息是,您可以更改新添加的列以删除该默认值。

TESTDB.ADMIN(ADMIN)=> ALTER TABLE TEST ALTER COLUMN DOB DROP DEFAULT;
ALTER TABLE
TESTDB.ADMIN(ADMIN)=> \d test
                         Table "TEST"
 Attribute |         Type          | Modifier | Default Value
-----------+-----------------------+----------+---------------
 NAME      | CHARACTER VARYING(20) |          |
 AGE       | INTEGER               |          |
 DOB       | CHARACTER VARYING(20) | NOT NULL |
Distributed on random: (round-robin)
Versions: 2

TESTDB.ADMIN(ADMIN)=> select * from test;
 NAME  | AGE | DOB
-------+-----+-----
 yours |  50 | 0
 mine  |   5 | 0
(2 rows)

作为分离注释,尽可能及时地修饰任何版本化的表非常重要,这样可以防止由于版本化表的性质而导致性能降低。

TESTDB.ADMIN(ADMIN)=> GROOM TABLE TEST VERSIONS;
NOTICE:  Groom will not purge records deleted by transactions that started after 2015-07-27 01:32:16.
NOTICE:  If this process is interrupted please either repeat GROOM VERSIONS or issue 'GENERATE STATISTICS ON "TEST"'
NOTICE:  Groom processed 1 pages; purged 0 records; scan size unchanged; table size unchanged.
GROOM VERSIONS
TESTDB.ADMIN(ADMIN)=> \d test
                         Table "TEST"
 Attribute |         Type          | Modifier | Default Value
-----------+-----------------------+----------+---------------
 NAME      | CHARACTER VARYING(20) |          |
 AGE       | INTEGER               |          |
 DOB       | CHARACTER VARYING(20) | NOT NULL |
Distributed on random: (round-robin)

此时,该表不再是版本化表,NOT NULL列的所有值都完全具体化。