名前を付けて保存され、その名前で呼び出される SQL 文を指定します。
ストアド・プロシージャは、データベースに保存され、サーバで起動される呼び出し可能なルーチンを提供します。Caché ObjectScript では、ストアド・プロシージャを作成することができます。
ストアド・プロシージャは、
メソッドや
クエリのいずれかとして実装されます。結果セットやデータの行を返すものは、オブジェクト・クエリ (クエリを含むように特別に設計されたオブジェクトの一部) として実装され、データベースを更新するものは、メソッドとして実装されなければなりません。
データベースからデータを返す多くのストアド・プロシージャは、標準クエリ・インタフェースで実装されます。この方法は、プロシージャが埋め込み SQL で記述されている限りうまくいきます。
クエリをストアド・プロシージャとして公開するには、Caché スタジオのインスペクタにクエリを入力して、SQLProc フィールドの値を真に変更するか、または、以下の
[ SqlProc ] 文字列をクエリ定義に追加します。
Query QueryName() As %SQLQuery( ... query definition ... )
[ SqlProc ]
単純な SQL 文としてクエリを記述し、それをクエリ・ウィザードで作成することが可能な場合、クエリを実装する基本的なメソッドに関する知識は必要ありません。
内部で、各クエリに対して、クラス・コンパイラはストアド・プロシージャの名前を基にしてメソッドを生成します。以下のものが含まれます。
クエリが %SQLQuery タイプである場合、クラス・コンパイラは自動的に複数の埋め込み SQL を生成されたメソッドに挿入します。Execute は SQL のためにストアド・カーソルを宣言し、開きます。Fetch は、空白の行 (SET Row="") を返すまで、繰り返し呼び出されます。オプションで、Fetch を AtEnd=1 のブーリアン・フラグを返すようにすることもできます。これは、現在の Fetch が最後の行を取り、次の Fetch で空白の行を返すようにすることを示します。ただし、空白行は必ず結果セットの終了を判断するためのテスト用として使用する必要があります。FetchRows は、論理的に Fetch への繰り返しの呼び出しと同じです。GetInfo は、ストアド・プロシージャに対する署名の詳細を返すために呼び出されます。Close はカーソルをクローズします。
これらすべてのメソッドは、クライアントからストアド・プロシージャが呼び出されるたびに自動的に呼び出されますが、論理的には、サーバで起動している ObjectScript から直接呼び出されることもあります。
オブジェクトを Execute から Fetch に渡すために、また Fetch から次の Fetch の呼び出しに渡すために、クエリ・ハンドラをそのオブジェクトのオブジェクト参照 (oref) に設定することができます。複数のオブジェクトを渡す場合、qHandle を配列として設定できます。
SET qHandle(1)=oref1,qHandle(2)=oref2
クエリ・モデルに一致しない複雑なクエリやストアド・プロシージャに対しては、多くの場合で、そのメソッドの一部、またはすべてを置き換えることでクエリをカスタマイズする必要があります。
%SQLQuery タイプの代わりに %Query タイプを選択する方が、クエリを実装するのに容易な場合もあります。これによって、同じ 5 つのメソッドが生成されますが、FetchRows は単純に Fetch の呼び出しを繰り返します (%SQLQuery には動作を引き起こすいくつかの最適化機能があります)。GetInfo は単純に署名から情報を得るので、コードが変更される必要はありません。これによって、他の 3 つのメソッドそれぞれに対し、クラス・メソッドを作成する上での問題が削減されます。クラスがコンパイルされるとき、コンパイラはこれらのメソッドの存在を検出します。上書きすることはありません。
メソッドは特定の署名を必要とします。それらはすべて %Binary タイプの Qhandle (クエリ・ハンドラ) を使用します。これは、クエリの特性と現状を維持する構造に対するポインタです。Execute と Fetch に対する参照と、Close に対する値によって渡されます。
ClassMethod SP1Close(qHandle As %Binary) As %Status
]
{
// ...
}
ClassMethod SP1Execute(ByRef qHandle As %Binary,
p1 As %String) As %Status
{
// ...
}
ClassMethod SP1Fetch(ByRef qHandle As %Binary,
ByRef Row As %List, ByRef AtEnd As %Integer=0) As %Status
{
// ...
}
Query SP1(p1 As %String)
As %%Query(CONTAINID=0,ROWSPEC="lastname:%String") [sqlproc ]
{
}
コードは通常、宣言を含み、SQL カーソルを使用します。%SQLQuery タイプのクエリから生成されたカーソルは、自動的に Q14 などの名前を持ちます。クエリに個別の名前が与えられていることを確認してください。
クラス・コンパイラは、カーソルを使用する前に、カーソル宣言を見つける必要があります。したがって、DECLARE 文 (通常は Execute 内) は、Close や Fetch と同じ MAC ルーチン内にあるべきで、Close や Fetch よりも先に来る必要があります。CDL を直接編集するには、カーソル宣言が先に来るように Close 定義と Fetch 定義の両方で PLACEAFTER メソッド・キーワードを使用します。
エラー・メッセージは、通常、桁を 1 桁余分に持っている内部カーソル名を参照します。したがって、カーソル Q140 に対するエラー・メッセージは、おそらく Q14 を参照しています。
クラス・メソッドはストアド・プロシージャとして公開されます。このようなメソッドは、値を計算して、それを返さずにデータベースに保存するストアド・プロシージャのような動作に対して理想的です。
メソッドは %SQLProcContext タイプのパラメータを持ちます。このパラメータは参照によって渡されますが、ストアド・プロシージャに値によって渡されるパラメータすべてがその後に続きます。
%SQLProcContext は、SQL のステータスと RowCount から成り立っています。これらの値に関しては何も行う必要はありませんが、クライアントによって解読されます。
例えば、CalcAvgScore メソッドがあるとします。
ClassMethod CalcAvgScore(pHandle As %SQLProcContext,
firstname As %String,lastname As %String) [sqlproc]
{
New SQLCODE,%ROWID
&sql(UPDATE students SET avgscore =
(SELECT AVG(sc.score)
FROM scores sc, students st
WHERE sc.student_id=st.student_id
AND st.lastname=:lastname
AND st.firstname=:firstname)
WHERE students.lastname=:lastname
AND students.firstname=:firstname)
IF ($g(pHandle)'=$$$NULLOREF) {
SET pHandle.SQLCode = SQLCODE
SET pHandle.RowCount = %ROWCOUNT
}
QUIT
}