Share via


出力パラメーターがあるストアド プロシージャの使用

JDBC ドライバーのダウンロード

SQL Server ストアド プロシージャのうち、呼び出すことができるのは、OUT パラメーター (呼び出し元のアプリケーションにデータを返す目的で使用されるパラメーター) を少なくとも 1 つ返すストアド プロシージャです。 Microsoft JDBC Driver for SQL Server が提供する SQLServerCallableStatement クラスを使用することで、この種類のストアド プロシージャを呼び出し、返されるデータを処理することができます。

JDBC ドライバーを使用してこの種類のストアド プロシージャを呼び出す場合は、call SQL エスケープ シーケンスを、SQLServerConnection クラスの prepareCall メソッドと一緒に使用する必要があります。 OUT パラメーターを持つ call エスケープ シーケンスの構文は次のとおりです。

{call procedure-name[([parameter][,[parameter]]...)]}

注意

SQL エスケープ シーケンスの詳細については、「SQL エスケープ シーケンスの使用」を参照してください。

call エスケープ シーケンスを作成する場合、OUT パラメーターは ? (疑問符) 文字で指定します。 この文字は、ストアド プロシージャから返されるパラメーター値のプレースホルダーになります。 OUT パラメーターの値を指定するには、ストアド プロシージャを実行する前に、SQLServerCallableStatement クラスの registerOutParameter メソッドを使用して、各パラメーターのデータ型を指定する必要があります。

registerOutParameter メソッドで OUT パラメーターに指定する値は、java.sql.Types に含まれる JDBC データ型のいずれかである必要があります。この値は、ネイティブの SQL Server データ型の 1 つに順にマップされます。 JDBC データ型と SQL Server データ型の詳細については、「JDBC ドライバーのデータ型について」を参照してください。

registerOutParameter メソッドに OUT パラメーターの値を渡す場合は、パラメーターに使用するデータ型だけでなく、ストアド プロシージャ内のパラメーターの順序またはパラメーター名も指定する必要があります。 たとえば、ストアド プロシージャに 1 つの OUT パラメーターがある場合、その序数値は 1 です。ストアド プロシージャに 2 つのパラメーターがある場合、最初の序数値は 1 で、2 番目の序数値は 2 になります。

Note

JDBC ドライバーでは、CURSOR、SQLVARIANT、TABLE、および TIMESTAMP の SQL Server データ型を OUT パラメーターとして使用することはできません。

例として、AdventureWorks2022 サンプル データベースで次のストアド プロシージャを作成します。

CREATE PROCEDURE GetImmediateManager  
   @employeeID INT,  
   @managerID INT OUTPUT  
AS  
BEGIN  
   SELECT @managerID = ManagerID
   FROM HumanResources.Employee
   WHERE EmployeeID = @employeeID  
END

このストアド プロシージャでは 1 つの整数の OUT パラメーター (managerID) が返されます。これは、同様に整数である指定した IN パラメーター (employeeID) に基づいています。 OUT パラメーターで返される値は、HumanResources.Employee テーブルに含まれる EmployeeID に基づく ManagerID です。

次の例の関数は、AdventureWorks2022 サンプル データベースに対して開かれた接続を渡され、execute メソッドを使って GetImmediateManager ストアド プロシージャを呼び出します。

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");) {  
        cstmt.setInt(1, 5);  
        cstmt.registerOutParameter(2, java.sql.Types.INTEGER);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt(2));  
    }  
}

この例では、序数位置を使用してパラメーターを識別しています。 序数位置の代わりに名前を使用してパラメーターを識別することもできます。 次のコード例では、前の例を変更して、Java アプリケーションで名前付きパラメーターを使用する方法を示します。 パラメーター名は、ストアド プロシージャの定義内にあるパラメーター名に対応しています。

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}"); ) {  
        cstmt.setInt("employeeID", 5);  
        cstmt.registerOutParameter("managerID", java.sql.Types.INTEGER);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt("managerID"));  
    }  
}

ドライバー バージョン 12.6 以降では、新しい接続プロパティ useFlexibleCallableStatements が導入されました。 true に設定すると、このプロパティによってドライバーの古い動作が保持され、ユーザーはパラメーターを識別するときに序数の位置とパラメーター名を組み合わせて使用できます。 false に設定すると、ユーザーはいずれか一方を使用する必要がありますが、両方を使用することはできません。

さらに、プロパティが true に設定されている場合、useFlexibleCallableStatements は柔軟な order ステートメント パラメーターに関する既存の動作を保持します。 ただし、false に設定すると、この順序は ストアド プロシージャの定義と一致する必要があります。 useFlexibleCallableStatements=true のこれらの機能の両方を次の例に示します。

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}"); ) {
        cstmt.registerOutParameter("managerID", java.sql.Types.INTEGER);
        cstmt.setInt(1, 5);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt("managerID"));  
    }  
}

Note

これらの例では、SQLServerCallableStatement クラスの execute メソッドを使用してストアド プロシージャを実行します。 このメソッドを使用しているのは、ストアド プロシージャによって結果セットが返されないためです。 結果セットが返される場合は、executeQuery メソッドを使用します。

ストアド プロシージャは、更新数および複数の結果セットを返すことができます。 Microsoft JDBC Driver for SQL Server が準拠している JDBC 3.0 仕様は、複数の結果セットと更新数が、OUT パラメーターの取得前に取得されなければならない旨が規定されています。 つまり、アプリケーションで CallableStatement.getter メソッドを使用して、OUT パラメーターを取得する前に、すべての ResultSet オブジェクトおよび更新数を取得する必要があります。 そうしないと、OUT パラメーターの取得時に、未取得の ResultSet オブジェクトおよび更新数が失われます。 更新数および複数の結果セットの詳細については、「更新数があるストアド プロシージャの使用」と「複数の結果セットの使用」を参照してください。

関連項目

ストアド プロシージャでのステートメントの使用