記事
Mihoko Iijima · 2021年7月15日 5m read

複数の結果セットを 一度に返す方法

これは 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 

00
1 0 0 11
Log in or sign up to continue