複数の結果セットを 一度に返す方法
これは InterSystems FAQ サイトの記事です。
InterSystems 製品は複数の SQL 文を一度に受け付けませんので、SQL 文での複数結果セットのサポートはありませんが、ストアドプロシージャを作成して複数の結果セットを返すことができます。
以下、ストアドプロシージャの中では、 %SQL.Statement クラスを利用して SQL を実行し、結果セットを作成し、結果セットを呼び出し元に返すため、ストアドプロシージャ実行時に自動生成されるプロシージャ・コンテキスト(=%sqlcontext 変数に格納)の中に、結果セットを登録しています。
結果セットの登録は、%Library.ProcedureContext クラスの AddResultSet() メソッドを使用します。
メモ:ストアドプロシージャ実行時に自動生成されるプロシージャ・コンテキストは %Library.ProcedureContext のインスタンスで %sqlcontext 変数に自動的に設定されます。
サンプルコードでは、Sample.Employee と Sample.Company を利用して SELECT 文を実行し、%Execute() 実行後に作成される結果セットを %sqlcontext に追加しています。 この操作を 5 回繰り返しているため、5 個の結果セットが呼び出し元に戻される予定です。
メモ:IRIS を利用されている場合、Sample.Employee と Sample.Company はインストール時に用意されていないため、以下のサンプルコードを試す場合は、「サンプル(Sample.Person)のクラス定義ダウンロードとサンプルデータの作成について」をご参照ください。
ClassMethod getMultipleResultSets(pMax As %Library.Integer = 2) As %Status [ ReturnResultsets, SqlName = getMultipleResultSets, SqlProc ]
{
#dim sqlEx,tSC as %Exception.StatusException
#dim tRS as %SQL.StatementResult
#dim tIdx as %Integer
#dim tFields,tSQL as %String
#dim tSystemError as %SYSTEM.Error
#dim %sqlcontext as %Library.ProcedureContext
try
{
set tFields = $lb("ID","Name","DOB","Company->Name as Company")
set tSC = $$$OK
for tIdx = 1 : 1 : 5
{
set tSQL = "SELECT TOP 20 {Fields} FROM Sample.Employee ORDER BY ID {Order}"
set tSQL = $replace(tSQL,"{Fields}",$listtostring($list(tFields,1,1+$random($ll(tFields)))))
set tSQL = $replace(tSQL,"{Order}",$select($random(2)=0:"ASC",1:"DESC"))
set stmt =##class(%SQL.Statement).%New()
set tSC = stmt.%Prepare(tSQL)
$$$THROWONERROR(sqlEx,tSC)
set tRS= stmt.%Execute()
if ($data(%sqlcontext))
{
set tSC = %sqlcontext.AddResultSet(tRS)
}
}
}
catch (sqlEx)
{
set %sqlcontext.%SQLCODE=sqlEx.AsSQLCODE()
set %sqlcontext.%Message=sqlEx.AsSQLMessage()
set tSC = sqlEx.AsStatus()
}
quit tSC
}
Java から実行する例は以下の通りです(サンプルはこちら)。
※ IRISへ接続する例で記載しています。
/*
* MultiResultSet
*
*/
import java.sql.*;
public class MultiRS {
public static void main(String[] args) throws Exception{
String url="jdbc:IRIS://localhost:51773/USER";
String username="_SYSTEM"; // null for default
String password="SYS"; // null for default
Class.forName ("com.intersystems.jdbc.IRISDriver");
Connection dbconnection = DriverManager.getConnection(url, username, password);
CallableStatement cstmt = dbconnection.prepareCall("{? = call devcon2008.getMultipleResultSets(?) }");
cstmt.registerOutParameter(1,java.sql.Types.BINARY);
cstmt.setInt(2,5);
boolean ok = cstmt.execute();
int count=1;
do {
if (ok) {
ResultSet rs = cstmt.getResultSet();
out("\n\n\nresultset #" + count++);
int row = 1;
while (rs.next())
{
out("row #" + row++);
int columns = rs.getMetaData().getColumnCount();
for (int col=1; col <= columns; col++)
{
out( "\t" +
rs.getMetaData().getColumnName(col) + "\t=\t"
+ rs.getString(col));
}
out("");
}
out("\n");
}
} while (cstmt.getMoreResults());
dbconnection.close();
}
static void out(Object o) {
System.out.println(o);
}
}
サンプルコード一式: https://github.com/Intersystems-jp/MultipleResultSetSample