Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

CALL

ストアド・プロシージャを実行します。

Synopsis

CALL procname(arg1,arg2,...) [USING contextvar]

retval=CALL procname(arg1,arg2,...) [USING contextvar]

引数

procname ストアド・プロシージャの名前。スキーマまで記述した完全修飾名でも、未修飾名でも指定できます。未修飾名を指定した場合、以下に説明するように、Caché によってスキーマ名が設定されます。
arg1 オプション — 実引数リスト。ストアド・プロシージャに渡す 1 つ以上の値をコンマで区切って順番に指定します。引数を指定しない場合でも、括弧は必須です。
USING contextvar オプションcontextvar には、プロシージャの呼び出しで生成されるプロシージャ・コンテキスト・オブジェクトを受け取る記述子領域変数を指定します。省略した場合の既定値は %sqlcontext です。
retval オプション — プロシージャの返り値を受け取るために指定する変数。格納できるのは単一の値です。結果セットは格納できません。ローカル変数、ホスト変数、または疑問符 (?) 引数として指定できます。

概要

CALL 文は、SQL ストアド・プロシージャとして公開されたクエリを呼び出します。procname は、現在のネームスペースにある既存のストアド・プロシージャであることが必要です。procname が見つからないと、Caché は SQLCODE -428 エラーを生成します。procname は、SqlProc=True のストアド・プロシージャであることが必要です。"Caché クラス定義リファレンス" の "SqlProc" を参照してください。

procname では、大文字と小文字は区別されません。引数をまったく指定しない場合でも、procname の後ろに引数の括弧を付加する必要があります。これを実行しないと、SQLCODE -1 エラーが返されます。

CALLarg 引数はオプションですが、括弧は記述する必要があります。このコンマ区切りリストは実引数リストと呼ばれ、このリストで指定される引数の数と順序は、プロシージャ定義内の仮引数リストのものと一致している必要があります。実引数値の指定が、ストアド・プロシージャで定義された仮引数より少なくてもかまいません。ストアド・プロシージャで定義された仮引数よりも多くの実引数値を指定した場合、システムは SQLCODE -370 エラーを生成します。このエラー・メッセージには、ストアド・プロシージャ名、指定した引数の数、およびそのストアド・プロシージャで定義している引数の数が示されます。

末尾の引数は省略できます。省略された末尾の引数は未定義となり、既定値が使用されます。引数リスト内で未定義の引数を指定するには、プレースホルダとしてコンマを指定します。例えば、(arg1,,arg3) と指定した場合は 3 つの引数が渡され、そのうち 2 番目の引数は未定義です。一般に、未定義の引数の値は、ストアド・プロシージャの定義時に指定された既定値となります。既定値が定義されていない場合、未定義の引数の値は NULL を取ります。詳細は、"Caché SQL の使用法" の "NULL および空文字列" を参照してください。

ストアド・プロシージャで定義されたデータ型と一致しない引数値を指定した場合は、既定値が指定されている場合でも、その引数は NULL を取ります。例えば、ストアド・プロシージャで引数が IN numarg INT DEFAULT 99 と定義されているとします。CALL で数値引数が指定されている場合は、その arg 値が使用されます。CALL でその引数が省略されている場合は、定義された既定値が使用されます。ただし、CALL で非数値引数が指定されている場合は、定義された既定値ではなく NULL が使用されます。

ストアド・プロシージャの詳細は、"CREATE PROCEDURE" コマンドを参照してください。

埋め込み SQL からの呼び出し

ObjectScript の埋め込み SQL では、CALL 文の発行、または DO コマンドによる基本ルーチンや基本メソッドの呼び出しが可能です。

埋め込み SQL では、CALL に渡す引数値をリテラルとして指定することも、:name 形式のホスト変数や疑問符 (?) の入力パラメータを自由に組み合わせて指定することもできます。次に例を示します。

   SET a=7,b="A",c=99
   &sql(CALL MyProc(:a,:b,:c))
   &sql(CALL MyProc(?,:b,?))

既定では、埋め込み SQL 内の最初の CALL 文の呼び出しにより、%sqlcontext 変数が作成されます。後続の反復は、この既存の %sqlcontext 変数を使用します。つまり、複数の反復が累積して、%sqlcontext が <STORE> エラーになる可能性があります。CALL 文が繰り返し反復される場合は、USING 節で %sqlcontext 変数を明示的に指定する必要があります。USING 節内でプロシージャ・コンテキストが指定されると、Caché は、呼び出されるたびにプロシージャ・コンテキストで NEW を発行します。

出力の arg に使用されるホスト変数には、単一値、配列の参照、1 つの oref.property の参照、または多次元 oref.property の参照を指定できます。

次のように、ホスト変数または疑問符 (?) を使用して、CALL 文から値を返すことができます。

   &sql(:rtnval=CALL MyProc())
   &sql(?=CALL MyProc())

CALL の返り値は、単一値にする必要があります。埋め込み SQL の CALL 文から結果セットを返すことはできません。値を返さないプロシージャに retval=CALL 構文を使用しようとすると SQLCODE -371 エラーが生成されます。

#SQLCompile Path マクロ指示文を使用してスキーマの検索パスを指定し、CALL ではこのパスを使用して未修飾のプロシージャ名を解決できます。#SQLCompile Path 指示文を定義していない場合、Caché では現在のクラスのパッケージにマップされたスキーマが使用されます。スキーマ検索パスとスキーマ既定値のいずれを使用しても指定されたプロシージャが見つからないと、Caché は SQLCODE -428 エラーを生成します。

詳細は、"Caché SQL の使用法" の "埋め込み SQL" の章を参照してください。

ダイナミック SQL からの呼び出し

次のダイナミック SQL の例では、ストアド・プロシージャ Sample.PersonSets を呼び出し、このプロシージャから Sample.Person テーブルに対して 2 つのクエリを実行します。このストアド・プロシージャの引数では、これら 2 つのクエリで使用する WHERE 節の値を指定します。最初の引数では、最初のクエリで Name 値が arg1 (この場合、文字 “M”) で始まるすべてのレコードを返すように指定しています。2 番目の引数では、2 番目のクエリで Home_State = arg2 (この場合、“MA”) を満たすすべてのレコードを返すように指定しています。

  ZNSPACE "Samples"
  SET mycall = "CALL Sample.PersonSets(?,'MA')"
  SET tStatement = ##class(%SQL.Statement).%New()
  SET qStatus = tStatement.%Prepare(mycall)
    IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET rset = tStatement.%Execute("M")
  IF rset.%SQLCODE '= 0 {WRITE "SQL error=",rset.%SQLCODE  QUIT}
  DO rset.%Display()

次のダイナミック SQL の例でも、ストアド・プロシージャ Sample.PersonSets を呼び出し、それぞれのクエリに対して個別に結果セットを返します。%Next()Opens in a new tab メソッドは、最初のクエリ結果セットで繰り返し処理を行います。%MoreResults()Opens in a new tab メソッドは、2 番目のクエリの結果セットにアクセスします。クエリが 3 つ以上ある場合、%MoreResults() は各結果セットに順番にアクセスします。

  ZNSPACE "Samples"
  SET mycall = "CALL Sample.PersonSets(?,'MA')"
  SET tStatement = ##class(%SQL.Statement).%New()
  SET qStatus = tStatement.%Prepare(mycall)
    IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET rset = tStatement.%Execute("M")
  IF rset.%SQLCODE '= 0 {WRITE "SQL error=",rset.%SQLCODE  QUIT}
FirstResultSet
  WHILE rset.%Next() {
     WRITE "Name: ",rset.%Get("Name")
     IF rset.%Get("Spouse") {
     WRITE " Spouse: ",rset.%Get("Spouse"),!}
     ELSE {WRITE " unmarried",! }
     }
  WRITE !,"1st row count=",rset.%ROWCOUNT,!!
SecondResultSet
   WHILE rset.%MoreResults() {
   DO rset.%CurrentResult.%Display()
   }

%Next() を呼び出す前に、CALL の実行によって設定された %SQLCODE 値を確認することが重要です。%Next() メソッドを呼び出すと、その前の CALL の %SQLCODE 値を上書きする形で、%SQLCODE が設定されます。%Next() が結果セット・データを受け取らない場合、このメソッドは %SQLCODE=100 と設定します。このメソッドは、空の結果セット (行が選択されていない) と、CALL 処理のエラーに起因する存在しない結果セットを区別しません。

%SQL.StatementOpens in a new tab の詳細、およびストアド・プロシージャの仮パラメータやその他のメタデータのリストを表示する方法については、"Caché SQL の使用法" の “ダイナミック SQL の使用法” の章を参照してください。%Display() メソッドの詳細および例については、“ダイナミック SQL の使用法” の章にある "完全な結果セットの返送" を参照してください。%Next() メソッドおよび %Get() メソッドの詳細および例については、“ダイナミック SQL の使用法” の章にある "結果セットからの特定値の返送" を参照してください。

ObjectScript からの呼び出し

埋め込み SQL から直接ストアド・プロシージャを呼び出すのではなく、ストアド・プロシージャを持つクラス・メソッドを ObjectScript から呼び出すことによって、そのストアド・プロシージャを実行することもできます。この場合、パラメータの管理が必要になります。また、クエリに基づいたストアド・プロシージャでは、個別のメソッドを呼び出し、フェッチ・ループを管理する必要もあります。

例えば、引数を持たない UpdateAllAvgScores というストアド・プロシージャとして公開されたメソッドを呼び出すためのコードは、以下のようになります。

   NEW phnd
   SET phnd=##class(%SQLProcContext).%New()
   DO ##class(students).UpdateAllAvgScores(phnd)
   IF phnd.%SQLCODE {QUIT phnd.%SQLCODE}
   USE 0
   WRITE !,phnd.%ROWCOUNT," Rows Affected"

CALL 文でプロシージャの引数を指定する際、そのプロシージャで %Library.SQLProcContext パラメータが明示的に定義されている場合は、%Library.SQLProcContext パラメータを指定しないでください。このパラメータは自動的に処理されます。

以下の例では、ストアド・プロシージャは 2 つの引数を取ります。また、明確に定義されたプロシージャ・コンテキストを使用します。

   ZNSPACE "Samples"
   NEW phnd
   SET phnd=##class(%SQLProcContext).%New()
   SET rtn=##class(Sample.ResultSets).PersonSets("D","NY")
   IF phnd.%SQLCODE {QUIT phnd.%SQLCODE}
   DO %sqlcontext.%Display()
   WRITE !,"All Done"

クエリとして実装されているストアド・プロシージャを呼び出すためには、以下の 3 つのメソッドすべてを呼び出す必要があります。

   NEW qhnd
   DO ##class(students).GetAvgScoreExecute(.qhnd,x1)
   NEW avgrow,AtEnd
   SET avgrow=$lb("") 
   SET AtEnd=0
   DO ##class(students).GetAvgScoreFetch(.qhnd,.avgrow,.AtEnd)
   SET x5=$lg(avgrow,1)
   DO ##class(students).GetAvgScoreClose(qhnd)

クエリ・ベースのストアド・プロシージャを多くのストアド・プロシージャ内に入れ子にする場合、ラッパ・メソッドを記述してすべて非表示にすると便利です。

ODBC または JDBC からの呼び出し

Caché は、ODBC 2.x 標準および JDBC 1.0 標準で定義されている CALL 構文を全面的にサポートしています。JDBC では、CallableStatement クラスのメソッドから CALL を実行できます。ODBC では、API を利用します。CALL の構文と意味は、JDBC と ODBC でまったく同じです。さらに、処理方法も同様です。どちらのドライバも文のテキストを解析し、CALL 文の場合は SQL エンジンを経由せずにサーバ側の専用メソッドを直接呼び出します。

PERSON クラスに SP1 と呼ばれるストアド・プロシージャが存在する場合、ODBC や JDBC クライアント (Microsoft Query など) からこのプロシージャを以下のように呼び出すことができます。

retcode = SQLExecDirect(hstmt, "{?=call PERSON_SP1(?,?)}", SQL_NTS);

Caché では、ストアド・プロシージャを呼び出す文の構造は、ODBC 標準に準拠しています。この標準の情報に関しては、関連するドキュメントを参照してください。

ODBC で使用する場合にのみ、Caché では呼び出しに柔軟な構文を適用できるので、CALL の前後の{ }括弧やパラメータの前後の括弧は必要ありません (これは、適切なプログラミング形式です。上記の例はこれらを使用しています)。

同様に、ODBC で使用する場合にのみ、Caché では、既定のパラメータを使用するために変更された構文を適用できます。したがって、CALL SPCALL SP() とは異なる機能を持ちます。2 番目のフォームは、既定のパラメータを使用しないことを意味します — これは CALL SP (,,)SP(,?,)、または他の構文などと同様です。つまり、CALL では、括弧を使用したフォームと括弧を使用しないフォームは異なります。

関連項目

FeedbackOpens in a new tab