2017-11-15 15 views
1

SQL Server 2016のインスタンスでは、数多くのパラメータを持つストアドプロシージャがあります。例:値を持つパラメータのみを指定してストアドプロシージャを呼び出す

私は、値を持つパラメータだけを指定してストアドプロシージャを呼び出すC#で書かれたクライアントを持っています。例:

SqlCommand cmd = new SqlCommand(); 

cmd.CommandText = "spName"; 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Connection = dbConn; 

cmd.Parameters.Add(new SqlParameter("par1", "val1")); 
cmd.Parameters.Add(new SqlParameter("par47", "val47")); 

... 

cmd.ExecuteNonQuery(); 

これは完全に機能します。したがって、プロシージャが実行され、2つのパラメータ(par1とpar47)のみが値を持ちます。他のパラメータはデフォルト値(NULL)を維持します。

Microsoft JDBCドライバ6.2を使用してJavaクライアントから同じことを行います。 私はパラメータをList<Map<String, Object>>で指定します。したがって、パラメータ名 - >パラメータ値の組み合わせのリスト。

private CallableStatement prepareStatement(String spName, Map<String, ?> parameters) throws SQLException { 
    setupConnection(); 
    CallableStatement stmt = null; 
    try { 
     stmt = conn.prepareCall(getSpCallString(spName, parameters)); 
     if (parameters != null) { 
      for (String parName : parameters.keySet()) 
       stmt.setObject(parName, parameters.get(parName)); 
     } 
    } catch (SQLException e) { 
     ApplicationLogging.severe("Cannot prepare callable statement", e); 
     throw e; 
    } 
    return stmt; 
} 

方法getSpCallString()プロシージャに渡された値を持つパラメータの数、そうではないすべての99個のパラメータとして?の数と種類{ call spName ?,?, ... , ? }の列を生成する:以下の方法は、PreparedStatementオブジェクトビルド。私は2つのパラメータを持っている場合、それは文字列{ call spName ?,? }を生成します。例par15 = val15とpar47 = val47それは、次の例外を発生させるために渡すことで は:

com.microsoft.sqlserver.jdbc.SQLServerException: The index 2 is out of range. 

私は、これは、ストアドプロシージャのパラメータが、数として呼び出しコマンドで?の同じ番号を入れて解決することができます。私は各ストアドプロシージャ(およびその位置)のパラメータの数を知らない! C#では、パラメータの名前だけが割り当てられているため、パラメータの数と順序は実際はブラックボックスになる可能性があるため、これは単純に解決されています。

Javaでこれを何らかの方法で実行できますか?

+0

のように呼び出すことができた。この

public static ResultSet executeStoredProcedureQuery( Connection conn, String spName, Map<String, Object> paramItems) throws SQLException { StringBuffer sqlBuf = new StringBuffer("EXEC "); sqlBuf.append(spName); int paramCount = 1; for (String paramName : paramItems.keySet()) { sqlBuf.append( (paramCount++ > 1 ? ", " : " ") + (paramName.startsWith("@") ? "" : "@") + paramName + "=?"); } String sql = sqlBuf.toString(); myLogger.log(Level.INFO, sql); // e.g., EXEC dbo.BreakfastSP @helpings=?, @person=?, @food=? PreparedStatement ps = conn.prepareStatement(sql); paramCount = 1; for (String paramName : paramItems.keySet()) { ps.setObject(paramCount++, paramItems.get(paramName)); } return ps.executeQuery(); } 

のようなコードを使用することができます回避策として

?私はその言葉に慣れていない。 –

+0

私は、ストアドプロシージャ(値がある)に与えるパラメータを意味します。他のパラメータは渡されないため、デフォルト値(NULL)が維持されます。 –

+0

名前付きパラメータに明示的に値を割り当てるSQL Server固有のストアドプロシージャコールを生成することはできません。 –

答えて

1

これは、mssql-jdbcドライバのCallableStatementの名前付きパラメータサポートの現在の実装ではconfirmed deficiencyです。 JDBC 4.2仕様のセクション13.3.2にもかかわらず...

名前付きパラメータを使用して、デフォルト値のない値のみを指定できます。

...我々はすべての可能なパラメータのパラメータプレースホルダを提供するために必要なように見える、と私たちはそう単純に省略するかもしれないパラメータについてDEFAULTを指定する方法があるように表示されません。私たちは付加価値化するパラメータであり、これは何

// test data 
Map<String, Object> paramItems = new HashMap<>(); 
paramItems.put("@person", "Gord"); 
paramItems.put("@food", "bacon"); 
paramItems.put("@helpings", 3); 
// 
ResultSet rs = executeStoredProcedureQuery(conn, "dbo.BreakfastSP", paramItems); 
+0

ありがとうございました。私はそれがMS Jdbsドライバの "バグ"または欠落した機能だとも考えました。 –

関連する問題