Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

CALL (SQL)

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

Synopsis

CALL procname(arg_list) [USING contextvar]

retval=CALL procname(arg_list) [USING contextvar]

引数

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

概要

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

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

引数

procname

既存のストアド・プロシージャの名前。引数を指定しない場合でも、procname の後には括弧を付加する必要があります。プロシージャ名は以下の形式のいずれかで指定することができます。

  • 未修飾 : 既定のスキーマ名が使用されます。例えば、MedianAgeProc() です。

  • 修飾 : スキーマ名を指定します。例えば、Patient.MedianAgeProc() です。

  • 複数レベル : 対応するクラス・パッケージ・メンバに一致させるために 1 つ以上のスキーマ・レベルで修飾します。この場合、procname に含めることができるピリオド文字は 1 つだけです。対応するクラス・メソッド名の他のピリオドは下線に置き換えられます。ピリオドは、最下位レベルのクラス・パッケージ・メンバの前に指定します。例えば、%SYSTEM.SQL_GetROWID()%SYS_PTools.StatsSQL_Export() のように指定します。

未修飾の procname と一致するプロシージャをスキーマ内で検索する際、既定のスキーマ名、または (指定されている場合は) スキーマ検索パスのスキーマ名が使用されます。スキーマ検索パスとシステム全体のスキーマ既定値のいずれを使用しても指定されたプロシージャが見つからない場合は、SQLCODE -428 エラーが生成されます。$SYSTEM.SQL.Schema.Default()Opens in a new tab メソッドを使用して、現在のシステム全体の既定のスキーマ名を確認できます。初期のシステム全体の既定のスキーマ名は、クラス・パッケージ名 User に対応する SQLUser です。

procname が現在のネームスペースに存在するかどうかを確認するには、$SYSTEM.SQL.Schema.ProcedureExists()Opens in a new tab メソッドを使用します。procname では、大文字と小文字は区別されません。

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

arg_list

値をストアド・プロシージャに渡すために使用される引数のリストです。arg_list は括弧で囲み、リストの引数はコンマで区切ります。引数を指定しない場合も括弧は必須です。

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

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

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

arg_list 引数にユーザ定義関数 (値を返すメソッド・ストアド・プロシージャ) を指定できます。

埋め込み 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 節内でプロシージャ・コンテキストが指定されると、InterSystems IRIS は、呼び出されるたびにプロシージャ・コンテキストで NEW を発行します。

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

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

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

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

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

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

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

  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() は各結果セットに順番にアクセスします。

  #include %occStatus
  set mycall = "CALL Sample.PersonSets(?,'MA')"
  set tStatement = ##class(%SQL.Statement).%New()
  set qStatus = tStatement.%Prepare(mycall)
  if $$$ISERR(qStatus) {write "%Prepare failed:" do $SYSTEM.Status.DisplayError(qStatus) quit}

  set rset = tStatement.%Execute("M")
  if (rset.%SQLCODE '= 0) {write "%Execute failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}

FirstResultSet
  while rset.%Next()
  {
    write "Name: ",rset.%Get("Name")
    if rset.%Get("Spouse") {write " Spouse: ",rset.%Get("Spouse"),!}
    else {write " unmarried",!}
  }
  if (rset.%SQLCODE < 0) {write "%Next failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}

  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 の詳細、およびストアド・プロシージャの仮パラメータやその他のメタデータのリストを表示する方法については、"InterSystems 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 つの引数を取ります。また、明確に定義されたプロシージャ・コンテキストを使用します。

   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 からの呼び出し

InterSystems IRIS は、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);

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

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

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

関連項目

FeedbackOpens in a new tab