To get the year for the date data type:
select extract(year from '2014-01-01'::date) as the_year; the_year
If you only need a year, use the small push with a control limit
create table t ( the_year smallint check( the_year between 0 and extract(year from current_date) ) ); insert into t (the_year) values (2030); ERROR: new row for relation "t" violates check constraint "t_the_year_check" DETAIL: Failing row contains (2030). insert into t (the_year) values (2014); INSERT 0 1
But if you save the whole date, then it makes no sense to divide into 3 columns.
Note that column semantics are application dependent. If the column is of type date , but the application takes into account only the year, then this column means year.
Mark Functions and Date and Time Operators
One solution to the partial date problem noted by @a_horse in the comments is to create a column indicating the accuracy of that date
create table t ( the_date date, the_date_precision varchar(5) ); insert into t (the_date, the_date_precision) values (current_date, 'year'), (current_date, 'month'), (current_date, 'day') ; select case the_date_precision when 'year' then to_char(the_date, 'YYYY') when 'month' then to_char(the_date, 'YYYY-MM') else to_char(the_date, 'YYYY-MM-DD') end as the_date from t ; the_date
The above is KISS approach, but I think the next implementation is more elegant.
create table t ( the_date date, the_date_precision smallint ); insert into t (the_date, the_date_precision) values (current_date, 1), (current_date, 2), (current_date, 3) ; select array_to_string( ( string_to_array(to_char(the_date, 'YYYY-MM-DD'), '-') )[1:the_date_precision] , '-' ) as the_date from t ; the_date
This expression of choice can be turned into a function that is easier to reproduce. Or just view
create view view_t as select *, array_to_string( ( string_to_array(to_char(the_date, 'YYYY-MM-DD'), '-') )[1:the_date_precision] , '-' ) as the_date_output from t ; select * from view_t; the_date | the_date_precision | the_date_output