範囲型は、ある要素型(その範囲の派生元型と呼ばれます)の値の範囲を表わすデータ型です。timestampの範囲は、会議室が予約されている時間の範囲を表すのに使うことができるでしょう。range」の短縮)で、timestampが派生元型となります。派生元型には完全な順序がなければなりません。これは、要素の値が範囲の前、中間、後のどこにあるのか明確に定義されている必要があるからです。範囲型は、一つの範囲内の多くの要素の値を表現できる、また、範囲の重なりなどの概念が明確に表現できる、などの理由で便利です。スケジューリングのために時刻と日付の範囲を使うのがもっとも簡単な例ですが、価格の範囲、機器による測定値の範囲などといったものにも利用できるでしょう。組み込みの範囲型PostgreSQLには、以下の組み込みの範囲型があります。dateの範囲この他にも、独自の範囲型を定義することができます。TYPEを参照してください。9.51を参照してください。空でない範囲には必ず2つの境界、つまり下限値と上限値があります。これらの値の間にある値はすべてその範囲に含まれます。閉じた境界とは、その境界値自体が範囲に含まれることを意味し、開いた境界とは、その境界値が範囲に含まれないことを意味します。範囲を文字列の形式で表すとき、閉じた下限値は「[」で、開いた下限値は「(」で表します。同様に、閉じた上限値は「]」で、開いた上限値は「)」で表します。8.17.5を参照してください。)関数lower_incおよびupper_incはそれぞれ、範囲の下限値と上限値が閉じているかどうかを検査します。範囲の下限値は省略することができ、このとき、上限値より小さいすべての値はその範囲に含まれることになります。同じように、範囲の上限値も省略することができ、このときは、下限値より大きいすべての値がその範囲に含まれることになります。下限値と上限値が両方とも省略されたときは、その要素型のすべての値がその範囲に含まれるとみなされます。これは、それぞれ、下限値が「マイナス無限大」である、あるいは、上限値が「プラス無限大」である、と見なすことと同等です。これらの無限大の値は範囲型の値にはならない、ということ、そして範囲の一部になることはできない、ということに注意してください。そのように書いてもそれは自動的に開いた境界に変換されます。)いくつかの要素型には「無限大」の概念がありますが、範囲型の機能に関する限り、これは一つの値として扱われます。timestampの範囲で[today,]の意味は[today,)と同じです。後者はtimestampの特別な値infinityを含みません。関数lower_infおよびupper_infはそれぞれ範囲の下限値と上限値が無限大かどうかを検査します。範囲値の入力は、以下の形式の一つに従わなければなりません。(lower-bound,upper-bound)(lower-bound,upper-bound][lower-bound,upper-bound)[lower-bound,upper-bound]empty前にも述べたとおり、丸括弧と大括弧は下限値と上限値が開いているか閉じているかを表します。最後の形式がemptyであることに注意してください。これは空の範囲(範囲に含まれる値が1つもない)を表します。lower-boundは、その派生元型の有効な入力値となる文字列か、あるいは省略して下限値がないことを指定するかのいずれかです。同様に、upper-boundは、その派生元型の有効な入力値となる文字列か、あるいは省略して上限値がないことを指定するかのいずれかです。境界値は"(二重引用符)で括ることができます。これは特に境界値が丸括弧、大括弧、カンマ、二重引用符、あるいはバックスラッシュを含んでいる場合に必要となります。しなければ、これらの文字は範囲の構文の一部とみなされてしまうからです。二重引用符あるいはバックスラッシュを引用符で括られた境界値の中に入れるには、その直前にバックスラッシュを入れてください。(また、SQLの文字列リテラルと同じように、二重引用符で括られた境界値の中で二重引用符を2つ続けることで1つの二重引用符を表すこともできます。引用符で括る代わりに、範囲の構文の一部とみなされるすべての文字をバックスラッシュでエスケープする、ということもできます。境界値として空文字列を指定するには""と書いてください。何も書かないと、境界値が無限大であることになってしまいます。境界値の前後に空白文字を入れることができますが、括弧内にある空白文字はすべて下限値あるいは上限値の一部とみなされます。(このことは、要素型によっては重要かもしれませんし、重要でないかもしれません。)注記これらの規則は、複合型のリテラルにフィールド値を記述する時と非常によく似ています。詳細な解説は8.16.6を参照してください。3を含み、7を含まない。範囲型には、その範囲型と同じ名前のコンストラクタ関数があります。コンストラクタ関数を使うと、境界値の指定で余計な引用を使わずに済むので、リテラルの定数で範囲を記述するよりも便利なことが多いでしょう。コンストラクタ関数は2つ、または3つの引数をとります。開いた上限値)という標準的な形式の範囲を生成します。引数が3つの形式では、3番目の引数で指定した形式の境界の範囲を生成します。3番目の引数は、以下の文字列のいずれかでなければなりません。「()」、「(]」、「[)」、または「[]」。離散的な範囲とは、integerやdateのように明確に定義された「ステップ」のある要素型の範囲のことです。このような型において、2つの要素の間に有効な値が1つもないとき、その2つの要素は隣接している、と言います。これは連続的な範囲と対照的です。連続的な範囲では、任意の2つの値について、それらの間に別の値を見つけることが、いつでも(あるいは、ほとんどいつでも)可能です。numeric型やtimestamp型の範囲は連続的です。(timestampの精度は限界があるので、理論的には離散的として取り扱うことも可能ですが、ステップの大きさについて関心がないのが普通ですから、連続的であると考える方が良いでしょう。)離散的な範囲型に関するもう1つの考え方は、各要素の値について、「次」あるいは「前」の値というのものが明確に考えられるか、ということです。これを知っていれば、範囲の境界の閉じた表現、あるいは開いた表現について、その値の次、あるいは前の値を使って、表現を変換することができます。整数の範囲型[4,8]と(3,9)は同じ値の集合を意味しますが、これがnumericの範囲型であったならそうではありません。離散的な範囲型はその要素型で使いたいステップのサイズを認識する正規化関数を持つべきです。正規化関数は同等な値の範囲型を、同一の表現に、特に、閉じた境界、開いた境界について一定の形式に変換します。正規化関数が指定されない場合、異なる形式の範囲は必ず等しくないものとして扱われます。これは例え、それらが現実的に同じ値の集合であったとしても、等しくないとされます。組み込みの範囲型であるint4range、int8range、およびdaterangeはいずれも閉じた下限値と開いた上限値、つまり[)の正規化形式を使います。ユーザ定義の範囲型はこれとは別の方式を使うことができます。独自の範囲型を定義することもできます。ありそうな理由は、組み込みの範囲型では、その派生元型についての範囲型が提供されていない、ということでしょう。float8を派生元型とする新しい範囲型を定義するには次のようにします。5.678]'::floatrange;float8には意味のある「ステップ」がないので、この例では正規化関数を定義していません。独自の範囲型を定義すると、派生元型とは異なるB-tree演算子クラスや照合順を指定でき、どの値が指定の範囲に入るかを決定するソート順を変更することもできます。TYPEコマンドでcanonical(正規化)関数を指定する必要があります。正規化関数は、範囲の値を入力として受け取り、それと同等な範囲の値を返さなければなりません。戻り値は、入力値とは異なる境界値と形式になっているかもしれません。8)の正規化出力は、同一である必要があります。異なる形式の同等な値が、いつでも同じ形式の同じ値に変換されるのであれば、正規化出力の形式は何であってもかまいません。正規化関数は、閉じた境界、開いた境界の形式を調整するだけではありません。派生元型が格納できるよりも大きなサイズのステップを使いたい場合は境界値を丸めることもあります。timestampの範囲型をステップのサイズを1時間として定義することができます。このとき、正規化関数は1時間の倍数になっていない境界値を丸める必要があります。その代わりにエラーを投げることもできます。GiSTまたはSP-GiSTインデックスと一緒に使われる範囲型は、派生元型の差分、つまりsubtype_diff関数を定義すべきです。(そのインデックスはsubtype_diffがなくても機能しますが、差分関数が提供されている時に比べると、あまり効果的でないことが多いでしょう。派生元型の差分関数は、2つの派生元型の入力値をとり、その差分(つまり、X引くY)をfloat8型の値として返します。上の例では、通常のfloat8のマイナス演算子が呼び出す関数float8miを使うことができますが、それ以外の派生元型では何らかの型変換が必要となるでしょう。差分をいかにして数字で表現するかについて、創造的な発想も必要になるかもしれません。可能な限りにおいて、subtype_diff関数は、選択した演算子クラスと照合順が示唆するソート順と矛盾しないようにすべき、つまり、ソート順で、1番目の引数が2番目の引数より上に来る場合は、必ず差分関数の結果は正になるべきです。subtype_diff関数の単純化されすぎていない例を以下に示します。TYPEを参照してください。インデックス範囲型の列にGiSTおよびSP-GiSTインデックスを作成することができます。(during);GiSTあるいはSP-GiSTインデックスがあると、以下の範囲演算子を含む検索を高速に実行できます。9.50を参照してください)。範囲型の列にB-treeおよびハッシュインデックスを作ることもできます。これらのインデックスについては、基本的に、等値演算のみが有効な範囲の演算です。範囲の値についてB-treeのソート順が、<および>演算子について定義されていますが、現実にはこの順序はあまり意味がなく、有効ではありません。範囲型のB-treeとハッシュのサポートは実際にインデックスを作ることよりも、むしろ、検索時に内部的にソートやハッシュをできるようにするのが主な目的です。範囲の制約UNIQUEはスカラー値には自然な制約ですが、範囲型には通常は適当ではありません。EXCLUDEを参照してください)。排他制約により、範囲型について「重なりがない」などといった制約を指定することができます。&&));この制約は、テーブル上で重なりのある値が同時に存在することを防ぎます。15:00:00")).btree_gistの拡張を使って通常のスカラーのデータ型について排他制約を定義することができます。これをさらに範囲の排他と組み合わせることで大きな柔軟性を得ることができます。btree_gistをインストールした時、次の制約は範囲の重なりについて、会議室の部屋番号も同じ時にのみ拒絶します。