2016-02-13 40 views
-1

我需要對數據類型具有CHECK約束,該數據類型必須具有010000129999的格式,並保留零,但我不知道如何實現這個。基本上,顯而易見,這是一個數字的月份。需要對SQL中的數字應用CHECK約束和長度檢查

我試過使用numeric(6,0)integer,但我不知道如何使用保留前導零的CHECK。

我也不知道如何使用character varying(6)更容易實現這一點,也不是首選,因爲我認爲在應用程序層使用它會更困難。

有什麼建議嗎?我正在使用Postgres。

+0

如果你想存儲月份和年份,我寧願去兩個整數列。 –

+0

我問過那個,但沒有辦法。 – cst1992

+1

'yyyymm'格式('201512,201601')怎麼樣? – lad2025

回答

-1

我結束了使用YYYYMM格式,由@ lad2025的建議。

1

三種方法(可能還有更多):

 -- (1) use a date type for a date 
CREATE TABLE mmyyyy 
     (id SERIAL NOT NULL PRIMARY KEY 
     , yyyymm01 DATE NOT NULL CHECK (date_trunc('month', yyyymm01) = yyyymm01) 
     ); 

INSERT INTO mmyyyy(yyyymm01) VALUES 
('1901-01-01') ,('0001-01-01') ,('2016-02-01') ; 

INSERT INTO mmyyyy(yyyymm01) VALUES ('1901-13-01') ; -- should fail 
INSERT INTO mmyyyy(yyyymm01) VALUES ('2016-02-13') ; -- should fail 

SELECT id, to_char(yyyymm01, 'mmyyyy') AS this FROM mmyyyy ; 

     -- (2) use a char type and apply the check on the cast_to_int result 
CREATE TABLE omg 
     (id SERIAL NOT NULL PRIMARY KEY 
     , mmyyyy varchar(6) NOT NULL CHECK (
       length(mmyyyy) = 6 AND 
       left(mmyyyy,2)::integer BETWEEN 1 AND 12) 
     ); 

INSERT INTO omg(mmyyyy) VALUES ('011901') ,('010001') ,('022016') ; 
INSERT INTO omg(mmyyyy) VALUES ('131901') ; -- should fail 
INSERT INTO omg(mmyyyy) VALUES ('002016') ; -- should fail 

SELECT id, mmyyyy FROM omg ; 

     -- (3) use an int type and apply the check to the value/10000 
CREATE TABLE wtf 
     (id SERIAL NOT NULL PRIMARY KEY 
     , mmyyyy INTEGER NOT NULL CHECK (
       mmyyyy/10000 BETWEEN 1 AND 12) 
     ); 

INSERT INTO wtf(mmyyyy) VALUES 
(11901) ,(10001) ,(22016) 
     ; 

INSERT INTO wtf(mmyyyy) VALUES (131901) ; -- should fail 
INSERT INTO wtf(mmyyyy) VALUES (2016) ; -- should fail 

SELECT id, to_char(mmyyyy, '099999') AS mmyyyy 
FROM wtf 
     ; 

     -- (extra) use an date/char/int type AS the baseclass for a domain(or type): 
     -- (this can come in handy if the "type" is used in more than one place) 
CREATE DOMAIN omgwtf AS 
     INTEGER CHECK (value/10000 BETWEEN 1 AND 12) 
     ; 

CREATE TABLE tralala 
     (id SERIAL NOT NULL PRIMARY KEY 
     , mmyyyy omgwtf NOT NULL 
     ); 

INSERT INTO tralala(mmyyyy) VALUES 
(11901) ,(10001) ,(22016) 
     ; 

INSERT INTO tralala(mmyyyy) VALUES (131901) ; -- should fail 
INSERT INTO tralala(mmyyyy) VALUES (2016) ; -- should fail 

SELECT id, to_char(mmyyyy, '099999') AS mmyyyy 
FROM tralala 
     ; 

輸出:

CREATE TABLE 
INSERT 0 3 
ERROR: date/time field value out of range: "1901-13-01" 
LINE 1: INSERT INTO mmyyyy(yyyymm01) VALUES ('1901-13-01') ; 
              ^
HINT: Perhaps you need a different "datestyle" setting. 
ERROR: new row for relation "mmyyyy" violates check constraint "mmyyyy_yyyymm01_check" 
DETAIL: Failing row contains (4, 2016-02-13). 
id | this 
----+-------- 
    1 | 011901 
    2 | 010001 
    3 | 022016 
(3 rows) 

CREATE TABLE 
INSERT 0 3 
ERROR: new row for relation "omg" violates check constraint "omg_mmyyyy_check" 
DETAIL: Failing row contains (4, 131901). 
ERROR: new row for relation "omg" violates check constraint "omg_mmyyyy_check" 
DETAIL: Failing row contains (5, 002016). 
id | mmyyyy 
----+-------- 
    1 | 011901 
    2 | 010001 
    3 | 022016 
(3 rows) 

CREATE TABLE 
INSERT 0 3 
ERROR: new row for relation "wtf" violates check constraint "wtf_mmyyyy_check" 
DETAIL: Failing row contains (4, 131901). 
ERROR: new row for relation "wtf" violates check constraint "wtf_mmyyyy_check" 
DETAIL: Failing row contains (5, 2016). 
id | mmyyyy 
----+--------- 
    1 | 011901 
    2 | 010001 
    3 | 022016 
(3 rows) 

CREATE DOMAIN 
CREATE TABLE 
INSERT 0 3 
ERROR: value for domain omgwtf violates check constraint "omgwtf_check" 
ERROR: value for domain omgwtf violates check constraint "omgwtf_check" 
id | mmyyyy 
----+--------- 
    1 | 011901 
    2 | 010001 
    3 | 022016 
(3 rows) 
+0

無法創建新表格;該字段應該是現有字段的一部分。無法爲此字段創建單獨的Java類。另外,(3)不適用,因爲應保留0。 – cst1992

+0

你的'numeric(6,0)'是(雖然是一個不好的選擇),與我的整數版本非常相似。 Java是無關緊要的,儘管它似乎允許強打字 – wildplasser