2017-11-15 25 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)을 유지합니다.

Java 클라이언트에서 Microsoft JDBC 드라이버 6.2를 사용하여 동일한 작업을 수행합니다. List<Map<String, Object>>으로 매개 변수를 지정하므로 몇 개의 parameterName -> parameterValue 목록이 필요합니다.

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는() 프로 시저에 전달되는 값을 갖는 파라미터의 개수 ?의 수와 유형 { call spName ?,?, ... , ? }의 캐릭터를 생성하고, 그래서 모든 99 개 개의 파라미터 : 다음 방법은 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을 지정하는 방법이있을 나타나지 않습니다. 우리는 우리가 valorized 매개 변수가 무엇이

// 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 드라이버의 "버그"또는 누락 된 기능이라고 생각했습니다. –