【问题标题】:Alter table add column not null on empty table in netezza在 netezza 的空表上​​更改表添加不为空的列
【发布时间】:2015-11-03 09:33:30
【问题描述】:
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”的非空约束不允许没有默认值

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

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

这是预期的行为吗?

【问题讨论】:

    标签: netezza


    【解决方案1】:

    这种行为是预期的。更改表时,Netezza 使用版本化表方法。如果您将一列添加到表中,实际上将有两个不同的表版本,它们作为单个表呈现给用户。

    原始表版本(没有新的 NOT NULL DEFAULT 列)不会被修改,直到 GROOM VERSIONS 将版本再次折叠到单个基础表中。这里的好处是更改速度很快,因为它不需要扫描/更新现有行。相反,它知道为原始基础表版本中不存在的列提供 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 列的所有值都已完全实现。

    【讨论】:

      【解决方案2】:

      您可以在不指定默认值的情况下从头开始创建表。

      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?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多