無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

4.2. 評価式

評価式は、例えば SELECT コマンドの目的リストとして、 INSERT UPDATE の新しい列の値として、もしくはいくつかのコマンドの検索条件として様々な文脈の中で使われます。 評価式の結果は、テーブル式の結果(つまりテーブル)から区別するために、 スカラ と呼ばれることもあります。 したがって、評価式は スカラ式 (またはもっと簡単に )とも呼ばれます。 式の構文によって、算術、論理、集合などの演算を行う基本的な部分で値の計算を行うことができます。

評価式は下記のうちのいずれかです。

これ以外にも、式として分類されるけれども一般的な構文規約には従わない、いくつかの構成要素があります。 これらは一般的に関数あるいは演算子の意味を持ちます。 第9章 の該当部分で説明されています。 例を挙げると IS NULL 句があります。

項4.1.2 で既に定数については説明しました。 続く節では残りのオプションについて説明します。

4.2.1. 列の参照

列は、下記のような形式で参照することができます。



correlation

.

columnname

correlation は、テーブル名(スキーマで修飾されている場合もあります)、あるいは FROM 句で定義されたテーブルの別名です。 相関名と区切り用のドットは、もし列名が現在の問い合わせで使われる全てのテーブルを通して一意である場合は省略することができます。 ( 第7章 も参照してください)。

4.2.2. 位置パラメータ

位置パラメータ参照は、外部からSQL文に渡される値を示すために使用されます。 パラメータはSQL関数定義およびプリペアド問い合わせの中で使用されます。 また、クライアントライブラリの中には、SQLコマンド文字列とデータ値を分離して指定できる機能をサポートするものもあります。 この場合、パラメータは行外データ値を参照するために使用されます。 パラメータ参照の形式は以下の通りです。

$

number

例えば、関数 dept の定義が以下のようにされたとします。

CREATE FUNCTION dept(text) RETURNS dept
    AS $$ SELECT * FROM dept WHERE name = $1 $$
    LANGUAGE SQL;

ここで $1 は関数が呼び出される時に最初の関数引数の値を参照します。

4.2.3. 添字

配列の値を与える式の場合、特定の配列要素の値は以下のように記述することで展開されます。



expression

[

subscript

]

また、複数の要素をまたがる( "配列の一部分" )場合は以下のように記述することで展開されます。



expression

[

lower_subscript

:

upper_subscript

]

(ここで大括弧 [ ] はリテラルとして現れています。) 各 subscript は自身が式であり、整数値を生成しなければなりません。

一般的には、配列 expression は括弧で括らなければなりませんが、添字が付いた式が単なる列参照や位置パラメータであった場合、その括弧を省略することができます。 以下に例を示します。

mytable.arraycolumn[4]
mytable.two_d_column[17][34]
$1[10:42]
(arrayfunction(a,b))[42]

最後の例では括弧が必要です。 配列の詳細は 項8.15 を参照してください。

4.2.4. フィールド選択

式が複合型(行型)の値を生成する場合、行の特定のフィールドは以下のように記述することで展開できます。



expression

.

fieldname

一般的には、行 expression は括弧で括らなければなりません。 しかし、選択元となる式が単なるテーブル参照や位置パラメータの場合、括弧を省略することができます。 以下に例を示します。

mytable.mycolumn
$1.somecolumn
(rowfunction(a,b)).col3

(したがって、修飾された列参照は実際のところ、単なるこのフィールド選択構文の特殊な場合です。)重要となる特殊な場合としては、複合型のテーブル列からフィールドを抽出するときです。

(compositecol).somefield
(mytable.compositecol).somefield

compositecol がテーブル名でなく列名であること、または2番目の場合の mytable がスキーマ名でなくテーブル名であることを示すため丸括弧が要求されます。

SELECT列のリスト( 項7.3 参照)に .* を記述することで、複合型の全ての値を問い合わせることが可能です。

(compositecol).*

4.2.5. 演算子の呼び出し

演算子の呼び出しには以下の3構文が可能です。

expression operator expression (二項中置演算子)
operator expression (単項前置演算子)
expression operator (単項後置演算子)

ここで operator トークンは、 項4.1.3 構文規則に従うもの、もしくはキーワード AND OR NOT のいずれか、または以下の形式の修飾された演算子名です。


OPERATOR(


schema


.


operatorname


)

具体的にどんな演算子が存在し、それが単項か二項かどうかは、システムやユーザによってどんな演算子が定義されたかに依存します。 第9章 にて、組み込み演算子について説明します。

4.2.6. 関数呼び出し

関数呼び出しの構文は、関数名(スキーマ名で修飾されている場合があります)に続けてその引数を丸括弧で囲んで列挙したものです。



function_name

 ([


expression

 [
, 

expression

 ... 
]
] )

例えば、以下のものは2の平方根を計算します。

sqrt(2)

組み込み関数の一覧は 第9章 にあります。 他の関数はユーザが追加できます。

引数には名前を任意で付与することができます。詳細は 項4.3 を見て下さい。

注意: 複合型の単一引数をとる関数はフィールド選択構文をオプショナルに使って呼び出すことができます。反対に関数形式でフィールド選択を記述することもできます。この記述方法は col(table) table.col となり、どちらを使っても変わりありません。 PostgreSQL では "計算された領域" のエミュレートをする関数の利用が可能なため、これはSQL標準の振る舞いではなく PostgreSQL 独自機能となります。詳しくは 項35.4.3 を参照してください。

4.2.7. 集約式

集約式 は、問い合わせによって選択される行に対して集約関数が適用されることを意味します。 集約関数は、例えば入力の合計や平均などのように、複数の入力を単一の出力値にします。 集約式の構文は下記のうちのいずれかです。



aggregate_name

 (

expression

 [ , ... ] [ 

order_by_clause

 ] )


aggregate_name

 (ALL 

expression

 [ , ... ] [ 

order_by_clause

 ] )


aggregate_name

 (DISTINCT 

expression

 [ , ... ] [ 

order_by_clause

 ] )


aggregate_name

 ( * )

ここで、 aggregate_name は事前に定義された集約(スキーマ名で修飾された場合もあります)、 expression はそれ自体に集約式またはウィンドウ関数呼び出しを含まない任意の値評価式、 order_by_clause は後述の省略可能な ORDER BY です。

集約式の最初の構文は、それぞれの入力行に対して1回ずつ集計を呼び出します。 ALL はデフォルトなので、2つ目の形式は最初の形式と同じです。 3番目の形式は、入力行の中にある式の、全ての重複しない値(複数式では重複しない値集合)の集約を呼び出します。最後の形式はそれぞれの入力行に対して1回ずつ集約を呼び出します。具体的な入力値が指定されていないため、これは一般的に count(*) 集約関数でのみ役に立ちます。

1つ以上の式がNULLを返した場合にその行を破棄するように、ほとんどの集約関数はNULL入力を無視します。これは、特記されていない限り、すべての組込み集約で正しいと仮定することができます。

例えば、 count(*) は入力行の合計数を求めます。 count はNULLを無視しますので、 count(f1) f1 が非NULLである入力行の数を求めます。 count(distinct f1) f1 の重複しない非NULL値の数を求めます。

通常、入力行は順序を指定されずに集計関数に与えられます。多くの場合では問題になりません。たとえば min は入力順序に関係なく同一の結果を返します。しかし一部の集約関数( array_agg および string_agg など)は入力行の順序に依存した結果を返します。こうした集約関数を使用する際は、省略可能な order_by_clause を使用して必要とする順序を指定できます。 order_by_clause は、 項7.5 で説明する問い合わせレベルの ORDER BY 句と同じ構文を取りますが、その式は常に単なる式であり、出力列名や序数とすることはできません。 以下に例を示します。

SELECT array_agg(a ORDER BY b DESC) FROM table;

複数の引数を取る集約関数を扱う場合、 ORDER BY 句はすべての集約引数の後に指定することに注意してください。 例えば、

SELECT string_agg(a, ',' ORDER BY a) FROM table;

であり、

SELECT string_agg(a ORDER BY a, ',') FROM table;  -- incorrect

ではありません。 後者は構文的には有効なものですが、2つの ORDER BY キーを持つ単一引数の集約関数の呼び出しを表しています。(2つ目のキーは定数なので役には立ちません。)

order_by_clause に加え DISTINCT が指定された場合、すべての ORDER BY 式が集約関数の通常の引数に一致しなければなりません。つまり、 DISTINCT リストに含まれない式でソートすることはできません。

注意: 集計関数における DISTINCT ORDER BY の指定機能はPostgreSQL独自の拡張です。

定義済みの集約関数は 項9.20 で説明されています。 ユーザは他の集約関数を追加することができます。

集約式は、 SELECT コマンドの結果リストもしくは HAVING 句内でのみ記述することができます。 WHERE などの他の句では許されません。 これらの句は理論上集計結果が形成される前に評価されるためです。

集約式が副問い合わせ( 項4.2.11 項9.22 を参照)内に現れた場合、通常集約は副問い合わせの行全体に対して評価します。 しかし、その集約の引数が上位レベルの変数のみを持つ場合は例外です。 その場合、上位問い合わせの行全体に対して評価します。 全体として、その集約式は、その後、その集約を含む副問い合わせでは外部参照となり、その副問い合わせにおける評価に対しては定数として動作します。 結果リストもしくは HAVING 句にのみ現れるという制約は、その集約が属する問い合わせレベルに関連して適用されます。

4.2.8. ウィンドウ関数呼び出し

ウィンドウ関数呼び出し は、問い合わせにより選択された行のある部分に渡って集約のような機能を実現することを表します。 通常の集約関数呼び出しと異なり、これは選択された行を1つの行にグループ化することに束縛されず、各行は別途問い合わせ出力に残ります。 しかしウィンドウ関数は、ウィンドウ関数呼び出しのグループ化指定( PARTITION BY リスト)に従った、現在の行のグループの一部となる行をすべてスキャンすることができます。 ウィンドウ関数呼び出しの構文は以下のいずれかです。



function_name

 ([


expression

 [
, 

expression

 ... 
]
]) OVER 

window_name




function_name

 ([


expression

 [
, 

expression

 ... 
]
]) OVER ( 

window_definition

 )


function_name

 ( * ) OVER 

window_name




function_name

 ( * ) OVER ( 

window_definition

 )

ここで、 window_definition は以下の構文になります。

[ 

existing_window_name

 ]
[ PARTITION BY 

expression

 [, ...] ]
[ ORDER BY 

expression

 [ ASC | DESC | USING 

operator

 ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ 

frame_clause

 ]

オプションの frame_clause は次の中の1つです。

[ RANGE | ROWS ] 

frame_start


[ RANGE | ROWS ] BETWEEN 

frame_start

 AND 

frame_end

ここで frame_start および frame_end は以下のいずれかです。

UNBOUNDED PRECEDING


value

 PRECEDING
CURRENT ROW


value

 FOLLOWING
UNBOUNDED FOLLOWING

ここで、 expression はそれ自身ウィンドウ関数呼び出しを含まないいかなる値式を表わします。

window_name は、問い合わせの WINDOW 句で定義された名前付きウィンドウ仕様への参照です。 あるいはまた、完全な window_definition WINDOW 句で定義された名前付きウィンドウと同じ構文を使って丸括弧の中に書くことができます。 詳細は SELECT マニュアルページを見てください。 OVER wname OVER (wname) とは厳密には等価ではないことを指摘しておくのは価値のあることでしょう。 後者はウィンドウ定義をコピーしたり修正したりすることを示唆しており、参照されるウィンドウ仕様がフレーム句を含む場合には拒絶されます。

PARTITION BY オプションは問い合わせの行を パーティション に纏め、パーティションはウィンドウ関数により別々に処理されます。 PARTITION BY は、その式が常に式であって出力列名や数値ではないという点を除いて、問い合わせレベルの GROUP BY 句と同様に動作します。 PARTITION BY がなければ、問い合わせで生じる行すべてが一つのパーティションとして扱われます。 ORDER BY オプションはパーティションの行がウィンドウ関数により処理される順序を決定します。 問い合わせレベルの ORDER BY 句と同様に動作しますが、やはり出力列名や数値は使えません。 ORDER BY がなければ、行は順序を指定されずに処理されます。

frame_clause は、パーティション全体の代わりにそのフレーム上で作動するウィンドウ関数に対して、 ウィンドウフレーム を構成する行の集合を指定します。 フレームは RANGE モードでも ROWS モードでも指定できます。 どちらの場合でも frame_start から frame_end までです。 frame_end を省略した場合のデフォルトは CURRENT ROW です。

UNBOUNDED PRECEDING frame_start はフレームがパーティションの最初の行から始まること意味し、同様に、 UNBOUNDED FOLLOWING frame_end をフレームがパーティションの最後の行で終わること意味します。

RANGE モードでは、 CURRENT ROW frame_start はフレームが現在行の最初の 同等な 行( ORDER BY が現在行と等しいとみなす行)から始まることを意味し、一方、 CURRENT ROW frame_end はフレームが現在行の最後の同等な行で終わることを意味します。 ROWS モードでは、 CURRENT ROW は単に現在行を意味します。

value PRECEDING value FOLLOWING の形式は、現在のところ ROWS モードでのみ許可されています。 これは、フレームの開始もしくは終了点となる現在行の前や後に、指定数の行があることを意味します。 value は一切の変数、集計関数、あるいはウィンドウ関数を含まない整数式でなければなりません。 またNULLや負数も許可されませんが、現在行を選択することになる0は指定可能です。

デフォルトのフレーム化オプションは RANGE UNBOUNDED PRECEDING で、 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW と同じです。 これはパーティションの開始から ORDER BY による順序付けに沿った現在行と同等となる最後の行までのフレームをセットします。 ORDER BY が無い場合は、すべての行が現在行と同等となりますのでパーティションのすべての行がウィンドウフレームに含まれます。

制限は、 frame_start UNBOUNDED FOLLOWING とすることができない点、 frame_end UNBOUNDED PRECEDING とすることができない点、および frame_end の選択は上のリストの中で frame_start の選択より先に記述することができない点です。例えば、 RANGE BETWEEN CURRENT ROW AND value PRECEDING は許されません。

組み込みウィンドウ関数は 表9-48 に記載されています。その他のウィンドウ関数をユーザが追加することが可能です。また、全ての組み込み、またはユーザ定義の集約関数もウィンドウ関数として使用できます。

* を使用した構文は、例えば count(*) OVER (PARTITION BY x ORDER BY y) のように、ウィンドウ関数として呼び出しパラメータのない集約関数を使用します。 アスタリスク( * )は習慣的に非集約ウィンドウ関数には使われません。通常の集約関数と異なり、集約ウィンドウ関数は、関数引数リストの中で DISTINCT ORDER BY が使われることを許可しません。

ウィンドウ関数呼び出しは問い合わせの SELECT リストと ORDER BY 句の中でのみ許可されます。

更なるウィンドウ関数についての情報は 項3.5 , 項9.21 , 項7.2.4 にあります。

4.2.9. 型キャスト

型キャストは、あるデータ型から他のデータ型への変換を指定します。 PostgreSQL は型キャストに2つの等価な構文を受け付けます。

CAST ( 

expression

 AS 

type

 )


expression

::

type

CAST 構文はSQLに準拠したものです。 :: を使用する構文は、 PostgreSQL で伝統的に使用されている方法です。

キャストが既知の型の評価式に適用された場合、それは実行時型変換を表します。 このキャストは、適切な型変換操作が定義されている場合のみ成功します。 項4.1.2.7 で示すように、これと定数のキャストの使用との微妙な違いに注意してください。 修飾されていない文字列リテラルに対するキャストは、リテラル定数値の初期に割り当てられる型を表します。 ですから、これは(文字列リテラル定数の内容がそのデータ型の入力構文で受け付けられるのであれば)全ての型で成功します。

通常(例えばテーブル列への代入時など)、評価式が生成しなければならない型に曖昧さがない場合、明示的な型キャストは省略することができます。 その場合、システムは自動的に型キャストを適用します。 しかし、自動キャストは、システムカタログに "暗黙的に適用しても問題なし" と示されている場合にのみ実行されます。 その他のキャストは明示的なキャスト構文で呼び出す必要があります。 この制限は、知らないうちに変換が実行されてしまうことを防ぐためのものです。

また、関数のような構文を使用して型キャストを指定することもできます。



typename

 ( 

expression

 )

しかし、これはその型の名前が関数の名前としても有効な場合にのみ動作します。 例えば、 double precision はこの方式で使用できませんが、同等の float8 は使用できます。 また、 interval time timestamp という名前は、構文が衝突するため、二重引用符で括った場合にのみこの方式で使用できます。 このように、この関数のようなキャスト構文は一貫性がなくなりがちですので、おそらくアプリケーションでは使用すべきではありません

注意: この関数のような構文は、実際には単なる関数呼び出しです。 2つの標準的なキャスト構文のうちの1つが実行時変換で使用されると、この構文は登録済みの関数を内部的に呼び出して変換を実行します。 慣習的に、これらの変換関数は自身の出力型と同じ名前を持ち、これにより、 "関数のような構文" は背後にある変換用関数を直接呼び出す以上のことを行いません。 移植性を持つアプリケーションが依存すべきものでないことは明確です。 詳細については CREATE CAST を参照してください。

4.2.10. 照合順序式

COLLATE 句は式の照合順序規則を上書きします。適用するため次の様に式に加えます。



expr

 COLLATE 

collation

collation はおそらくスキーマ部を含む識別子です。 COLLATE 句は演算子よりも優先度が低いため、必要に応じて括弧で囲います。

もし照合順序が何も指定されなければ、データベースシステムは式にある列から照合順序を取得します。もし列に関する照合順序が式になければ、データベースのデフォルトの照合順序を使います。

例として、よく使われる COLLATE 句による並び替え順序の上書きを挙げます。 ORDER BY 句を使う場合には、

SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C";

とします。ロケール依存を伴った関数や演算子の呼び出しに対しての上書き方法例は

SELECT * FROM tbl WHERE a > 'foo' COLLATE "C";

とします。後者の場合、 COLLATE 句が、処理対象と想定している入力演算子の引数に対して付与されることに注意してください。演算子や関数の呼び出しのどの引数に対して COLLATE 句が付与されるかは問題ではありません。演算子や関数により適用される照合順序は対象となる全ての引数を考慮して引き出され、そして明示的に指定された COLLATE 句がその他の全ての引数に対しての照合順序を上書きするからです。(しかし、複数の引数に対して一致しない COLLATE 句の付与はエラーとなります。詳細は 項22.2 を参照してください)。このため、前述の例と同じ結果を次の様にして取得することができます。

SELECT * FROM tbl WHERE a COLLATE "C" > 'foo';

ただし、これはエラーになります。正しくは次の様にします。

SELECT * FROM tbl WHERE (a > 'foo') COLLATE "C";

なぜなら、照合順序を与えることができない boolean 型となる > 演算子の結果に対して。照合順序が適用されようとするからです。

4.2.11. スカラ副問い合わせ

スカラ副問い合わせは、正確に1行1列を返す、括弧内の通常の SELECT 問い合わせです (問い合わせの記述方法については 第7章 を参照してください)。 その SELECT 問い合わせは実行され、返される単一の値はその値の前後の評価式で使用されます。 1行を超える行や1列を超える列がスカラ副問い合わせ用の問い合わせとして使用された場合はエラーになります (しかし、ある実行時に、副問い合わせが行を返さない場合はエラーとはなりません。 そのスカラ結果はNULLとして扱われます)。 副問い合わせは、その周りの問い合わせ内の値を参照することができます。 その値は副問い合わせの評価時には定数として扱われます。 副問い合わせに関する他の式については 項9.22 も参照してください。

例えば、以下は各州で最も人口の多い都市を検索します。

SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
    FROM states;

4.2.12. 配列コンストラクタ

配列コンストラクタは、メンバー要素に対する値を用いて配列値を構築する式です。 単純な配列コンストラクタの構成は、 ARRAY キーワード、左大括弧 [ 、(カンマで区切った)配列要素値用の式のリストで、最後に右大括弧 ] です。 以下に例を示します。

SELECT ARRAY[1,2,3+4];
  array
---------
 {1,2,7}
(1 row)

デフォルトで配列要素型は、メンバ式の型と同じで、 UNION CASE 構文と同じ規則を使用して決定されます ( 項10.5 を参照してください)。これを明示的に配列コンストラクタを希望する型にキャストすることで書き換えることができます。例をあげます。

SELECT ARRAY[1,2,22.7]::integer[];
  array
----------
 {1,2,23}
(1 row)

これはそれぞれの式を配列型に個別にキャストするのと同じ効果があります。キャストについてより多くは 項4.2.9 を参照してください。

多次元配列値は、配列コンストラクタを入れ子にすることで構築できます。 内側のコンストラクタでは ARRAY キーワードは省略可能です。 例えば、以下は同じ結果になります。

SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

SELECT ARRAY[[1,2],[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

多次元配列は四角形配列でなければなりませんので、同一レベルの内部コンストラクタは同一次元の副配列を生成しなければなりません。外部 ARRAY コンストラクタに適用される全てのキャストは自動的に全ての内部コンストラクタに伝播します。

多次元配列コンストラクタの要素は、副 ARRAY 構文だけでなく、適切な種類の配列を生成するものをとることができます。 以下に例を示します。

CREATE TABLE arr(f1 int[], f2 int[]);

INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]);

SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;
                     array
------------------------------------------------
 {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}
(1 row)

空配列を構築できますが、型を所有しない配列を持つことは不可能なので、空配列を望まれる型に明示的にキャストしなければなりません。例をあげます。

SELECT ARRAY[]::integer[];
 array
-------
 {}
(1 row)

また、副問い合わせの結果から配列を構成することも可能です。 この形式の場合、配列コンストラクタは ARRAY キーワードの後に括弧(大括弧ではない)で括られた副問い合わせとして記述されます。 以下に例を示します。

SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
                                 array
-----------------------------------------------------------------------
 {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31,2412,2413}
(1 row)

副問い合わせは単一の列を返さなければなりません。 その結果である一次元配列は、副問い合わせの出力列と一致する型を要素型とした、副問い合わせの結果内の各行を要素として持ちます。

ARRAY で構築された配列値の添字は、常に1から始まります。 配列についての詳細は 項8.15 を参照してください。

4.2.13. 行コンストラクタ

行コンストラクタは、そのメンバフィールドに対する値を用いて行値(複合値とも呼ばれます)を構築する式です。 行コンストラクタは、 ROW キーワード、左括弧、行のフィールド値用の0個以上の式(カンマ区切り)、最後に右括弧からなります。 以下に例を示します。

SELECT ROW(1,2.5,'this is a test');

ROW キーワードは、1つ以上の式がリスト内にある場合は省略することができます。

行コンストラクタには rowvalue .* 構文を含めることができます。 これは、 SELECT リストの最上位レベルで .* 構文が使用された時とまったく同様に、行値の要素の列挙に展開されます。 たとえば、テーブル t f1 列と f2 列を持つ場合、以下は同一です。

SELECT ROW(t.*, 42) FROM t;
SELECT ROW(t.f1, t.f2, 42) FROM t;

注意: PostgreSQL 8.2より前では、 .* 構文は展開されませんでした。 ROW(t.*, 42) と記述すると、1つ目のフィールドに別の行値を持つ、2つのフィールドからなる行が作成されました。 たいていの場合、新しい動作はより使いやすくなっています。 入れ子状の行値という古い動作が必要であれば、 .* を使用せずに、たとえば ROW(t, 42) といった、内部行値を記述してください。

デフォルトでは、 ROW 式により作成される値は匿名レコード型になります。 必要に応じて、名前付きの複合型、テーブルの行型、もしくは CREATE TYPE AS で作成された複合型にキャストすることができます。 明示的なキャストは曖昧性を防止するために必要となることもあります。 以下に例を示します。

CREATE TABLE mytable(f1 int, f2 float, f3 text);

CREATE FUNCTION getf1(mytable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- getf1()が1つしか存在しないためキャスト不要。
SELECT getf1(ROW(1,2.5,'this is a test'));
 getf1
-------
     1
(1 row)

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);

CREATE FUNCTION getf1(myrowtype) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- ここでは、どの関数を呼び出すのかを示すためにキャストが必要。
SELECT getf1(ROW(1,2.5,'this is a test'));
ERROR:  function getf1(record) is not unique

SELECT getf1(ROW(1,2.5,'this is a test')::mytable);
 getf1
-------
     1
(1 row)

SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype));
 getf1
-------
    11
(1 row)

行コンストラクタは、複合型のテーブル列に格納する複合型の値を構築するため、あるいは複合型のパラメータを受け付ける関数に渡すために使用することができます。 また、以下の例のように、2つの行値を比較することも、 IS NULL もしくは IS NOT NULL で行を検査することも可能です。

SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');
SELECT ROW(table.*) IS NULL FROM table;  -- すべてがNULLの行を検出します。

詳細は 項9.23 を参照してください。 行コンストラクタは、 項9.22 で説明した、副問い合わせと一緒に使用することもできます。

4.2.14. 式の評価規則

副式の評価の順序は定義されていません。 特に演算子や関数の入力は、必ずしも左から右などの決まった順序で評価されるわけではありません。

さらに、その式の一部を評価しただけで式の結果を判断できる場合には、他の副式がまったく評価されないこともあります。 例えば、

SELECT true OR somefunc();

では、(おそらく) somefunc() は呼び出されないでしょう。 以下の場合も同様です。

SELECT somefunc() OR true;

これは一部のプログラミング言語に見られる、ブーリアン演算子での左から右への "ショートサーキット" とは異なることに注意してください。

そのため、副次作用がある関数を複雑な式の一部として使用することは推奨されません。 特に、 WHERE 句および HAVING 句で副次作用や評価順に依存するのは危険です。 これらの句は、実行計画を作成する過程で頻繁に再処理されるからです。 これらの句のブール式( AND / OR / NOT の組み合わせ)は、ブール代数の規則で許されるあらゆる方式で再編成することができます。

評価の順序を強制することが重要であれば、 CASE 構文( 項9.17 を参照)を使用できます。 例えば、次の式は WHERE 句で0除算を避ける方法としては信頼性の低いものです。

SELECT ... WHERE x > 0 AND y/x > 1.5;

しかし、次のようにすれば安全です。

SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;

このような方法で使用される CASE 構文は最適化を妨げるものなので、必要な場合にのみ使用してください。 (特に、この例では、 y > 1.5*x と代わりに記述することが問題を回避するより優れた方法です。)


powered by SEO.CUG.NET