2016-12-13 18 views
0

insertまたはupdateからテーブルを更新しようとしましたが、PostgreSQLのビューで呼び出します。ここで私は何をすべきかの簡単な例です:ここではトリガ&挿入プロシージャを使用してビューにデータを挿入するとき、「空白」挿入を避けるにはどうすればよいですか?

[Person] table: 
id | lastname | firstname | city | age 

[Person_View] table: 
id | lastname | firstname | city 

は、トリガおよび関連手順です:

CREATE TRIGGER tg_update_person_view 
    INSTEAD OF INSERT OR UPDATE OR DELETE ON 
     Person_View FOR EACH ROW EXECUTE PROCEDURE update_person_view_table(); 

CREATE OR REPLACE FUNCTION update_person_view_table() 
RETURNS TRIGGER 
LANGUAGE plpgsql 
AS $function$ 
    BEGIN 
     IF TG_OP = 'INSERT' THEN 
     INSERT INTO Person (id, lastname, firstname) 
     VALUES(NEW.id, NEW.lastname, NEW.firstname); 
     RETURN NEW; 
     ELSIF TG_OP = 'UPDATE' THEN 
     UPDATE Person 
     SET id=NEW.id, lastname=NEW.lastname, firstname=NEW.firstname 
     WHERE id=OLD.id; 
     RETURN NEW; 
     END IF; 
     RETURN NEW; 
    END; 
$function$; 

私が行う場合:

INSERT INTO Person_View (id, city) VALUES ('3', 'Berlin') 

A IDのみの行がビューと親テーブルに追加されます。

値が挿入されている列にはプロシージャで定義された "マッピング"があり、マッピングされた列がない場合は続行されません。

+0

を、単一のテーブルに基づいてビューが自動的に更新可能です。 – klin

+0

私は、この単純化された例が自動的に更新可能であると言いました。私の実際の状況は、私は複数のテーブルに基づいてビューがあり、私はこれらの空のレコードが発生しないようにしています。 – kaycee

答えて

1

あなたは、テーブルの上に例えばをチェック制約を定義することができます。:

create table person(
    id int primary key, 
    lastname text, 
    firstname text, 
    city text, 
    age int, 
    check(coalesce(lastname, firstname, city, age::text) is not null) 
); 

insert into person (id) 
values (1); 

ERROR: new row for relation "person" violates check constraint "person_check" 
DETAIL: Failing row contains (1, null, null, null, null). 

ソリューションは関係なく、テーブルに基づいて、任意のビューが作成されたかどうか動作します。

1

簡略化するためにON DELETEのためのトリガー機能&トリガーがあります。 (とにかくON DELETEは何もしていません)

CHECKのような制約klin suggestedは良い考えのようです。あなたはCOALESCEとキャストは必要ありません。 の値がNULLであることを確認してください。

CHECK (NOT ROW(lastname, firstname) IS NULL) -- ROW keyword is noise 

この行では、少なくとも1つのnotnull値が強制的に適用されます。任意の数の列および任意のデータ型に対して機能します。

特に、ROW(lastname, firstname) IS NOT NULLは同じではなく、動作しないことに注意してください。詳細説明:CHECK制約がオプションでない場合

、あなたはトリガーで同じ表現を使用することができます - トリガ機能に追加するよりも高速であるべきです。

CREATE TRIGGER tg_update_person_view 
INSTEAD OF INSERT OR UPDATE ON Person_View 
FOR EACH ROW 
WHEN (NOT (NEW.lastname, NEW.firstname) IS NULL) -- more columns? 
EXECUTE PROCEDURE update_person_view_table(); 

WHEN式はTRUEに評価されない場合は

Also, a trigger definition can specify a Boolean WHEN condition, which will be tested to see whether the trigger should be fired. In row-level triggers the WHEN condition can examine the old and/or new values of columns of the row.

The manual on CREATE TRIGGER:は、トリガー機能であっても呼び出されません - それは does not proceedよう要請しました。


ただし、私はあなたのトリガーを逃したINSTEAD OFです。あなたが関数本体にチェックを移動する必要があり、この場合にはThe manual:

INSTEAD OF triggers do not support WHEN conditions.

:あなたがルールやトリガを必要としない9.3+のPostgresでは

IF NOT (NEW.lastname, NEW.firstname) IS NULL THEN 
    -- do stuff 
END IF; 
+0

私はこのエラーが発生します: 'ERROR:INSTEAD OFトリガはWHEN条件を持つことができません********** Error **********'。 – kaycee

+0

@kaycee:ああ、申し訳ありません。 'INSTEAD'トリガではありません。この場合、小切手を機能に移す必要があります。 (あなたは 'CHECK'制約を考慮しましたか?) –

関連する問題