1

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

4

3 回答 3

4

您可以将日期限制为该月的第一天:

create table customer (
    cc_expire date check (cc_expire = date_trunc('month', cc_expire))
);

现在这失败了:

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

但输入哪一天并不重要。您只会检查月份:

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
于 2013-02-16T22:56:17.977 回答
0

作为另一个想法,您基本上可以使用 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 exp_valid('{04,13}');
 exp_valid 
-----------
 t
(1 row)

postgres=# select exp_valid('{13,04}');
 exp_valid 
-----------
 f
(1 row)

postgres=# select exp_valid('{04,13,12}');
 exp_valid 
-----------
 f
(1 row)

然后我们可以将它们转换为日期:

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

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

于 2013-03-04T12:23:07.067 回答
0

使用任一

  • char(5) 表示两位数年份,或
  • char(7) 表示四位数年份。

下面的代码假定两位数的年份,这是匹配我所有信用卡的形式。首先,让我们创建一个有效到期日期表。

create table valid_expiration_dates (
  exp_date char(5) primary key
);

现在让我们填充它。此代码仅适用于 2013 年。您可以通过更改开始日期(当前为 '2013-01-01')和“月数”(当前为 11,这样您可以通过添加从距开始日期 0 到 11 个月)。

with all_months as (
  select '2013-01-01'::date + (n || ' months')::interval months
  from generate_series(0, 11) n
)
insert into valid_expiration_dates
select to_char(months, 'MM') || '/' || to_char(months, 'YY') exp_date
from all_months;

现在,在您的数据表中,创建一个 char(5) 列,并将其中的外键引用设置为 valid_expiration_dates.exp_date。

当您忙于这个时,请认真考虑“exp_month”是否可能比“exp_date”更适合该列。(我认为会的。)

于 2013-02-17T01:33:39.900 回答