パラメーターの構成
適用対象: .NET Framework
.NET
.NET Standard
コマンド オブジェクトは、パラメーターを使用して SQL ステートメントまたはストアド プロシージャに値を渡すことによって、型チェックと検証の機能を実現します。 コマンド テキストとは異なり、パラメーターの入力は実行可能なコードとしてではなく、リテラル値として扱われます。 この動作により、攻撃者がサーバーのセキュリティを侵害するコマンドを SQL ステートメントに挿入する "SQL インジェクション" 攻撃を防ぐことができます。
パラメーター化コマンドによりクエリ実行パフォーマンスも向上します。これは、データベース サーバーが入力コマンドを適切なキャッシュ済みクエリ プランに正確に一致させるのに役立つためです。 詳細については、「実行プランのキャッシュと再利用」および「パラメーターと実行プランの再利用」を参照してください。 セキュリティおよびパフォーマンス上の利点に加え、パラメーター化コマンドを使用すると、データ ソースに渡す値を簡単に扱うことができます。
DbParameter オブジェクトは、コンストラクターを使って作成できるほか、 DbParameterCollection コレクションの Add
メソッドを呼び出し、 DbParameterCollection にオブジェクトを追加することによって作成することもできます。 Add
メソッドは、コンストラクター引数または既存のパラメーター オブジェクトを入力として受け取ります。この点はデータ プロバイダーによっても異なります。
ParameterDirection プロパティを指定する
パラメーターを追加する際は、入力パラメーターとは別に、パラメーターの ParameterDirection プロパティを指定する必要があります。 ParameterDirection
で使用できる ParameterDirection の値を次の表に示します。
メンバー名 | 説明 |
---|---|
Input | このパラメーターは入力パラメーターです。 この値は既定値です。 |
InputOutput | このパラメーターは入力と出力の両方の機能を持っています。 |
Output | このパラメーターは出力パラメーターです。 |
ReturnValue | パラメーターは、ストアド プロシージャ、組み込み関数、ユーザー定義関数などの操作からの戻り値を表します。 |
パラメーターのプレースホルダーを操作する
パラメーターのプレースホルダーの構文はデータ ソースに依存します。 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 型は、Parameter
オブジェクトの Value
の .NET Framework 型から、または Parameter
オブジェクトの DbType
から推論されます。 Parameter
値として渡されるオブジェクトまたは指定された Parameter
に基づいて推論される DbType
型を、次の表に示します。
.NET の種類 | DbType | SqlDbType |
---|---|---|
Boolean | Boolean |
Bit |
Byte | Byte |
TinyInt |
byte[] |
Binary |
VarBinary . バイト配列が VarBinary の最大サイズ (8,000 バイト) より大きい場合、この暗黙的な変換は失敗します。 8000 バイトを超えるバイト配列の場合は、明示的に SqlDbType を設定してください。 |
Char | char から SqlDbType への推論はサポートされていません。 | |
DateTime | DateTime |
DateTime |
DateTimeOffset | DateTimeOffset |
DateTimeOffset (SQL Server 2008)。 DateTimeOffset から SqlDbType への推論は、SQL Server 2008 より前のバージョンの SQL Server ではサポートされていません。 |
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 の最大サイズ (4,000 文字) より大きい場合、この暗黙的な変換は失敗します。 4000 文字を超える文字列の場合は、明示的に SqlDbTypeを設定してください。 |
TimeSpan | Time |
Time (SQL Server 2008)。 TimeSpan から SqlDbType への推論は、SQL Server 2008 より前のバージョンの SQL Server ではサポートされていません。 |
UInt16 | UInt16 |
UInt16 から SqlDbType への推論はサポートされていません。 |
UInt32 | UInt32 |
UInt32 から SqlDbType への推論はサポートされていません。 |
UInt64 | UInt64 |
UInt64 から SqlDbType への推論はサポートされていません。 |
AnsiString |
VarChar |
|
AnsiStringFixedLength |
Char |
|
Currency |
Money |
|
Date |
Date (SQL Server 2008)。 Date から SqlDbType への推論は、SQL Server 2008 より前のバージョンの SQL Server ではサポートされていません。 |
|
SByte |
SByte から SqlDbType への推論はサポートされていません。 |
|
StringFixedLength |
NChar |
|
Time |
Time (SQL Server 2008)。 Time から SqlDbType への推論は、SQL Server 2008 より前のバージョンの SQL Server ではサポートされていません。 |
|
VarNumeric |
VarNumeric から SqlDbType への推論はサポートされていません。 |
|
ユーザー定義型 ( SqlUserDefinedAggregateAttributeを持つオブジェクト) | SqlClient は常に Object を返します | SqlUserDefinedTypeAttribute が存在する場合は SqlDbType.Udt 。それ以外の場合は Variant |
Note
decimal から他の型への変換は縮小変換になるため、decimal 値は最も近い整数値に切り捨てられます。 変換の結果が変換先の型で表現できない場合は、OverflowException がスローされます。
Note
サーバーに NULL パラメーター値を送信する場合は、null
(Visual Basic の場合は Nothing
) ではなく、DBNull を指定する必要があります。 システムの null 値は、値のない空オブジェクトです。 DBNull は、null 値を表すために使用します。
パラメーター情報を派生させる
DbCommandBuilder
クラスを使用してストアド プロシージャからパラメーターを派生させることができます。 SqlCommandBuilder
クラスには静的メソッド DeriveParameters
が用意されています。これにより、ストアド プロシージャからのパラメーター情報を使用するコマンド オブジェクトのパラメーターのコレクションが自動的に設定されます。 DeriveParameters
により、コマンドの既存のパラメーター情報が上書きされます。
Note
パラメーター情報を派生させた場合、情報を取得するためにデータ ソースへのラウンド トリップが 1 つ増えるため、パフォーマンスが低下します。 パラメーター情報がデザイン時にわかっている場合は、パラメーターを明示的に設定することでアプリケーションのパフォーマンスを改善できます。
詳細については、「CommandBuilder でのコマンドの生成」を参照してください。
SqlCommand およびストアド プロシージャでのパラメーターの使用
ストアド プロシージャは、データドリブンのアプリケーションに多くの利点を提供します。 ストアド プロシージャを使用すると、データベース操作を 1 つのコマンドでカプセル化し、最良のパフォーマンスのために最適化し、セキュリティを強化して拡張することができます。 ストアド プロシージャは、ストアド プロシージャ名の後にパラメーター引数を記述して SQL ステートメントとして渡すことで呼び出すことができますが、ADO.NET の DbCommand オブジェクトの Parameters コレクションを使用すると、ストアド プロシージャ パラメーターをより明示的に定義でき、出力パラメーターや戻り値にもアクセスできます。
Note
パラメーター化ステートメントは、 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 を作成しています。 SqlCommand オブジェクトおよび SqlParameter オブジェクトが作成され、それぞれのプロパティが設定されます。 SqlDataReader によって SqlCommand
が実行された後、ストアド プロシージャから結果セットが返されて、出力がコンソール ウィンドウに表示されます。
Note
SqlCommand
オブジェクトと SqlParameter
オブジェクトを作成してから別個のステートメントでプロパティを設定する代わりに、オーバーロード コンストラクターを使用して複数のプロパティを 1 つのステートメントで設定することもできます。
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();
}
}
}