Kapish Kumar
Kapish Kumar

Reputation: 143

Alter table add column not null on empty table in 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;

ERROR: ALTER TABLE: not null constraint for column "DOB" not allowed without default value

Do we have to specify a default value after not null even on empty table?

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

Is this expected behavior ?

Upvotes: 3

Views: 6013

Answers (2)

ScottMcG
ScottMcG

Reputation: 3887

This behavior is expected. When altering a table, Netezza uses a versioned table approach. If you add a column to a table, there will actually be two different table versions under the covers which are presented as a single table to the user.

The original table version (the one without the new NOT NULL DEFAULT column) is not modified until a GROOM VERSIONS collapses the versions again into a single underlying table. The upside here is that the alter is fast because it doesn't require a scan/update of the existing rows. Instead it knows to provide the DEFAULT value for column that doesn't exist in the original underlying table version.

When altering a table to add a column with the NOT NULL property, the system requires a DEFAULT specification so that it knows how to represent the added column. This is required whether the table actually has any rows or not.

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)

The good news is that you can then alter the newly added column to remove that default.

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)

As a parting note, it's important to groom any versioned tables as promptly as possible in order to keep your performance from degrading over time due to the nature of versioned tables.

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)

At this point the table is no longer a versioned table an all values for the NOT NULL columns are fully materialized.

Upvotes: 1

Niederee
Niederee

Reputation: 4295

You can create the table from scratch without specifying a default value.

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

However when adding a column it is required in postgresql (netezza) to specify a default value to fill any nulls that would be present. This is expected. The sequence to remove the default is as follows:

 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?

Upvotes: 4

Related Questions