この記事の著者は、Java を介して SQL Server のストアド プロシージャを呼び出す方法を紹介し、5 種類のストレージについて詳しく説明します。詳細は下記をご覧ください
1. パラメーターなしでストアド プロシージャを使用する
JDBC ドライバーを使用してパラメーターなしでストアド プロシージャを呼び出す場合は、呼び出し SQL エスケープ シーケンスを使用する必要があります。パラメーターのない呼び出しエスケープ シーケンスの構文は次のとおりです。
次のようにコードをコピーします。
{呼び出しプロシージャ名}
例として、SQL Server 2005 AdventureWorks サンプル データベースに次のストアド プロシージャを作成します。
次のようにコードをコピーします。
プロシージャの作成 GetContactFormalNames
として
始める
上位 10 件のタイトル + ' ' + 名 + ' ' + 姓を正式名として選択
FROM 担当者連絡先
終わり
このストアド プロシージャは、Person.Contact テーブル内の最初の 10 人の連絡先の役職、名、姓で構成されるデータ列を含む 1 つの結果セットを返します。
次の例では、この関数に、AdventureWorks サンプル データベースへのオープン接続が渡され、executeQuery メソッドを使用して GetContactFormalNames ストアド プロシージャが呼び出されます。
次のようにコードをコピーします。
public static voidexecuteSprocNoParams(Connection con) ...{
試す...{
ステートメント stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("{call dbo.GetContactFormalNames}");
while (rs.next()) ...{
System.out.println(rs.getString("FormalName"));
}
rs.close();
stmt.close();
}
catch (例外 e) ...{
e.printStackTrace();
}
}
2. 入力パラメータを含むストアド プロシージャを使用する
JDBC ドライバーを使用してパラメーターを指定してストアド プロシージャを呼び出す場合は、呼び出し SQL エスケープ シーケンスを SQLServerConnection クラスの prepareCall メソッドと組み合わせて使用する必要があります。 IN パラメータを使用した呼び出しエスケープ シーケンスの構文は次のとおりです。
次のようにコードをコピーします。
{呼び出しプロシージャ名[([パラメータ][,[パラメータ]]...)]}
呼び出しエスケープ シーケンスを作成するときは、? (疑問符) 文字を使用して IN パラメータを指定します。この文字は、ストアド プロシージャに渡されるパラメータ値のプレースホルダとして機能します。 SQLServerPreparedStatement クラスのセッター メソッドの 1 つを使用して、パラメーターの値を指定できます。使用可能な設定メソッドは、IN パラメータのデータ型によって決まります。
値をセッター メソッドに渡すときは、パラメーターで使用される実際の値だけでなく、ストアド プロシージャ内のパラメーターの順序位置も指定する必要があります。たとえば、ストアド プロシージャに 1 つの IN パラメータが含まれる場合、その序数値は 1 になります。ストアド プロシージャに 2 つのパラメーターが含まれる場合、最初の序数値は 1 で、2 番目の序数値は 2 です。
IN パラメータを含むストアド プロシージャを呼び出す方法の例として、SQL Server 2005 AdventureWorks サンプル データベースの uspGetEmployeeManagers ストアド プロシージャを使用します。このストアド プロシージャは、整数値である EmployeeID という名前の単一の入力パラメータを受け入れ、指定された EmployeeID に基づいて従業員とそのマネージャーの再帰リストを返します。このストアド プロシージャを呼び出す Java コードは次のとおりです。
次のようにコードをコピーします。
public static voidexecuteSprocInParams(Connection con) ...{
試す...{
PreparedStatement pstmt = con.prepareStatement("{call dbo.uspGetEmployeeManagers(?)}");
pstmt.setInt(1, 50);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) ...{
System.out.println("従業員:");
System.out.println(rs.getString("姓") + ", " + rs.getString("名"));
System.out.println("マネージャー:");
System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName"));
System.out.println();
}
rs.close();
pstmt.close();
}
catch (例外 e) ...{
e.printStackTrace();
}
}
3. 出力パラメーターを含むストアド プロシージャを使用する
JDBC ドライバーを使用してこのようなストアド プロシージャを呼び出す場合は、呼び出し SQL エスケープ シーケンスを SQLServerConnection クラスの prepareCall メソッドと組み合わせて使用する必要があります。 OUT パラメータを使用した呼び出しエスケープ シーケンスの構文は次のとおりです。
次のようにコードをコピーします。
{呼び出しプロシージャ名[([パラメータ][,[パラメータ]]...)]}
呼び出しエスケープ シーケンスを作成するときは、? (疑問符) 文字を使用して OUT パラメータを指定します。この文字は、このストアド プロシージャから返されるパラメーター値のプレースホルダーとして機能します。 OUT パラメーターの値を指定するには、ストアド プロシージャを実行する前に、SQLServerCallableStatement クラスの registerOutParameter メソッドを使用して各パラメーターのデータ型を指定する必要があります。
registerOutParameter メソッドを使用して OUT パラメータに指定する値は、java.sql.Types に含まれる JDBC データ型の 1 つである必要があり、これはネイティブ SQL Server データ型の 1 つにマップされます。 JDBC および SQL Server のデータ型の詳細については、「JDBC ドライバーのデータ型について」を参照してください。
OUT パラメータの registerOutParameter メソッドに値を渡すときは、パラメータに使用するデータ型を指定するだけでなく、ストアド プロシージャ内のパラメータの序数位置またはパラメータの名前も指定する必要があります。たとえば、ストアド プロシージャに 1 つの OUT パラメータが含まれる場合、その順序値は 1 になります。ストアド プロシージャに 2 つのパラメータが含まれる場合、最初の順序値は 1、2 番目の順序値は 2 になります。
例として、SQL Server 2005 AdventureWorks サンプル データベースに次のストアド プロシージャを作成します。指定された整数の IN パラメータ (employeeID) に基づいて、このストアド プロシージャは単一の整数の OUT パラメータ (managerID) も返します。 HumanResources.Employee テーブルに含まれる EmployeeID に基づいて、OUT パラメータに返される値は ManagerID です。
次の例では、この関数に、AdventureWorks サンプル データベースへのオープン接続が渡され、execute メソッドを使用して GetImmediateManager ストアド プロシージャが呼び出されます。
次のようにコードをコピーします。
public static voidexecuteStoredProcedure(Connection con) ...{
試す...{
CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");
cstmt.setInt(1, 5);
cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
cstmt.execute();
System.out.println("マネージャーID: " + cstmt.getInt(2));
}
catch (例外 e) ...{
e.printStackTrace();
}
}
この例では、順序位置を使用してパラメーターを識別します。あるいは、パラメータは順序位置ではなく名前によって識別することもできます。次のコード例は、前の例を変更して、Java アプリケーションで名前付きパラメータを使用する方法を示しています。これらのパラメーター名は、ストアド プロシージャの定義内のパラメーター名に対応していることに注意してください: 11x16CREATE PROCEDURE GetImmediateManager
次のようにコードをコピーします。
@従業員ID INT、
@managerID INT 出力
として
始める
SELECT @マネージャーID = マネージャーID
FROM 人事.従業員
WHERE 従業員ID = @従業員ID
終わり
ストアド プロシージャは、更新カウントと複数の結果セットを返す場合があります。 Microsoft SQL Server 2005 JDBC ドライバは、OUT パラメータを取得する前に複数の結果セットと更新カウントを取得する必要があると規定されている JDBC 3.0 仕様に準拠しています。つまり、アプリケーションは最初にすべての ResultSet オブジェクトを取得してカウントを更新し、次に CallableStatement.getter メソッドを使用して OUT パラメータを取得する必要があります。そうしないと、OUT パラメータを取得するときに、まだ取得されていない ResultSet オブジェクトと更新数が失われます。
4. リターンステータスのあるストアドプロシージャを使用する
JDBC ドライバーを使用してこのようなストアド プロシージャを呼び出す場合は、呼び出し SQL エスケープ シーケンスを SQLServerConnection クラスの prepareCall メソッドと組み合わせて使用する必要があります。ステータス パラメータを返す呼び出しエスケープ シーケンスの構文は次のとおりです。
次のようにコードをコピーします。
{[?=]呼び出しプロシージャ名[([パラメータ][,[パラメータ]]...)]}
呼び出しエスケープ シーケンスを作成するときは、? (疑問符) 文字を使用して戻りステータス パラメータを指定します。この文字は、このストアド プロシージャから返されるパラメーター値のプレースホルダーとして機能します。戻りステータス パラメーターの値を指定するには、ストアド プロシージャを実行する前に、SQLServerCallableStatement クラスの registerOutParameter メソッドを使用してパラメーターのデータ型を指定する必要があります。
さらに、戻りステータス パラメーターの値を registerOutParameter メソッドに渡すときは、使用するパラメーターのデータ型だけでなく、ストアド プロシージャ内のパラメーターの順序位置も指定する必要があります。ストアド プロシージャが呼び出されるとき、戻りステータス パラメータは常に最初のパラメータとなるため、戻りステータス パラメータの序数位置は常に 1 です。 SQLServerCallableStatement クラスでは、特定のパラメーターを示すパラメーター名の使用がサポートされていますが、返されるステータス パラメーターにはパラメーターの序数位置番号のみを使用できます。
例として、SQL Server 2005 AdventureWorks サンプル データベースに次のストアド プロシージャを作成します。
次のようにコードをコピーします。
プロシージャの作成 CheckContactCity
(@cityName CHAR(50))
として
始める
IF ((SELECT COUNT(*)
FROM 人の住所
WHERE 都市 = @cityName) > 1)
リターン1
それ以外
リターン0
終わり
ストアド プロシージャは、cityName パラメーターで指定された都市が Person.Address テーブルで見つかるかどうかに応じて、1 または 0 のステータス値を返します。
次の例では、この関数にオープン接続が AdventureWorks サンプル データベースに渡され、execute メソッドを使用して CheckContactCity ストアド プロシージャが呼び出されます。
次のようにコードをコピーします。
public static voidexecuteStoredProcedure(Connection con) ...{
試す...{
CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}");
cstmt.registerOutParameter(1, java.sql.Types.INTEGER);
cstmt.setString(2, "アトランタ");
cstmt.execute();
System.out.println("戻りステータス: " + cstmt.getInt(1));
}
cstmt.close();
catch (例外 e) ...{
e.printStackTrace();
}
}
5. 更新回数を指定したストアド プロシージャを使用する
SQLServerCallableStatement クラスを使用してストアド プロシージャへの呼び出しを構築した後、execute メソッドまたはexecuteUpdate メソッドを使用してストアド プロシージャを呼び出すことができます。 executeUpdate メソッドは、このストアド プロシージャの影響を受ける行数を含む int 値を返しますが、execute メソッドはこの値を返しません。 execute メソッドを使用し、影響を受ける行数を取得したい場合は、ストアド プロシージャの実行後に getUpdateCount メソッドを呼び出すことができます。
例として、SQL Server 2005 AdventureWorks サンプル データベースに次のテーブルとストアド プロシージャを作成します。
次のようにコードをコピーします。
CREATE TABLE テストテーブル
(Col1 int IDENTITY,
Col2 varchar(50)、
Col3 int);
CREATE PROCEDURE UpdateTestTable
@Col2 varchar(50)、
@Col3 int
として
始める
テストテーブルの更新
SET Col2 = @Col2、Col3 = @Col3
終わり;
次の例では、この関数には、AdventureWorks サンプル データベースへのオープン接続が渡され、execute メソッドを使用して UpdateTestTable ストアド プロシージャを呼び出し、次に getUpdateCount メソッドを使用してストアド プロシージャの影響を受ける行数を返します。
次のようにコードをコピーします。
public static voidexecuteUpdateStoredProcedure(Connection con) ...{
試す...{
CallableStatement cstmt = con.prepareCall("{call dbo.UpdateTestTable(?, ?)}");
cstmt.setString(1, "A");
cstmt.setInt(2, 100);
cstmt.execute();
int カウント = cstmt.getUpdateCount();
cstmt.close();
System.out.println("影響を受ける行: " + count);
}
catch (例外 e) ...{
e.printStackTrace();