Como usar um procedimento armazenado com parâmetros de saída
Um procedimento armazenado do SQL Server que pode ser chamado é aquele que retorna um ou mais parâmetros OUT, que são parâmetros usados pelo procedimento armazenado para retornar os dados ao aplicativo de chamada. O Microsoft JDBC Driver para SQL Server fornece a classe SQLServerCallableStatement que pode ser usada para chamar esse tipo de procedimento armazenado e processar os dados que ele retorna.
Ao chamar esse tipo de procedimento armazenado usando o driver JDBC, você precisa usar a sequência de escape call
do SQL junto com o método prepareCall da classe SQLServerConnection. A sintaxe da sequência de escape call
com parâmetros OUT é a seguinte:
{call procedure-name[([parameter][,[parameter]]...)]}
Observação
Para obter mais informações sobre as sequências de escape SQL, confira Como usar sequências de escape do SQL.
Ao construir a sequência de escape call
, especifique os parâmetros OUT usando o caractere de ponto de interrogação (?). Esse caractere age como um espaço reservado para os valores de parâmetros que retornarão do procedimento armazenado. Para especificar um valor para um parâmetro OUT, especifique o tipo de dados de cada parâmetro usando o método registerOutParameter da classe SQLServerCallableStatement antes de executar o procedimento armazenado.
O valor especificado para o parâmetro OUT no método registerOutParameter precisa ser um dos tipos de dados do JDBC contidos em java.sql.Types que, por sua vez, é mapeado para um dos tipos de dados nativos do SQL Server. Para obter mais informações sobre os tipos de dados JDBC e SQL Server, confira Noções básicas sobre os tipos de dados do JDBC Driver.
Ao passar para o método registerOutParameter um valor para um parâmetro OUT, especifique não só o tipo de dados a ser usado para o parâmetro, mas também o posicionamento ordinal do parâmetro ou o nome do parâmetro no procedimento armazenado. Por exemplo, se seu procedimento armazenado contiver um único parâmetro OUT, seu valor ordinal será 1. Se o procedimento armazenado contiver dois parâmetros, o primeiro valor ordinal será 1 e o segundo valor ordinal será 2.
Observação
O driver JDBC não dá suporte ao uso dos tipos de dados CURSOR, SQLVARIANT, TABLE e TIMESTAMP do SQL Server como parâmetros OUT.
Como exemplo, crie o seguinte procedimento armazenado no banco de dados de exemplo AdventureWorks2022:
CREATE PROCEDURE GetImmediateManager
@employeeID INT,
@managerID INT OUTPUT
AS
BEGIN
SELECT @managerID = ManagerID
FROM HumanResources.Employee
WHERE EmployeeID = @employeeID
END
Esse procedimento armazenado retorna um único parâmetro OUT (managerID), que é um inteiro, com base no parâmetro IN especificado (employeeID), que também é um inteiro. O valor retornado no parâmetro OUT é o ManagerID baseado no EmployeeID contido na tabela HumanResources.Employee
.
No seguinte exemplo, uma conexão aberta com o banco de dados de exemplo AdventureWorks2022 é passada para a função, e o método execute é usado para chamar o procedimento armazenado 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));
}
}
Esse exemplo usa as posições ordinais para identificar os parâmetros. Como alternativa, você pode identificar um parâmetro usando seu nome em vez da sua posição ordinal. O exemplo de código a seguir modifica o exemplo anterior para demonstrar como usar os parâmetros nomeados em um aplicativo Java. Os nomes de parâmetros correspondem aos nomes de parâmetros na definição do procedimento armazenado:
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"));
}
}
Observação
Esses exemplos usam o método de execução da classe SQLServerCallableStatement para executar o procedimento armazenado. Ele é usado porque o procedimento armazenado também não retornou um conjunto de resultados. Se ele tivesse retornado, o método executeQuery teria sido usado.
Os procedimentos armazenados podem retornar contagens de atualização e vários conjuntos de resultados. O Microsoft JDBC Driver para SQL Server segue a especificação do JDBC 3.0, a qual declara que vários conjuntos de resultados e contagens de atualização devem ser recuperados antes que os parâmetros OUT sejam recuperados. Ou seja, o aplicativo deve recuperar todos os objetos ResultSet e as contagens de atualização antes de recuperar os parâmetros OUT usando os métodos CallableStatement.getter. Caso contrário, os objetos ResultSet e as contagens de atualizações que ainda não foram recuperados pelo driver serão perdidos quando os parâmetros OUT forem recuperados. Para obter mais informações sobre contagens de atualizações e vários conjuntos de resultados, confira Como usar um procedimento armazenado com uma contagem de atualização e Como usar vários conjuntos de resultados.