Add timestamp column with default NOW() for new rows only - postgresql

I have a table that has thousands of rows. Since the table wasn't constructed with created_at column initially, there is no way of getting their creation timestamp. It is crucial though to start getting the timestamps for future rows.
Is there a way I can add a timestamp column with default value NOW() so that it won't populate the values to previous rows but only for the future ones?
If I do the ALTER query, it populates all rows with timestamp:
ALTER TABLE mytable ADD COLUMN created_at TIMESTAMP DEFAULT NOW()

You need to add the column with a default of null, then alter the column to have default now().
ALTER TABLE mytable ADD COLUMN created_at TIMESTAMP;
ALTER TABLE mytable ALTER COLUMN created_at SET DEFAULT now();

You could add the default rule with the alter table,
ALTER TABLE mytable ADD COLUMN created_at TIMESTAMP DEFAULT NOW()
then immediately set to null all the current existing rows:
UPDATE mytable SET created_at = NULL
Then from this point on the DEFAULT will take effect.

For example, I will create a table called users as below and give a column named date a default value NOW()
create table users_parent (
user_id varchar(50),
full_name varchar(240),
login_id_1 varchar(50),
date timestamp NOT NULL DEFAULT NOW()
);
Thanks

minor optimization.
select pg_typeof(now()); --returns: timestamp with time zone. So now include timezone.
So better with timestamptz.
begin;
ALTER TABLE mytable ADD COLUMN created_at TIMESTAMPTZ;
ALTER TABLE mytable ALTER COLUMN created_at SET DEFAULT now();
commit;

Try something like:-
ALTER TABLE table_name ADD CONSTRAINT [DF_table_name_Created]
DEFAULT (getdate()) FOR [created_at];
replacing table_name with the name of your table.

Related

ALTER TABLE ON UPDATE CURREN_TIMESTAMP in postgresql

ALTER TABLE tabelName ADD COLUMN IF NOT EXISTS columnName TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
I am using this query to create column on update current_timestamp
It is throwing error ERROR: syntax error at or near "ON"
Thank you all in advance!
There is no ON UPDATE clause in ALTER TABLE ... ADD COLUMN ... statement. Try instead:
ALTER TABLE tableName ADD COLUMN IF NOT EXISTS columnName TIMESTAMP DEFAULT CURRENT_TIMESTAMP;

Applying unique constraint of date on TIMESTAMP column in postgresql

I have a postgresql table as
CREATE TABLE IF NOT EXISTS table_name
(
expiry_date DATE NOT NULL,
created_at TIMESTAMP with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
CONSTRAINT user_review_uniq_key UNIQUE (expiry_date, created_at::date) -- my wrong attempt of using ::
)
I want to put uniue constraint on this table in such a way that expiry_date and date of created_at should be unique. Problem is created_at column is timestamp not date.
so is there any way to put unique constraint such that expire_date and created_at::date should be unique?
My attempt was to use
CONSTRAINT user_review_uniq_key UNIQUE (expiry_date, created_at::date) which is not valid.
If you do not need a time zone for your created date : create a unique index has follows :
create unique index idx_user_review_uniq_key on table_name (expiry_date, cast(created_at as date));
If you need that badly to have a time zone then you need to use a little trick (https://gist.github.com/cobusc/5875282) :
create unique index idx_user_review_uniq_key on table_name (expiry_date, date(created_at at TIME zone 'UTC'));

ALTER table column to timestamp now() properties

I created a table in postgres from samples I found on the internet. The definition of the column stored is:
stored | timestamp without time zone | default '2014-04-11 21:19:20.144487'::timestamp without time zone
How do I alter this to be a "normal" timestamp now() type? So it will stamp the current date-time when inserting data?
Thank you all in advance!
If you're trying to change the default value . . .
alter table your-table-name
alter column stored set default current_timestamp
For changing the field type and default value the syntax will be ...
alter table your-table-name
alter column your-field type timestamp,
alter column your-field set default current_timestamp;

Alter column set not null fails

Consider the following table with approximately 10M rows
CREATE TABLE user
(
id bigint NOT NULL,
...
CONSTRAINT user_pk PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
)
Then i applied the following alter
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
This is very strange since id column (which has been copied to business_id column) can't contain null values since it is the primary key, but to be sure i check it
select count(*) from USER where BUSINESS_ID is null
--0 records
I suspect that this is a bug, just wondering if i am missing something trivial
The only logical explanation would be a concurrent INSERT.
(Using tbl instead of the reserved word user as table name.)
ALTER TABLE tbl ADD COLUMN BUSINESS_ID VARCHAR2(50);
--OK
UPDATE tbl SET BUSINESS_ID = ID; //~1500 sec
--OK
-- concurrent INSERT HERE !!!
ALTER TABLE tbl ALTER COLUMN BUSINESS_ID SET NOT NULL;</code></pre>
To prevent this, use instead:
ALTER TABLE tbl
ADD COLUMN BUSINESS_ID VARCHAR(50) DEFAULT ''; -- or whatever is appropriate
...
You may end up with a default value in some rows. You might want to check.
Or run everything as transaction block:
BEGIN;
-- LOCK tbl; -- not needed
ALTER ...
UPDATE ...
ALTER ...
COMMIT;
You might take an exclusive lock to be sure, but ALTER TABLE .. ADD COLUMN takes an ACCESS EXCLUSIVE lock anyway. (Which is only released at the end of the transaction, like all locks.)
Maybe it wants a default value? Postgresql docs on ALTER:
To add a column, use a command like this:
ALTER TABLE products ADD COLUMN description text;
The new column is initially filled with whatever default value is given (null if you don't specify a DEFAULT clause).
So,
ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET DEFAULT="",
ALTER COLUMN BUSINESS_ID SET NOT NULL;
You cannot do that at the same transaction. Add your column and update it. Then in a separate transaction set the not null constraint.

Alter a Column Data Type Postgres

Hey I have just started working on PostgreSQL, and I am wondering how can we change a column's data type, I tried the following command:
alter table tableName alter column columnName type timestamp with time zone;
However I got the following message:
column "columnName" cannot be cast to type timestamp with time zone
The current column's data type is int, and i would like to change it to timestamp
Postgres doesn't know how to translate int to timestamp. There are several cases and usually they have different starting date.
Create temporary column with timestamp
Update table and copy data from old column to temporary column using your own translation
Drop old column
Rename temporary column.
If you look into documentation, you will find one line syntax with example how to convert unix time integer type:
ALTER [ COLUMN ] column [ SET DATA ] TYPE type [ USING expression ]
Postgres does't allow int type column to change directly into timezone. To achive this, you have to first change column type to varchar and then change it to timezone.
alter table tableName alter column columnName type varchar(64);
alter table tableName alter column columnName type timestamp with time zone;
There is a better way to do this, with the USING clause. Like so:
ALTER TABLE tableName
ALTER columnName type TIMESTAMP WITH TIME ZONE
USING to_timestamp(columnName) AT TIME ZONE 'America/New_York';
I achieved it from timestamp to timestamp with time zone by:
ALTER TABLE tableName ALTER COLUMN columnName SET DATA TYPE timestamp with time zone;
but if it is from timestamp to int or bigint you may need to do this:
ALTER TABLE tableName ALTER COLUMN columnName SET DATA TYPE int8 USING columnName::bigint