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 ? (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 o 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. Observe que os nomes de parâmetro correspondem aos nomes de parâmetro 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"));
}
}
Para drivers versão 12.6 e superiores, foi introduzida uma nova propriedade de conexão useFlexibleCallableStatements
. Quando definida como true
, esta propriedade mantém o comportamento antigo do driver, permitindo que os usuários usem uma combinação de posições ordinais e nomes de parâmetros ao identificar parâmetros. Quando definido como false
, o usuário deve usar um ou outro, mas não pode usar ambos.
Além disso, useFlexibleCallableStatements
mantém o comportamento existente em relação aos parâmetros flexíveis da instrução de solicitação que podem ser definidos quando a propriedade é definida comotrue
. Entretanto, quando definida como false
, a ordem deve corresponder à definição do procedimento armazenado. Ambos os recursos para useFlexibleCallableStatements=true
podem ser vistos no exemplo a seguir:
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"));
}
}
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 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.
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de