設定參數

適用於:.NET Framework .NET .NET Standard

下載 ADO.NET

命令物件會使用參數將值傳遞至 SQL 陳述式或預存程序 (Stored Procedure),以提供型別檢查及驗證。 與命令文字不同的是,參數輸入會被視為常值 (Literal),而非可執行程式碼。 此行為有助於防範「SQL 插入式」攻擊,在此類攻擊中,攻擊者會將危害伺服器安全的命令插入 SQL 陳述式中。

參數型命令 (Parameterized Command) 也可以改善查詢執行效能,因為它們可以協助資料庫伺服器正確地比對內送命令與正確快取的查詢計畫。 如需詳細資訊,請參閱執行計畫快取與重複使用參數和執行計畫的重複使用。 除了安全性和效能的優點以外,參數型命令也提供方便的方法,可讓您安排傳遞至資料來源的值。

DbParameter 物件可透過其建構函式建立,或者透過呼叫 DbParameterCollection 集合的 Add 方法,將其加入 DbParameterCollection 來建立。 Add 方法會將建構函式引數或現有的參數物件當做輸出,依資料提供者而定。

提供 ParameterDirection 屬性

在加入參數時,您必須為不是輸入參數的參數提供 ParameterDirection 屬性。 下表所顯示的 ParameterDirection 值是可以與 ParameterDirection 列舉一起使用的。

成員名稱 說明
Input 這是輸入參數, 這是預設值。
InputOutput 這個參數可執行輸入和輸出。
Output 這是輸出參數。
ReturnValue 此參數代表預存程序 (Stored Procedure)、內建函式或使用者定義函式等作業的傳回值。

使用參數預留位置

參數預留位置的語法會隨資料來源而有所不同。 Microsoft SqlClient Data Provider for SQL Server 會以不同的方式來處理命名及指定參數與參數預留位置。 SqlClient 資料提供者會使用 @parametername 格式的具名參數。

指定參數資料類型

參數的資料類型是特定於 Microsoft SqlClient Data Provider for SQL Server。 指定類型會先將 Parameter 的值轉換成 Microsoft SqlClient Data Provider for SQL Server 類型,然後再將該值傳遞到資料來源。 您也可以使用一般方式指定 Parameter 的型別,方法是將 DbType 物件的 Parameter 屬性設為特定的 DbType

Parameter 物件的 Microsoft SqlClient Data Provider for SQL Server 類型是從 Value 物件之 Parameter 的 .NET Framework 類型,或是從 Parameter 物件的 DbType 推斷而來。 下列表格說明根據以 Parameter 值或指定之 Parameter 來傳遞的物件而推斷出的 DbType型別。

.NET 類型 DbType SqlDbType
Boolean Boolean Bit
Byte Byte TinyInt
byte[] Binary VarBinary. 如果位元組陣列超過 VarBinary 的大小上限 (8000 個位元組),則這個隱含轉換將會失敗。 若要使用超過 8000 個位元組的位元組陣列,請明確設定 SqlDbType
Char 不支援從 char 推斷 SqlDbType
DateTime DateTime DateTime
DateTimeOffset DateTimeOffset SQL Server 2008 中:DateTimeOffset。 SQL Server 2008 之前的 SQL Server 版本不支援從 DateTimeOffset 推斷 SqlDbType
Decimal Decimal Decimal
Double Double Float
Single Single Real
Guid Guid UniqueIdentifier
Int16 Int16 SmallInt
Int32 Int32 Int
Int64 Int64 BigInt
Object Object Variant
String String NVarChar. 如果字串超過 NVarChar 的最大大小 (4000 個字元),則這項隱含轉換將會失敗。 若要使用超過 4000 個字元的字串,請明確設定 SqlDbType
TimeSpan Time SQL Server 2008 中:Time。 SQL Server 2008 之前的 SQL Server 版本不支援從 TimeSpan 推斷 SqlDbType
UInt16 UInt16 不支援從 UInt16 推斷 SqlDbType
UInt32 UInt32 不支援從 UInt32 推斷 SqlDbType
UInt64 UInt64 不支援從 UInt64 推斷 SqlDbType
AnsiString VarChar
AnsiStringFixedLength Char
Currency Money
Date SQL Server 2008 中:Date。 SQL Server 2008 之前的 SQL Server 版本不支援從 Date 推斷 SqlDbType
SByte 不支援從 SByte 推斷 SqlDbType
StringFixedLength NChar
Time SQL Server 2008 中:Time。 SQL Server 2008 之前的 SQL Server 版本不支援從 Time 推斷 SqlDbType
VarNumeric 不支援從 VarNumeric 推斷 SqlDbType
使用者定義型別 (包含 SqlUserDefinedAggregateAttribute的物件) SqlClient 一律會傳回物件 如果 SqlUserDefinedTypeAttribute 存在,則為 SqlDbType.Udt,否則為 Variant

注意

將十進位值轉換為其他型別的過程稱為窄化轉換,此類轉換會將十進位值向零的方向取整數。 如果目的地類型無法代表轉換的結果,則會擲回 OverflowException

注意

當您將 Null 參數值傳送到伺服器時,必須指定 DBNull,而不是 null (在 Visual Basic 中為 Nothing)。 系統中的 Null 值是沒有值的空物件。 DBNull 用於表示 null 值。

衍生參數資訊

您也可以使用 DbCommandBuilder 類別 (Class) 從預存程序衍生參數。 SqlCommandBuilder 類別會提供靜態方法 DeriveParameters,其會自動填入使用來自預存程序參數資訊之 Command 物件的參數集合。 DeriveParameters 會覆寫命令的任何現有參數資訊。

注意

衍生參數資訊會造成效能降低,因為這項作業需要對資料來源進行額外的來回行程才能擷取資訊。 若在設計階段已知參數資訊,您便可以明確設定參數,改善應用程式的效能。

如需詳細資訊,請參閱使用 CommandBuilder 產生命令

搭配 SqlCommand 與預存程序使用參數

預存程序對資料驅動應用程式有許多好處。 藉由使用預存程序,資料庫作業可以封裝在單一命令中、最佳化為最佳效能,並且可進一步提升安全性。 雖然只要將後接參數引數的預存程序名稱當成 SQL 陳述式傳遞即可呼叫預存程序,透過使用 ADO.NET DbCommand 物件的 Parameters 集合,可以讓您更明確地定義預存程序參數,以及存取輸出參數與傳回值。

注意

參數化陳述式能在伺服器上執行,都是透過允許查詢計畫重複使用的 sp_executesql, 。 呼叫 sp_executesql 的批次無法見到 sp_executesql批次中的本機資料指標或變數。 資料庫內容中的變更只會持續到 sp_executesql 陳述式結束。 如需詳細資訊,請參閱 sp_executesql (Transact-SQL)

將參數與 SqlCommand 搭配使用以執行 SQL Server 預存程序時,加入 Parameters 集合的參數名稱必須與預存程序中的參數標記名稱相符。 Microsoft SqlClient Data Provider for SQL Server 針對將參數傳遞至 SQL 陳述式或預存程序,並不支援問號 (?) 預留位置。 它會將預存程式中的參數視為具名參數,並搜尋相符的參數標記。 例如, CustOrderHist 預存程序是使用名為 @CustomerID的參數所定義的。 則當您的程式碼執行預存程序時,也必須使用名為 @CustomerID的參數。

CREATE PROCEDURE dbo.CustOrderHist @CustomerID varchar(5)

範例

此範例會示範如何在 Northwind 範例資料庫中呼叫 SQL Server 預存程序。 預存程序的名稱為 dbo.SalesByCategory ,而且具有名為 @CategoryName 的輸入參數 (資料型別為 nvarchar(15))。 此程式碼會在 Using 區塊中建立新的 SqlConnection ,這樣當程序結束時就會清除連接。 SqlCommandSqlParameter 物件會建立,其屬性也會設定。 SqlDataReader 會執行 SqlCommand 並從預存程序傳回結果集,在主控台視窗中顯示輸出。

注意

與其建立 SqlCommandSqlParameter 物件,然後再以個別的陳述式設定屬性,您可以選擇使用其中一個多載建構函式 (Constructor),以單一的陳述式設定多個屬性。

static void GetSalesByCategory(string connectionString,
    string categoryName)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        // Create the command and set its properties.
        SqlCommand command = new SqlCommand();
        command.Connection = connection;
        command.CommandText = "SalesByCategory";
        command.CommandType = CommandType.StoredProcedure;

        // Add the input parameter and set its properties.
        SqlParameter parameter = new SqlParameter();
        parameter.ParameterName = "@CategoryName";
        parameter.SqlDbType = SqlDbType.NVarChar;
        parameter.Direction = ParameterDirection.Input;
        parameter.Value = categoryName;

        // Add the parameter to the Parameters collection.
        command.Parameters.Add(parameter);

        // Open the connection and execute the reader.
        connection.Open();
        using (SqlDataReader reader = command.ExecuteReader())
        {
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    Console.WriteLine("{0}: {1:C}", reader[0], reader[1]);
                }
            }
            else
            {
                Console.WriteLine("No rows found.");
            }
            reader.Close();
        }
    }
}

請參閱