Why default is not used when I set not null contratint? - postgresql

I have table in postgresql database.
For given column I set default value, then I want it to be NOT NULL:
ALTER TABLE "order" ALTER COLUMN last_bill_date SET DEFAULT '-Infinity';
ALTER TABLE "order" ALTER COLUMN last_bill_date SET NOT NULL;
But second statement fails:
ERROR: column "last_bill_date" contains null values
Why DEFAULT value is not used when NOT NULL is applied for this column?

Per the documentation:
DEFAULT default_expr
(...)
The default expression will be used in any insert operation that does not specify a value for the column. If there is no default for a column, then the default is null.
The altered default expression cannot modify rows already existing in the table, you should do it before setting the not null constraint:
update "order"
set last_bill_date = '-Infinity'
where last_bill_date is null

Related

How to set a normal column back to a generated one in postgresql?

I am firstly creating a table like this:
CREATE TABLE public.case_change (
id integer NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
to_quantity integer NOT NULL,
to_cancelled_quantity integer NOT NULL DEFAULT 0,
to_completed_quantity integer NOT NULL DEFAULT 0,
to_outstanding_quantity integer GENERATED ALWAYS AS (to_quantity - to_cancelled_quantity - to_completed_quantity) STORED NOT NULL
);
And then I am applying this:
alter table public.case_change alter column to_outstanding_quantity DROP EXPRESSION;
alter table public.case_change alter column to_outstanding_quantity set DEFAULT 0;
which will set to_outstanding_quantity to be the same as to_completed_quantity.
Now I would like to set it back to exactly how it was before (generated ), how do I do that?
I've tried this but I'm getting syntax error :
alter table public.case_change ALTER column to_outstanding_quantity SET GENERATED ALWAYS(to_quantity - to_cancelled_quantity - to_completed_quantity) STORED NOT NULL;
You are going to have to:
alter table public.case_change drop column to_outstanding_quantity;
alter table public.case_change ADD column to_outstanding_quantity
GENERATED ALWAYS AS (to_quantity - to_cancelled_quantity - to_completed_quantity )
STORED;

Want Not Null and Default to False if Supplied value is NULL

I want to achieve this:
column bool is not null
when supplied value is null it will fill in with default value false
thought this will make it:
create table public.testnull
(
xid integer not null, bool boolean default false
)
test got error
insert into public.testnotnull values(2, null)
ERROR: null value in column "bool" violates not-null constraint
DETAIL: Failing row contains (2, null).
SQL state: 23502
this will run but won't use default. Please don't tell me to use trigger.
CREATE TABLE public.testnull
(
xid integer NOT NULL, bool boolean DEFAULT false
)
You need to use the DEFAULT keyword instead of NULL in your INSERT statement.
From the docs:
DEFAULT: The corresponding column will be filled with its default value. An identity column will be filled with a new value generated by the associated sequence. For a generated column, specifying this is permitted but merely specifies the normal behavior of computing the column from its generation expression.
Also, always explicitly specify column names when using INSERT.
Speaking from decades of experience: unless you're using an ORM it's impossible to keep your CREATE TABLE definitions and INSERT statements in-sync, and eventually you'll add a new column or alter an existing column somewhere that the INSERT statements aren't expecting and everything will break.
INSERT INTO table ( xid, bool ) VALUES ( 2, DEFAULT )
Please don't tell me to use trigger.
However, if you want to change the NULL into DEFAULT or FALSE in a statement like this: INSERT INTO table ( xid, bool ) VALUES ( 2, NULL ) then you have to use a TRIGGER. There's no real way around that.
(You could use a VIEW with a custom INSERT handler, of course, but that's the same thing as creating a trigger).

How to convert an existing column to a foreign key that allows null values - PostgreSQL

I have a Postgres database with table t and column fk_c. I want to convert the column to a foreign key that references c_id in table lookup_c and allows null values. How can I do this?
ALTER TABLE public.t ADD CONSTRAINT "fk_t_c" FOREIGN KEY ("fk_c" ) REFERENCES "public"."lookup_c" ("c_id");
does not work because there rows with null values in column fk_c and I get
ERROR: insert or update on table "t" violates foreign key constraint "fk_t_c"
DETAIL: Key (fk_c)=() is not present in table "lookup_c".
The error message indicates that you have empty strings in that column, not null values.
You need to set those values to null before creating the foreign key:
update t
set fk_c = null
where trim(fk_c) = '';

Unable to change field type to not null with default value

I have a simple SQL statement, which looks like so:
alter table my_table alter column my_field set data type numeric(12,4) not null default 0;
But I get an error message, that points to not. What is wrong with that?
Use separate ALTER COLUMN clauses for the type, null behavior, and default value:
ALTER TABLE my_table
ALTER COLUMN my_field TYPE numeric(12,4),
ALTER COLUMN my_field SET DEFAULT 0,
ALTER COLUMN my_field SET NOT NULL;

Change column type and set not null

How do you change the column type and also set that column to not null together?
I am trying:
ALTER TABLE mytable ALTER COLUMN col TYPE character varying(15) SET NOT NULL
This returns an error.
What is the right syntax?
This should be correct:
ALTER TABLE mytable
ALTER COLUMN col TYPE character varying(15),
ALTER COLUMN col SET NOT NULL
Also, if you want to REMOVE NOT NULL constrain in postgresql:
ALTER TABLE mytable
ALTER COLUMN email DROP NOT NULL;