Empleo de un procedimiento almacenado con parámetros de salida

Descargar controlador JDBC

Un procedimiento almacenado de SQL Server al que se puede llamar es aquel que devuelve uno o más parámetros OUT, que son los parámetros que el procedimiento almacenado usa para devolver los datos a la aplicación que realiza la llamada. El controlador JDBC de Microsoft para SQL Server ofrece la clase SQLServerCallableStatement, que se puede usar para llamar a este tipo de procedimiento almacenado y procesar los datos que devuelve.

Cuando se llama a este tipo de procedimiento almacenado con JDBC Driver, se debe usar la secuencia de escape call de SQL junto con el método prepareCall de la clase SQLServerConnection. La sintaxis para la secuencia de escape call con parámetros OUT es la siguiente:

{call procedure-name[([parameter][,[parameter]]...)]}

Nota

Para obtener más información sobre las secuencias de escape de SQL, consulte Usar secuencias de escape de SQL.

Al crear la secuencia de escape call, especifique los parámetros OUT mediante el carácter ? (signo de interrogación). Este carácter actúa como un marcador de posición para los valores de parámetros devueltos por el procedimiento almacenado. Para especificar un valor para un parámetro OUT, debe especificar el tipo de datos de cada parámetro mediante el método registerOutParameter de la clase SQLServerCallableStatement antes de ejecutar el procedimiento almacenado.

El valor especificado para el parámetro OUT en el método registerOutParameter debe ser uno de los tipos de datos JDBC incluidos en java.sql.Types, que se asigna a su vez a uno de los tipos de datos nativos de SQL Server. Para obtener más información sobre el JDBC y los tipos de datos de SQL Server, consulte Comprender los tipos de datos del controlador JDBC.

Cuando pasa un valor al método registerOutParameter para un parámetro OUT, debe especificar no solo el tipo de datos que se usará para el parámetro, sino también la posición ordinal del parámetro o el nombre del mismo en el procedimiento almacenado. Por ejemplo, si el procedimiento almacenado contiene un solo parámetro OUT, su valor ordinal es 1 y, si el procedimiento almacenado contiene dos parámetros, el primer valor ordinal es 1 y el segundo 2.

Nota

JDBC Driver no admite el uso de los tipos de datos CURSOR, SQLVARIANT, TABLE y TIMESTAMP de SQL Server como parámetros OUT.

Cree, a modo de ejemplo, el siguiente procedimiento almacenado en la base de datos de ejemplo AdventureWorks2022:

CREATE PROCEDURE GetImmediateManager  
   @employeeID INT,  
   @managerID INT OUTPUT  
AS  
BEGIN  
   SELECT @managerID = ManagerID
   FROM HumanResources.Employee
   WHERE EmployeeID = @employeeID  
END

Este procedimiento almacenado devuelve un solo parámetro OUT (managerID), que es un entero, en función del parámetro IN (employeeID) especificado, que también es un entero. El valor devuelto en el parámetro OUT es ManagerID en función de EmployeeID en la tabla HumanResources.Employee.

En el siguiente ejemplo, se pasa a la función una conexión abierta a la base de datos de ejemplo AdventureWorks2022 y se usa el método execute para llamar al procedimiento almacenado GetImmediateManager:

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");) {  
        cstmt.setInt(1, 5);  
        cstmt.registerOutParameter(2, java.sql.Types.INTEGER);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt(2));  
    }  
}

Este ejemplo utiliza las posiciones ordinales para identificar los parámetros. También puede identificar un parámetro utilizando su nombre en lugar de su posición ordinal. En el ejemplo de código siguiente se modifica el ejemplo anterior para demostrar cómo utilizar los parámetros con nombre en una aplicación Java. Observe que los nombres de parámetros se corresponden con los nombres de parámetros en la definición del procedimiento almacenado:

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}"); ) {  
        cstmt.setInt("employeeID", 5);  
        cstmt.registerOutParameter("managerID", java.sql.Types.INTEGER);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt("managerID"));  
    }  
}

Para los controladores de la versión 12.6 y posteriores, se introdujo una nueva propiedad de conexión useFlexibleCallableStatements. Cuando se establece en true, esta propiedad conserva el comportamiento anterior del controlador, lo que permite a los usuarios usar una combinación de posiciones ordinales y nombres de parámetro al identificar parámetros. Cuando se establece en false, el usuario debe usar uno u otra, pero no puede usar ambas.

Además, useFlexibleCallableStatements conserva el comportamiento existente con respecto a los parámetros de instrucción de orden flexible en los que se puede establecer, cuando la propiedad está establecida en true. Sin embargo, cuando se establece en false, el orden debe coincidir con la definición del procedimiento almacenado. Ambas características de useFlexibleCallableStatements=true se pueden ver en el ejemplo siguiente:

public static void executeStoredProcedure(Connection con) throws SQLException {  
    try(CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}"); ) {
        cstmt.registerOutParameter("managerID", java.sql.Types.INTEGER);
        cstmt.setInt(1, 5);  
        cstmt.execute();  
        System.out.println("MANAGER ID: " + cstmt.getInt("managerID"));  
    }  
}

Nota:

En estos ejemplos se usa el método execute de la clase SQLServerCallableStatement para ejecutar el procedimiento almacenado. Se usa dicho método porque el procedimiento almacenado no ha devuelto ningún conjunto de resultados. En caso contrario, se usaría el método executeQuery.

Los procedimientos almacenados también pueden devolver recuentos de actualizaciones y múltiples conjuntos de resultados. El controlador JDBC de Microsoft para SQL Server sigue la especificación de JDBC 3.0, que indica que se deben recuperar varios conjuntos de resultados y recuentos de actualizaciones antes de recuperar los parámetros OUT. Es decir, la aplicación debería recuperar todos los objetos ResultSet y recuentos de actualizaciones antes de recuperar los parámetros OUT con los métodos CallableStatement.getter. De lo contrario, los objetos ResultSet y los recuentos de actualizaciones que aún no se hayan recuperado se perderán cuando se recuperen los parámetros OUT. Para obtener más información sobre los recuentos de actualizaciones y varios conjuntos de resultados, consulte Empleo de un procedimiento almacenado con un recuento de actualización y Empleo de varios conjuntos de resultados.

Consulte también

Empleo de instrucciones con procedimientos almacenados