PostgreSql-向表中添加年和月

PostgreSql-向表中添加年和月,postgresql,Postgresql,我正在创建一个客户表,我希望其中一个属性是信用卡的到期日。我希望格式为“月-年”。我应该使用什么数据类型?我想使用日期,但格式是年/月/日。是否有其他方法将格式限制为仅月份和年份 您可以将日期约束为每月的第一天: create table customer ( cc_expire date check (cc_expire = date_trunc('month', cc_expire)) ); select date_trunc('month', cc_expire) >

我正在创建一个客户表,我希望其中一个属性是信用卡的到期日。我希望格式为“月-年”。我应该使用什么数据类型?我想使用日期,但格式是年/月/日。是否有其他方法将格式限制为仅月份和年份

您可以将日期约束为每月的第一天:

create table customer (
    cc_expire date check (cc_expire = date_trunc('month', cc_expire))
);
select
    date_trunc('month', cc_expire) > current_date as valid
from customer;
 valid 
-------
 t
现在这失败了:

insert into customer (cc_expire) values ('2014-12-02');
ERROR:  new row for relation "customer" violates check constraint "customer_cc_expire_check"
DETAIL:  Failing row contains (2014-12-02).
这是有效的:

insert into customer (cc_expire) values ('2014-12-01');
INSERT 0 1
但进入哪一天并不重要。您将只检查月份:

create table customer (
    cc_expire date check (cc_expire = date_trunc('month', cc_expire))
);
select
    date_trunc('month', cc_expire) > current_date as valid
from customer;
 valid 
-------
 t
分别提取年份和月份:

select extract(year from cc_expire) "year", extract(month from cc_expire) "month"
from customer
;
 year | month 
------+-------
 2014 |    12
或连接:

select to_char(cc_expire, 'YYYYMM') "month"
from customer
;
 month  
--------
 201412

您可以将日期约束为每月的第一天:

create table customer (
    cc_expire date check (cc_expire = date_trunc('month', cc_expire))
);
select
    date_trunc('month', cc_expire) > current_date as valid
from customer;
 valid 
-------
 t
现在这失败了:

insert into customer (cc_expire) values ('2014-12-02');
ERROR:  new row for relation "customer" violates check constraint "customer_cc_expire_check"
DETAIL:  Failing row contains (2014-12-02).
这是有效的:

insert into customer (cc_expire) values ('2014-12-01');
INSERT 0 1
但进入哪一天并不重要。您将只检查月份:

create table customer (
    cc_expire date check (cc_expire = date_trunc('month', cc_expire))
);
select
    date_trunc('month', cc_expire) > current_date as valid
from customer;
 valid 
-------
 t
分别提取年份和月份:

select extract(year from cc_expire) "year", extract(month from cc_expire) "month"
from customer
;
 year | month 
------+-------
 2014 |    12
或连接:

select to_char(cc_expire, 'YYYYMM') "month"
from customer
;
 month  
--------
 201412
使用其中一个

  • 字符(5)表示两位数年份,或
  • 字符(7)表示四位数的年份
下面的代码假设两位数的年份,这是匹配我所有信用卡的形式。首先,让我们创建一个有效到期日期表

create table valid_expiration_dates (
  exp_date char(5) primary key
);
现在让我们填充它。此代码仅适用于2013年。您可以通过更改开始日期(当前为“2013-01-01”)和月数(当前为11,通过将开始日期从0添加到11个月,可以轻松调整范围

现在,在数据表中,创建一个char(5)列,并将其中的外键引用设置为valid\u expiration\u dates.exp\u date

当您忙于此项工作时,请仔细考虑“exp_month”是否比“exp_date”更适合该列。(我想会的。)

使用其中一种

  • 字符(5)表示两位数年份,或
  • 字符(7)表示四位数的年份
下面的代码假设两位数的年份,这是匹配我所有信用卡的形式。首先,让我们创建一个有效到期日期表

create table valid_expiration_dates (
  exp_date char(5) primary key
);
现在让我们填充它。此代码仅适用于2013年。您可以通过更改开始日期(当前为“2013-01-01”)和月数(当前为11,通过将开始日期从0添加到11个月,可以轻松调整范围

现在,在数据表中,创建一个char(5)列,并将其中的外键引用设置为valid\u expiration\u dates.exp\u date


当您忙于此项工作时,请仔细考虑“exp_month”是否比“exp_date”更适合该列。(我想会的。)

作为另一个想法,您可以使用int[]创建一些简单的实用程序来完成这项工作:

CREATE OR REPLACE FUNCTION exp_valid(int[]) returns bool LANGUAGE SQL IMMUTABLE as
$$ 
SELECT $1[1] <= 12 AND (select count(*) = 2 FROM unnest($1));
$$;

CREATE OR REPLACE FUNCTION first_invalid_day(int[]) RETURNS date LANGUAGE SQL IMMUTABLE AS 
$$ 
SELECT (to_date($1[2]::text || $1[1]::text, CASE WHEN $1[2] < 100 THEN 'YYMM' ELSE 'YYYYMM' END) + '1 month'::interval)::date;
$$;
然后我们可以将其转换为日期:

postgres=# select first_invalid_day('{04,13}');
 first_invalid_day 
-------------------
 2013-05-01
(1 row)

使用数组不会违反任何规范化规则,因为数组作为一个整体在其域中表示一个值。我们正在存储两个表示单个日期的整数。”{12,2}是2002年12月,而{2,12}是2012年2月。每个表示域的单个值,因此是完全原子的。

另一个想法是,您可以使用int[]为您创建一些简短的实用程序:

CREATE OR REPLACE FUNCTION exp_valid(int[]) returns bool LANGUAGE SQL IMMUTABLE as
$$ 
SELECT $1[1] <= 12 AND (select count(*) = 2 FROM unnest($1));
$$;

CREATE OR REPLACE FUNCTION first_invalid_day(int[]) RETURNS date LANGUAGE SQL IMMUTABLE AS 
$$ 
SELECT (to_date($1[2]::text || $1[1]::text, CASE WHEN $1[2] < 100 THEN 'YYMM' ELSE 'YYYYMM' END) + '1 month'::interval)::date;
$$;
然后我们可以将其转换为日期:

postgres=# select first_invalid_day('{04,13}');
 first_invalid_day 
-------------------
 2013-05-01
(1 row)

使用数组不会违反任何规范化规则,因为数组作为一个整体在其域中表示一个值。我们正在存储两个表示单个日期的整数。”{12,2}是2002年12月,而{2,12}是2012年2月。每个代表域的单个值,因此是完全原子的。

但这意味着每次我插入到期日期的数据时,我都必须添加月份的第一天???也可以同时提取月份和年份吗???而且你的代码不提取月份,而是打印整个月份date@ueg1990是如果使用“检查”约束,则插入第一个,如果不使用,则插入任何一天。edited您也可以使用触发器截断到月的第一天。但这意味着每次我插入到期日期的数据时,我都必须添加月的第一天???也可以同时提取月份和年份吗???而且你的代码不提取月份,而是打印整个月份date@ueg1990是如果使用“检查”约束,则插入第一个,如果不使用,则插入任何一天。edited您也可以使用触发器截断到本月的第一个。我认为另外,创建一个扩展来执行此操作和其他操作可能是值得的。我认为另外,创建一个扩展来执行此操作和其他操作可能是值得的。