簡體   English   中英

未為存儲過程定義參數@ x…使用MS_SQL JDBC

[英]Parameter @x was not defined for stored procedure… with MS_SQL JDBC

我正在嘗試在一種方法中使用SQL Server JDBC執行存儲過程:

//Connection connection, String sp_name, Map<String, Object>params input to the method
DatabaseMetaData dbMetaData = connection.getMetaData();
HashMap<String, Integer> paramInfo = new HashMap<String, Integer>();
if (dbMetaData != null)
{
        ResultSet rs = dbMetaData.getProcedureColumns (null, null, sp_name.toUpperCase(), "%");
        while (rs.next())
            paramInfo.put(rs.getString(4), rs.getInt(6));
        rs.close();
}
String call = "{ call " + sp_name + " ( ";
for (int i = 0; i < paramInfo.size(); i ++)
    call += "?,";
if (paramInfo.size() > 0)
    call = call.substring(0, call.length() - 1);
call += " ) }";
CallableStatement st = connection.prepareCall (call);
for (String paramName: paramInfo.keySet()){
    int paramType = paramInfo.get(paramName);
    System.out.println("paramName="+paramName);
    System.out.println("paramTYpe="+paramType);
    Object paramVal = params.get(paramName);
    st.setInt(paramName, Integer.parseInt(((String)paramVal))); //All stored proc parameters are of type int
}

假設存儲過程的名稱為ABC ,參數為@a 現在DatabaseMetaData返回列名@a但是設置st.setInt("@a",0)返回以下錯誤:

com.microsoft.sqlserver.jdbc.SQLServerException:未為存儲過程ABC定義參數@a。

相反,我嘗試了一下: st.setInt("a",0) ,它執行得很好。

現在的問題是我必須動態設置參數,因為我有太多的存儲過程和太多的參數,但是jdbc給出了錯誤。

編輯1:

正如一個答案中指出的那樣,我的問題是以下內容的重復: JDBC中的命名參數 ,我想解釋一下這里的問題不是命名參數或位置參數,而是關於JDBC無法正確處理SQL Server參數本身或我在調用它時出錯了。

更新2017年10月7日: 修復了此問題合並請求已被接受,因此版本6.3.4和更高版本不再是問題。


是的,對於mssql-jdbc,不幸的不一致之處是DatabaseMetaData#getProcedureColumns返回的參數名稱與CallableStatement#setInt 接受的名稱不匹配 如果您認為它是一個錯誤,則應在GitHub上創建一個問題 ,也許它將在將來的版本中得到修復。

但是,與此同時,您只需要解決它。 因此,而不是像這樣的代碼...

ResultSet rs = connection.getMetaData().getProcedureColumns(null, "dbo", "MenuPlanner", null);
while (rs.next()) {
    if (rs.getShort("COLUMN_TYPE") == DatabaseMetaData.procedureColumnIn) {
        String inParamName = rs.getString("COLUMN_NAME");
        System.out.println(inParamName);
    }
}

...產生...

@person
@food

...您將需要使用這樣的代碼...

boolean isMssqlJdbc = connection.getClass().getName().equals(
        "com.microsoft.sqlserver.jdbc.SQLServerConnection");
ResultSet rs = connection.getMetaData().getProcedureColumns(null, "dbo", "MenuPlanner", null);
while (rs.next()) {
    if (rs.getShort("COLUMN_TYPE") == DatabaseMetaData.procedureColumnIn) {
        String inParamName = rs.getString("COLUMN_NAME");
        if (isMssqlJdbc && inParamName.startsWith("@")) {
            inParamName = inParamName.substring(1, inParamName.length());
        }
        System.out.println(inParamName);
    }
}

...產生...

person
food

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM