java - 参数 @x 没有为存储过程定义...使用 MS_SQL JDBC

标签 java sql-server stored-procedures jdbc mssql-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: Parameter @a was not defined for stored procedure ABC.

相反,我尝试了这个:st.setInt("a",0) 并且它执行得很完美。

现在的问题是我必须动态设置参数,因为我有太多的存储过程和太多的参数,但是 jdbc 给出了错误。

编辑 1:

正如在一个答案中指出的那样,我的问题与以下问题重复:Named parameters in JDBC , 我想解释一下这里的问题不是命名参数或位置参数,而是关于 JDBC 没有正确处理 SQL 服务器参数本身或者我在调用它时出错。

最佳答案

2017-10-07 更新:merge request to fix this issue已被接受,所以这应该不再是版本 6.3.4 的问题及以后。


是的,不幸的是不一致,对于 mssql-jdbc,DatabaseMetaData#g​​etProcedureColumns 返回的参数名称与 CallableStatement#setInt 接受的名称不匹配 等。等。。如果您认为这是一个错误,那么您应该创建一个 issue on 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

关于java - 参数 @x 没有为存储过程定义...使用 MS_SQL JDBC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46294187/

相关文章:

c# - Linq 加入表中的最后一个实例

mysql - mysql 中 if...end-if 存储过程出错

mysql - 每 5 次插入更改一些值(MySQL 存储过程)

sql-server - SQL Server 存储过程区分大小写?

java - android:ime 渲染问题

java - 创建一个全局对象或多个局部对象

java - Java 读取文本文件并将内容存储到列表中

SQL 更新日期时间条目

java - 通过 Spring XmlWebApplicationContext 指定相对资源路径

sql-server - 区域日期格式和数据库日期格式的不同日期格式的 SQL Server 错误