2017-01-23 24 views
3

在我的測試應用程序中,我在PostgreSQL9.6實例上使用了以下設置的數據庫。Postgresql具有非空限制的可更新視圖

CREATE TABLE public.parties 
(
    id integer NOT NULL DEFAULT nextval('parties_id_seq'::regclass), 
    party_type_id text NOT NULL, 
    fullname text NOT NULL DEFAULT ''::text, 
    created_at timestamp without time zone NOT NULL DEFAULT now(), 
    CONSTRAINT parties_pkey PRIMARY KEY (id, party_type_id), 

    (... extra sql not relevant to the question ...) 
); 

CREATE TABLE public.party_people 
(
    id integer NOT NULL, 
    gender text NOT NULL DEFAULT ''::text, 
    CONSTRAINT party_people_pkey PRIMARY KEY (id), 

    (... extra sql not relevant to the question ...) 
); 


CREATE OR REPLACE VIEW public.people AS 
SELECT t1.id, 
    t1.party_type_id, 
    t1.fullname, 
    t2.gender, 
    t1.created_at 
    FROM parties t1 
    JOIN party_people t2 ON t1.id = t2.id; 


CREATE OR REPLACE FUNCTION public.people_vw_update_func() 
    RETURNS trigger AS 
    LANGUAGE plpgsql 
    $BODY$  
    BEGIN 
    IF TG_OP = 'INSERT' THEN 
     IF NEW.id IS NULL THEN 
     NEW.id = NEXTVAL('parties_id_seq'); 
     END IF; 

     INSERT INTO parties 
     VALUES (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at); 

     INSERT INTO party_people 
     VALUES (NEW.id, NEW.party_type_id, NEW.gender); 
     RETURN NEW; 
    ELSIF 
     (... extra sql to deal with DELETE and UPDATE cases ...) 
    END IF; 
    RETURN NEW; 
    END; 
    $BODY$ 

CREATE TRIGGER people_vw_update_trig 
    INSTEAD OF INSERT OR UPDATE OR DELETE 
    ON people 
    FOR EACH ROW 
    EXECUTE PROCEDURE people_vw_update_func(); 

我試圖創建Postgres的可更新視圖,我可以,我可以通過people視圖管理人員的數據,而不是手動編寫查詢到在兩個表中的數據拆分。

我遇到的問題是,我不能對視圖後盾桌的NON NULL約束,否則查詢,如:

INSERT INTO people (fullname, gender) 
VALUES ("James Jones", "male"); 

將在created_at失敗,因爲約束和因爲在NEW.create_at觸發功能顯然是NULL

所以我的問題是: 有誰知道的方法來處理一個更新的視圖內NON NULL約束無R esorting喜歡的東西:

IF NEW.created_at IS NULL THEN 
    INSERT INTO parties 
    VALUES (NEW.id, NEW.party_type_id, NEW.fullname); 
ELSE  
    INSERT INTO parties 
    VALUES (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at); 
END IF; 

雖然這種解決方案會爲一列工作,如果有更多的,則解決方案會帶來麻煩的真快。

EDIT

最後,我實現爲通過瘋狂科學家建議的解決方案。對於任何人誰可能在將來我最終的解決辦法是在這個問題絆倒:

ALTER TABLE people 
    ALTER COLUMN created_at SET DEFAULT now() 

視圖觸發所有我需要做的是設置在相應的表中的值作爲視圖會採取這種方式關心使用默認值填充NEW變量,其中NULL通常是。

回答

2

您可以在視圖上創建默認值,而不僅僅是在表格上。如果你有一個可更新的視圖,我只是將基礎表的默認值添加到它。 NOT NULL約束可以由底層表強制執行,但如果沒有提供值,INSTEAD OF觸發器將看到默認值,而不是有問題的NULL。

視圖上默認值的語法與更改表的默認值的語法相同。

1

你只可以做:

IF NEW.created_at IS NULL THEN 
    NEW.created_at = now() ; 
END IF ; 
/* Do the same for all columns requiring default values */ 

INSERT INTO 
     parties 
     (id,  party_type_id,  fullname,  created_at) 
VALUES 
     (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at); 

或也

INSERT INTO 
     parties 
     (id,  party_type_id,  fullname,  created_at) 
VALUES 
     (NEW.id, NEW.party_type_id, NEW.fullname, coalesce(NEW.created_at, now())); 

檢查documentation on Coalesce

+1

+1用於推薦coalesce函數。這幾乎是我正在尋找的確切解決方案,但最終我選擇了「瘋狂科學家」的答案,因爲我認爲將默認值放在視圖上更適合我的目的。 – Zerodestiny