Upload
akio-ishida
View
1.078
Download
1
Embed Size (px)
Citation preview
PostgreSQLの
範囲型と排他制約
PostgreSQL勉強会@札幌
2013.12.17
@iakio
範囲型とは
• 範囲をあらわすデータ型(そのまんま)
• 開始と終了を持つ
• 含まれているとか、結合・交差とかの演算子が定義さ
れている
• PostgreSQLでは任意の型を元に新しい範囲型を定義で
きる
Developing Time-Oriented Database Applications in SQLではPeriod型、
Temporal Data and the Relational ModelではInterval型と呼ばれているよ
組み込みの範囲型
範囲型 元の型 離散的か
int4range integer ○
int8range bigint ○
numrange numeric ×
tsrange timestamp ×
tstzrange timestamp with timezone
×
daterange date ○
範囲型の例(日付の範囲)
こうなります
create table members (birthday date,period daterange,name_en text
);
insert into members(birthday, period, name_en) values('1988-10-20', '[2001-08-26, 2012-05-18]', 'Risa Niigaki'),('1988-12-23', '[2003-01-19, 2010-12-15]', 'Eri Kamei'),('1989-11-11', '[2003-01-19, 2013-05-21]', 'Reina Tanaka'),('1989-07-13', '[2003-01-19,]', 'Sayumi Michishige'),('1985-02-26', '[2003-01-19, 2007-06-01]', 'Miki Fujimoto'),...
範囲型の例(整数型)
こうなります
create table level1 (level int,exp_range int4range,primary key(level),exclude using gist (exp_range with &&)
);
insert into level1 values(1, '[0,11)'),(2, '[11,59)'),(3, '[59,164)');
範囲型の作り方色々
'[0,10)' 0以上10未満
'[0,10]' 0以上10以下
'[0,)' 0以上(上限値なし)
'[,)' 上限も下限もなし
'empty' 空の範囲
int4range(0, 10) コンストラクタ関数[0,10)と同じ
int4range(0, 10, '[]') [0,10]と同じ
演算子、関数
http://www.postgresql.jp/document/9.3/html/functions-range.html
離散的、正規化
-- 0以上11未満(11は含まない)-- 離散的な範囲型では正規化される=# select int4range '[0,10]';int4range-----------[0,11)(1 行)
=# select v, int4range '[,11)' @> vfrom generate_series(10, 12) as s(v);v | ?column?----+----------10 | t11 | f12 | f(3 行)
使用例
-- 二人の在籍期間の重複日数=# with q(n1, n2, p) as (select m1.name_en, m2.name_en,m1.period * m2.periodfrom members m1join members m2 on(m1.name_en < m2.name_en)
)select n1, n2, upper(p) - lower(p)
from q where not isempty(p) order by 3;
n1 | n2 | ?column?------------------+-------------------+----------...Reina Tanaka | Sayumi Michishige | 3776Ai Takahashi | Risa Niigaki | 3688Reina Tanaka | Risa Niigaki | 3408Risa Niigaki | Sayumi Michishige | 3408
EXCLUDE制約
• UNIQUE制約は、同じものがないという制約
• EXCLUDE制約は、任意の2行に対して指定し
た演算子が真とならない制約
•=演算子のEXCLUDE制約はUNIQUE制約と同
じ
範囲型のEXCLUDE制約
=# select * from level1;level | exp_range-------+-------------
1 | [0,11)2 | [11,59)3 | [59,164)
...
=# insert into level1 values(100, '[11,12)');ERROR: 重複キーの値が排除制約 "level1_exp_range_excl" に違反していますDETAIL: キー (exp_range)=([11,12)) が既存のキー (exp_range)=([11,59)) と競合しています
タイプ レベル 開始 終了
100万 1 0 11
100万 2 11 59
100万 3 59 164
150万 1 0 16
150万 2 16 99
150万 3 89 246
スカラ型と範囲型の組み合わせ
-- gistは標準では = を使えないcreate extension btree_gist;
create table level2 (exp_type int,level int,exp_range int4range,primary key(exp_type, level),exclude using gist (exp_type with =, exp_range with &&)
);
insert into level2 values(100, 1, '[0,11)'),(100, 2, '[11,59)'),...(150, 1, '[0,16)'),(150, 2, '[16,89)'),
こんなに便利
•境界を含む、含まないを表現できる
•上限、下限の無い範囲を表現できる
•インデックスが効く
• EXCLUDE制約で、重複していないことを保証
できる
•豊富な演算子