stored salida registrados procedimientos procedimiento parámetros parametros número nombres llamar ejemplo ejecutar desde con coincide callablestatement almacenados almacenado java sql-server stored-procedures jdbc mssql-jdbc

java - salida - El parámetro @x no se definió para el procedimiento almacenado... con MS_SQL JDBC



procedimiento almacenado sql server ejemplo (1)

Estoy tratando de ejecutar un procedimiento almacenado utilizando SQL Server JDBC en un método:

//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 }

Supongamos que el nombre del procedimiento almacenado es ABC y el parámetro es @a . Ahora DatabaseMetaData devuelve el nombre de la columna @a pero la configuración de st.setInt("@a",0) devuelve el siguiente error:

com.microsoft.sqlserver.jdbc.SQLServerException: el parámetro @a no se definió para el procedimiento almacenado ABC.

En cambio, probé esto: st.setInt("a",0) y se ejecutó perfectamente.

Ahora el problema es que tengo que establecer los parámetros dinámicamente ya que tengo demasiados procedimientos almacenados y demasiados parámetros, pero jdbc está dando error.

Editar 1:

Como mencioné en una respuesta que mi pregunta es un duplicado de: Parámetros con nombre en JDBC , me gustaría explicar que el problema aquí no se llama parámetros o posicionales, sino que se trata de que JDBC no maneje los parámetros del servidor SQL propiamente o Estoy cometiendo un error al invocarlo.


Actualización 2017-10-07: se ha aceptado la solicitud de fusión para solucionar este problema , por lo que ya no debería ser un problema con las versiones 6.3.4 y posteriores.

Sí, es una incoherencia desafortunada que para mssql-jdbc los nombres de parámetros devueltos por DatabaseMetaData#getProcedureColumns no coincidan con los nombres aceptados por CallableStatement#setInt et. Alabama. . Si considera que se trata de un error, debe crear un problema en GitHub y quizás se solucione en una versión futura.

Mientras tanto, sin embargo, tendrás que evitarlo. Entonces, en lugar de un código como este ...

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); } }

... que produce ...

@person @food

... necesitarás usar un código como este ...

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); } }

... que produce ...

person food