没有为存储过程定义参数 @x... MS_SQL JDBC
Parameter @x was not defined for stored procedure... with MS_SQL JDBC
我正在尝试在方法中使用 SQL 服务器 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
returns 列名 @a
但设置 st.setInt("@a",0)
returns 出现以下错误:
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 has been accepted, so this should no longer be a problem with versions 6.3.4 及更高版本。
是的,不幸的是不一致,对于 mssql-jdbc,DatabaseMetaData#getProcedureColumns
返回的参数名称与 CallableStatement#setInt
et 接受的名称不匹配。等。如果您认为它是一个错误,那么您应该创建一个 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
我正在尝试在方法中使用 SQL 服务器 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
returns 列名 @a
但设置 st.setInt("@a",0)
returns 出现以下错误:
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 has been accepted, so this should no longer be a problem with versions 6.3.4 及更高版本。
是的,不幸的是不一致,对于 mssql-jdbc,DatabaseMetaData#getProcedureColumns
返回的参数名称与 CallableStatement#setInt
et 接受的名称不匹配。等。如果您认为它是一个错误,那么您应该创建一个 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