2017-06-11 18 views
2

内の各カスタム型の素子上の制約、私はこのカスタムタイプがあるとします。PostgreSQLの - 配列

CREATE TYPE post AS (
    title varchar(100), 
    content varchar(10000) 
); 

そして、この表:コードにコメントしたよう

CREATE TABLE blogs (
    -- Constraint on one custom type element: 
    one_post post NOT NULL 
    CHECK ((one_post).title IS NOT NULL AND (one_post).content IS NOT NULL), 

    -- Constraint on array elements: 
    posts post[] NOT NULL CHECK (???) 
); 

を、私はあることを確認したいですpostsの各要素のタイトルと内容はNOT NULLですが、その表現方法はわかりません。これを行う正しい方法は何ですか?

(P.S:私は正しい道が私のスキーマを正規化することである知っている、私は私が行うことができます尋ね場合は、単に興味があります。)

答えて

3

通常、保存された機能を使用し、複雑なチェック制約のために。

便利な方法でそれを作るために私の試みがあります:すべての

まず:ここ

create type post as (
    title varchar(100), 
    content varchar(10000) 
); 

create function is_filled(post) returns bool immutable language sql as $$ 
    select $1.title is not null and $1.content is not null 
$$; 

with t(x) as (values(('a','b')::post), (('a',null)::post), ((null,null)::post)) 
select *, is_filled(x), (x).is_filled from t; 
 
╔═══════╤═══════════╤═══════════╗ 
║ x │ is_filled │ is_filled ║ 
╠═══════╪═══════════╪═══════════╣ 
║ (a,b) │ t   │ t   ║ 
║ (a,) │ f   │ f   ║ 
║ (,) │ f   │ f   ║ 
╚═══════╧═══════════╧═══════════╝ 

あなたは個人的に、私は二番目に好き(関数呼び出しの2つの構文を見ることができます - それはより多くのOOPのような)

次です:

create function is_filled(post[]) returns bool immutable language sql as $$ 
    select bool_and((x).is_filled) and $1 is not null from unnest($1) as x 
$$; 

with t(x) as (values(('a','b')::post), (('a',null)::post), ((null,null)::post)) 
select (array_agg(x)).is_filled from t; 

名前は同じだがパラメータが異なる関数を使用できることに注意してください。PostgreSQLではOkです。

最後に:

create table blogs (
    one_post post check ((one_post).is_filled), 
    posts post[] check ((posts).is_filled) 
); 

insert into blogs values(('a','b'), array[('a','b'),('c','d')]::post[]); -- Works 
insert into blogs values(('a','b'), array[('a','b'),(null,'d')]::post[]); -- Fail 
insert into blogs values(('a',null), array[('a','b')]::post[]); -- Fail 

PS:私たちの実験をクリアするためのスクリプト:

/* 
drop table if exists blogs; 
drop function if exists is_filled(post); 
drop function if exists is_filled(post[]); 
drop type if exists post; 
*/ 
+0

ありがとう!非常にエレガントなソリューション。 –