Especificar parâmetros em um procedimento armazenado
Aplica-se a:Banco de Dados SQL do Azure
Banco de Dados Azure SQL
Instância Gerenciada SQL do Azure
Azure Synapse Analytics
Analytics Platform System (PDW)
Banco de Dados SQL no Microsoft Fabric
Ao especificar parâmetros de procedimento, os programas de chamada são capazes de passar valores para o corpo do procedimento. Esses valores podem ser usados para uma variedade de finalidades durante a execução do procedimento. Os parâmetros de procedimento também podem retornar valores para o programa de chamada se o parâmetro estiver marcado como um parâmetro OUTPUT.
Um procedimento pode ter um máximo de 2100 parâmetros; Cada um atribuiu um nome, tipo de dados e direção. Opcionalmente, os parâmetros podem ser atribuídos valores padrão.
A seção a seguir fornece informações sobre como passar valores em parâmetros e sobre como cada um dos atributos de parâmetro é usado durante uma chamada de procedimento.
Observação
Consulte a série AdventureWorks
de bancos de dados de exemplo para os exercícios deste artigo. Para obter mais informações, consulte bancos de dados de exemplo do AdventureWorks.
Passar valores em parâmetros
Os valores dos parâmetros fornecidos com uma chamada de procedimento devem ser constantes ou uma variável; Um nome de função não pode ser usado como um valor de parâmetro. As variáveis podem ser definidas pelo usuário ou variáveis do sistema, como @@spid
.
Os exemplos a seguir demonstram a passagem de valores de parâmetros para o procedimento uspGetWhereUsedProductID
. Eles ilustram como passar parâmetros como constantes e variáveis e também como usar uma variável para passar o valor de uma função.
USE AdventureWorks2022;
GO
-- Passing values as constants.
EXEC dbo.uspGetWhereUsedProductID 819, '20050225';
GO
-- Passing values as variables.
DECLARE @ProductID int, @CheckDate datetime;
SET @ProductID = 819;
SET @CheckDate = '20050225';
EXEC dbo.uspGetWhereUsedProductID @ProductID, @CheckDate;
GO
O exemplo a seguir retorna um erro porque uma função não pode ser passada como um valor de parâmetro.
-- Try to use a function as a parameter value.
-- This produces an error message.
EXEC dbo.uspGetWhereUsedProductID 819, GETDATE();
Em vez disso, use uma variável para passar um valor de função para o parâmetro, como no exemplo a seguir:
-- Passing the function value as a variable.
DECLARE @CheckDate datetime;
SET @CheckDate = GETDATE();
EXEC dbo.uspGetWhereUsedProductID 819, @CheckDate;
GO
Especificar nomes de parâmetros
Ao criar um procedimento e declarar um nome de parâmetro, o nome do parâmetro deve começar com um único caractere @
e deve ser exclusivo no escopo do procedimento.
Nomear explicitamente os parâmetros e atribuir os valores apropriados a cada parâmetro em uma chamada de procedimento permite que os parâmetros sejam fornecidos em qualquer ordem. Por exemplo, se o procedimento my_proc
espera três parâmetros chamados @first
, @second
e @third
, os valores passados para o procedimento podem ser atribuídos aos nomes dos parâmetros, como: EXECUTE my_proc @second = 2, @first = 1, @third = 3;
.
Observação
Se um valor de parâmetro for fornecido na forma @parameter = value
, todos os parâmetros subsequentes devem ser fornecidos dessa maneira. Se os valores dos parâmetros não forem passados na forma @parameter = value
, os valores devem ser fornecidos na mesma ordem (da esquerda para a direita) como os parâmetros são listados na instrução CREATE PROCEDURE. É uma boa prática especificar nomes de parâmetros, tanto para uma legibilidade superior quanto para compatibilidade com versões futuras do procedimento armazenado.
Advertência
Qualquer parâmetro passado no formulário @parameter = value
com o parâmetro escrito incorretamente, fará com que o SQL Server gere um erro e impeça a execução do procedimento.
Especificar tipos de dados de parâmetros
Os parâmetros devem ser definidos com um tipo de dados quando são declarados em uma instrução CREATE PROCEDURE. O tipo de dados de um parâmetro determina o tipo e o intervalo de valores que são aceitos para o parâmetro quando o procedimento é chamado. Por exemplo, se você definir um parâmetro com um tipo de dados tinyint, somente valores numéricos que variam de 0 a 255 serão aceitos quando passados para esse parâmetro. Um erro é retornado se um procedimento é executado com um valor incompatível com o tipo de dados.
Especificar valores padrão de parâmetro
Um parâmetro é considerado opcional se tiver um valor padrão especificado quando for declarado. Não é necessário fornecer um valor para um parâmetro opcional em uma chamada de procedimento.
O valor padrão de um parâmetro é usado quando:
- Nenhum valor para o parâmetro é especificado na chamada de procedimento.
- A palavra-chave DEFAULT é especificada como o valor na chamada de procedimento.
Observação
Se o valor padrão for uma cadeia de caracteres que contenha espaços em branco ou pontuação incorporados, ou se começar com um número (por exemplo, 6abc
), ele deverá ser colocado entre aspas simples e retas.
Observação
Os parâmetros padrão não são suportados no Azure Synapse Analytics ou no Analytics Platform System (PDW).
Se nenhum valor puder ser especificado adequadamente como padrão para o parâmetro, especifique NULL
como padrão. É uma boa ideia fazer com que o procedimento retorne uma mensagem personalizada se o procedimento for executado sem um valor para o parâmetro.
O exemplo a seguir cria o procedimento uspGetSalesYTD
com um parâmetro de entrada, @SalesPerson
.
NULL
é atribuído como o valor padrão para o parâmetro e é usado em instruções de tratamento de erros para retornar uma mensagem de erro personalizada para casos em que o procedimento é executado sem um valor para o parâmetro @SalesPerson
.
USE AdventureWorks2022;
GO
IF OBJECT_ID('Sales.uspGetSalesYTD', 'P') IS NOT NULL
DROP PROCEDURE Sales.uspGetSalesYTD;
GO
CREATE PROCEDURE Sales.uspGetSalesYTD
@SalesPerson nvarchar(50) = NULL -- NULL default value
AS
SET NOCOUNT ON;
-- Validate the @SalesPerson parameter.
IF @SalesPerson IS NULL
BEGIN
PRINT 'ERROR: You must specify the last name of the sales person.'
RETURN
END
-- Get the sales for the specified sales person and
-- assign it to the output parameter.
SELECT SalesYTD
FROM Sales.SalesPerson AS sp
JOIN HumanResources.vEmployee AS e ON e.BusinessEntityID = sp.BusinessEntityID
WHERE LastName = @SalesPerson;
RETURN
GO
O exemplo a seguir executa o procedimento. A primeira instrução executa o procedimento sem especificar um valor de entrada. Isso faz com que as instruções de tratamento de erro no procedimento retornem a mensagem de erro personalizada. A segunda instrução fornece um valor de entrada e retorna o conjunto de resultados esperados.
-- Run the procedure without specifying an input value.
EXEC Sales.uspGetSalesYTD;
GO
-- Run the procedure with an input value.
EXEC Sales.uspGetSalesYTD N'Blythe';
GO
Embora os parâmetros para os quais os valores padrão estão definidos possam ser omitidos, a lista de parâmetros não nulos apenas pode ser truncada. Por exemplo, se um procedimento tiver cinco parâmetros, sem especificar os nomes dos parâmetros com um @parameter = value
, o quarto e o quinto parâmetros podem ser omitidos. No entanto, o quarto parâmetro não pode ser ignorado, desde que o quinto parâmetro esteja incluído, a menos que os parâmetros sejam fornecidos na forma @parameter = value
.
Especificar vários parâmetros com valores padrão
Você pode omitir parâmetros se especificar os nomes dos parâmetros. Considere o seguinte procedimento armazenado com vários parâmetros opcionais com valores padrão de NULL
.
USE AdventureWorks2022;
GO
IF OBJECT_ID ( 'Production.uspSearchList', 'P' ) IS NOT NULL
DROP PROCEDURE Production.uspSearchList;
GO
CREATE PROCEDURE Production.uspSearchList
@ListPrice money
, @ProductCategoryID int = NULL -- NULL default value
, @ProductSubcategoryID int = NULL -- NULL default value
, @ProductBusinessEntityID int = NULL -- NULL default value
AS
SET NOCOUNT ON;
SELECT
p.Name, p.Class, p.ListPrice, p.ProductID, pc.Name, psc.Name, v.Name
FROM
Production.Product AS p
INNER JOIN Production.ProductSubCategory AS psc ON p.ProductSubcategoryID = psc.ProductSubcategoryID
INNER JOIN Production.ProductCategory AS pc ON psc.ProductCategoryID = pc.ProductCategoryID
INNER JOIN Purchasing.ProductVendor AS pv ON p.ProductID = pv.ProductID
INNER JOIN Purchasing.Vendor AS v ON pv.BusinessEntityID = v.BusinessEntityID
WHERE (p.ListPrice < @ListPrice)
AND (pc.ProductCategoryID = @ProductCategoryID or @ProductCategoryID IS NULL)
AND (psc.ProductSubcategoryID = @ProductSubcategoryID or @ProductSubcategoryID IS NULL)
AND (pv.BusinessEntityID = @ProductBusinessEntityID or @ProductBusinessEntityID IS NULL);
GO
Você pode especificar ou omitir parâmetros com valores padrão, como demonstra a série de exemplos a seguir, desde que cada um seja fornecido com seu nome de parâmetro no formato @parameter = value
:
--Find all Products with a list price less than 150.00 and in the ProductCategoryID = 4
EXEC Production.uspSearchList @ListPrice = 150, @ProductCategoryID = 4;
--Find all Products with a list price less than 150.00 and in the ProductSubCategoryID = 36
EXEC Production.uspSearchList @ListPrice = 150, @ProductSubCategoryID = 36;
--Find all Products with a list price less than 150.00 and from @ProductBusinessEntityID = 1498
EXEC Production.uspSearchList @ListPrice = 150, @ProductBusinessEntityID = 1498;
--Find all Products with a list price less than 150.00 and in the ProductSubCategoryID = 36 and from @ProductBusinessEntityID = 1498
EXEC Production.uspSearchList @ListPrice = 150, @ProductCategoryID = 4, @ProductBusinessEntityID = 1498;
O exemplo a seguir não é uma sintaxe T-SQL válida, porque todos os parâmetros subsequentes devem ser fornecidos da mesma maneira, uma vez que um nome de parâmetro é fornecido. O fornecimento de nomes de parâmetros para todos os valores é sempre recomendado e evita erros e confusão.
EXEC Production.uspSearchList @ListPrice = 150, 4, 1498;
Especificar a direção do parâmetro
A direção de um parâmetro pode ser de entrada, onde um valor é passado para o corpo do procedimento, ou de saída, onde o procedimento retorna um valor para o programa chamador. O padrão é um parâmetro de entrada.
Para especificar um parâmetro de saída, a palavra-chave OUTPUT deve ser especificada na definição do parâmetro na instrução CREATE PROCEDURE. O procedimento retorna o valor atual do parâmetro de saída para o programa de chamada quando o procedimento é encerrado. O programa de chamada também deve usar a palavra-chave OUTPUT ao executar o procedimento para salvar o valor do parâmetro em uma variável que pode ser usada no programa de chamada.
O exemplo a seguir cria o procedimento Production.usp_GetList
, que retorna uma lista de produtos com preços que não excedem um valor especificado. O exemplo mostra o uso de várias instruções SELECT e vários parâmetros OUTPUT. Os parâmetros OUTPUT permitem que um procedimento externo, um lote ou mais de uma instrução Transact-SQL acesse um conjunto de valores durante a execução do procedimento.
USE AdventureWorks2022;
GO
IF OBJECT_ID ( 'Production.uspGetList', 'P' ) IS NOT NULL
DROP PROCEDURE Production.uspGetList;
GO
CREATE PROCEDURE Production.uspGetList
@Product varchar(40)
, @MaxPrice money
, @ComparePrice money OUTPUT
, @ListPrice money OUT
AS
SET NOCOUNT ON;
SELECT p.[Name] AS Product, p.ListPrice AS 'List Price'
FROM Production.Product AS p
JOIN Production.ProductSubcategory AS s
ON p.ProductSubcategoryID = s.ProductSubcategoryID
WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice;
-- Populate the output variable @ListPprice.
SET @ListPrice = (SELECT MAX(p.ListPrice)
FROM Production.Product AS p
JOIN Production.ProductSubcategory AS s
ON p.ProductSubcategoryID = s.ProductSubcategoryID
WHERE s.[Name] LIKE @Product AND p.ListPrice < @MaxPrice);
-- Populate the output variable @compareprice.
SET @ComparePrice = @MaxPrice;
GO
Execute usp_GetList
para devolver uma lista de produtos Adventure Works (Bikes
) que custam menos de $700. Os parâmetros OUTPUT @cost
e @compareprices
são usados com linguagem de controle de fluxo de execução para retornar uma mensagem na janela de Mensagens .
Observação
A variável OUTPUT deve ser definida durante a criação do procedimento e também durante o uso da variável. O nome do parâmetro e o nome da variável não precisam corresponder. No entanto, o tipo de dados e o posicionamento dos parâmetros devem corresponder (a menos que @listprice = variable
seja usado).
DECLARE @ComparePrice money, @Cost money ;
EXECUTE Production.uspGetList '%Bikes%', 700,
@ComparePrice OUT,
@Cost OUTPUT
IF @Cost <= @ComparePrice
BEGIN
PRINT 'These products can be purchased for less than
$'+RTRIM(CAST(@ComparePrice AS varchar(20)))+'.'
END
ELSE
PRINT 'The prices for all products in this category exceed
$'+ RTRIM(CAST(@ComparePrice AS varchar(20)))+'.';
Aqui está o conjunto de resultados parciais:
Product List Price
-------------------------------------------------- ------------------
Road-750 Black, 58 539.99
Mountain-500 Silver, 40 564.99
Mountain-500 Silver, 42 564.99
...
Road-750 Black, 48 539.99
Road-750 Black, 52 539.99
(14 row(s) affected)
These items can be purchased for less than $700.00.