適用於:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
分析平台系統(PDW)
Microsoft Fabric 中的 SQL 資料庫
藉由指定程序參數,呼叫端程式就能夠將值傳入程序的主體。 這些值可用於程式執行期間的各種用途。 如果參數標示為 OUTPUT 參數,程序參數也可以將值傳回呼叫程式。
程式最多可以有 2,100 個參數;每個指派的名稱、數據類型和方向。 您可以選擇性指派預設值給參數。
下節提供有關傳遞值至參數,以及在程序呼叫期間如何使用每個參數屬性的詳細資訊。
Note
關於本文的練習,請參閱 AdventureWorks 系列範例資料庫。 如需詳細資訊,請參閱 AdventureWorks 範例資料庫。
將值傳遞至參數
以程序呼叫提供的參數值必須是常數或變數,函數名稱不可做為參數值。 變數可以是使用者自訂變數或系統變數,如 @@spid。
下列範例示範傳遞參數值至 uspGetWhereUsedProductID程序。 這些範例說明如何以常數和變數方式傳遞參數,以及如何使用變數傳遞函數值。
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
下列範例會傳回錯誤,因為函數無法當做參數值傳遞。
-- Try to use a function as a parameter value.
-- This produces an error message.
EXEC dbo.uspGetWhereUsedProductID 819, GETDATE();
請改用變數將函數值傳遞至參數,如下列範例所示:
-- Passing the function value as a variable.
DECLARE @CheckDate datetime;
SET @CheckDate = GETDATE();
EXEC dbo.uspGetWhereUsedProductID 819, @CheckDate;
GO
指定參數名稱
當建立程序及宣告參數名稱時,參數名稱必須以單個 @ 字元開始,而且在程序範圍中必須是唯一的。
明確為參數命名以及在程序呼叫中指定適當值給每個參數,就能以任何順序提供參數。 例如,如果 my_proc 程序預期有三個參數,名稱分別為 @first、@second 和 @third,您可以將傳遞給程序的值指派給參數名稱,例如:EXECUTE my_proc @second = 2, @first = 1, @third = 3;。
Note
如果以 @parameter = value 形式提供一個參數值,所有後續的參數就必須按照此方式來提供。 如果參數值不是以形式 @parameter = value傳遞,則值必須以相同的順序提供,因為參數列在語句中 CREATE PROCEDURE 。 最好指定參數名稱,以便有較佳的可讀性且與預存程序的未來版本相容。
Warning
任何以 @parameter = value 形式傳遞的參數若有拼字錯誤,就會讓 SQL Server 產生錯誤,並導致程序無法執行。
指定參數數據類型
參數必須在語句中 CREATE PROCEDURE 宣告參數時,以數據類型定義。 參數的資料類型將決定在呼叫程序時參數可接受的值類型和範圍。 例如,若將參數定義為 tinyint 資料類型,在傳遞數值至該參數時,只能接受 0 到 255 範圍內的數值。 執行程序時,如果值與資料類型不相容的話,就會傳回錯誤。
指定參數預設值
如果在宣告時,已指定參數的預設值,此參數視為選擇性參數。 在程序呼叫中,不需要提供值給選擇性參數。
在下列情況下會使用參數的預設值:
- 在程序呼叫中未指定參數值。
- 關鍵詞
DEFAULT會指定為過程調用中的值。
Note
如果預設值是包含內嵌空白或標點的字元字串,或是以數字開頭 (例如 6abc),就必須將它括在單引號中。
Note
Azure Synapse Analytics 或 Analytics Platform System (PDW) 中均不支援預設參數。
如果無法指定適當的值做為參數的預設值,您可以指定 NULL 做為預設值。 在沒有參數值的狀況下執行程序時,最好讓程序傳回自訂的訊息
下列範例使用一個輸入參數 uspGetSalesYTD 來建立 @SalesPerson程序。
NULL 做為預設值指派給參數,並用於錯誤處理陳述式,以便在未指定值給 @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
下列範例執行此程序。 第一個陳述式會在不指定輸入值的情況下執行程序。 這將造成程序中的錯誤處理陳述式傳回自訂錯誤訊息。 第二個陳述式則提供輸入值並傳回預期的結果集。
-- 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
雖然可以省略已提供預設值的參數,但只能截斷不可為 Null 的參數清單。 例如,如果程序有五個參數,且使用 @parameter = value 而未指定參數名稱,則第四個和第五個參數可以省略。 但除非是以 @parameter = value 形式提供參數,否則只要包含第五個參數,就不能省略第四個參數。
使用預設值指定多個參數
如果指定參數名稱,就可以省略參數。 請考慮下列預存程序,其中包含多個具有 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
您可以指定或省略具有預設值的參數,如下列範例所示,只要每個參數都以 @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;
下列範例不是有效的 T-SQL 語法,因為一旦提供某個參數名稱,所有後續參數都必須以相同方式提供。 一律建議為所有值提供參數名稱,以防止錯誤和混淆。
EXEC Production.uspSearchList @ListPrice = 150, 4, 1498;
指定參數方向
參數的方向可以是輸入或輸出,前者指將值傳入程序的主體,後者則指程序傳回值給呼叫端程式。 預設是輸入參數。
若要指定輸出參數, OUTPUT 必須在語句中 CREATE PROCEDURE 參數的定義中指定 關鍵詞。 程序結束時,會將輸出參數目前的值傳回給呼叫端程式。 呼叫端程式在執行程式時也必須使用 OUTPUT 關鍵詞,以將參數的值儲存在可用於呼叫程式的變數中。
下列範例會建立 Production.usp_GetList 程序,以傳回價格不超過指定金額的產品清單。 此範例示範如何使用多個 SELECT 語句和多個 OUTPUT 參數。
OUTPUT 參數允許外部程式、批次或多個 Transact-SQL 語句存取程式執行期間設定的值。
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
執行 usp_GetList 以傳回成本低於 $700 的 Adventure Works 產品 (Bikes) 清單。 與參數會與流程控制語言搭配使用,以在 [OUTPUT] 視窗中傳回訊息。@cost@compareprices
Note
變數 OUTPUT 必須在程式建立期間以及變數的使用期間定義。 參數名稱和變數名稱不一定要相符。 但是,資料類型和參數定位必須相符 (除非使用 @listprice = variable)。
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)))+'.';
部分結果集如下:
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.