2013-02-16 2 views
1

고객 표를 생성 중입니다. 속성 중 하나가 만료일 인 신용 카드 여야합니다. 형식을 '월간'으로 지정합니다. 어떤 데이터 유형을 사용해야합니까? 나는 날짜를 사용하고 싶지만 형식은 년/월/일입니다. 형식을 월 및 연도로만 제한하는 다른 방법이 있습니까?PostgreSql - 표에 YEar 및 월 추가

당신은 달 1 일에 날짜를 제한 할 수

답변

4

:

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). 

을 그리고이 작품 :

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

지금이 실패

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 
+0

하지만 이것은 매월 데이터를 삽입 할 때마다 만료일의 첫날을 추가해야한다는 것을 의미합니까 ??? 또한 같은 시간에 월과 연도를 모두 추출 할 수 있습니까 ??? – ueg1990

+0

또한 ur 코드는 그 달을 추출하지 않으며, 전체 날짜를 인쇄합니다. – ueg1990

+0

@ ueg1990 예. 검사 제약 조건을 사용하면 첫 번째를 삽입하고 그렇지 않으면 요일을 삽입하십시오. 수정 됨 –

0

사용 중

  • 문자를 (5)에 대한 두 자리 연도 또는
  • 4 자리 연도의 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; 

이제, 데이터 테이블에서 숯불 (5) 열을 생성하고, 그것을 valid_expiration_dates.exp_date에서 외래 키 참조를 설정.

이 작업에 익숙하시는 동안 "exp_month"가 "exp_date"보다 해당 열의 더 나은 이름인지 생각해보십시오. (나는 것이라고 생각합니다.)

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) 

이 배열을 사용하면 t가 정규화 규칙을 위반하지 않습니다. 그는 배열 전체가 그 영역에서 하나의 값을 나타냅니다. 우리는 하나의 날짜를 나타내는 두 개의 정수를 저장하고 있습니다. '{12.2}'는 2002 년 12 월이고 '{2,12}'는 2012 년 2 월입니다.각각은 도메인의 단일 값을 나타내므로 완전한 원자입니다.

+0

이 작업을 수행하는 데 확장 기능을 추가 할 가치가 있다고 생각합니다. –