パラメータおよびパラメータのデータ型の構成 (ADO.NET)
更新 : November 2007
コマンド オブジェクトは、パラメータを使用して SQL ステートメントまたはストアド プロシージャに値を渡すことによって、型チェックと検証の機能を実現します。コマンド テキストとは異なり、パラメータの入力は実行可能なコードとしてではなく、リテラル値として扱われます。これにより、攻撃者がサーバーのセキュリティを侵害するコマンドを SQL ステートメントに "注入" する SQL インジェクション攻撃を防ぐことができます。
パラメータ化コマンドによりクエリ実行パフォーマンスも向上します。これは、データベース サーバーが入力コマンドを適切なキャッシュ済みクエリ プランに正確に一致させるのに役立つためです。詳細については、SQL Server オンライン ブックの「実行プランのキャッシュと再利用」および「パラメータと実行プランの再利用」を参照してください。セキュリティおよびパフォーマンス上の利点に加え、パラメータ化コマンドを使用すると、データ ソースに渡す値を簡単に扱うことができます。
DbParameter オブジェクトは、コンストラクタを使って作成できるほか、DbParameterCollection コレクションの Add メソッドを呼び出し、DbParameterCollection にオブジェクトを追加することによって作成することもできます。Add メソッドは、コンストラクタ引数または既存のパラメータ オブジェクトを入力として受け取ります。この点はデータ プロバイダによっても異なります。
ParameterDirection プロパティの指定
パラメータを追加する際は、入力パラメータとは別に、パラメータの ParameterDirection プロパティを指定する必要があります。ParameterDirection で使用できる ParameterDirection の値を次の表に示します。
メンバ名 |
説明 |
---|---|
このパラメータは入力パラメータです。これは、既定の設定です。 |
|
このパラメータは入力と出力の両方の機能を持っています。 |
|
このパラメータは出力パラメータです。 |
|
パラメータは、ストアド プロシージャ、組み込み関数、ユーザー定義関数などの操作からの戻り値を表します。 |
パラメータのプレースホルダの使用
パラメータのプレースホルダの構文はデータ ソースに依存します。.NET Framework のデータ プロバイダによって、パラメータおよびパラメータのプレースホルダの名前付けや指定方法が異なります。次の表に示すように、データ ソースごとに固有の構文が採用されています。
データ プロバイダ |
パラメータの名前付け構文 |
---|---|
@parametername 形式の名前付きパラメータが使用されます。 |
|
疑問符 (?) で指定される位置パラメータ マーカーが使用されます。 |
|
疑問符 (?) で指定される位置パラメータ マーカーが使用されます。 |
|
:parmname (または parmname) 形式の名前付きパラメータが使用されます。 |
パラメータのデータ型の指定
パラメータのデータ型は .NET Framework データ プロバイダに固有の属性です。型が指定されている場合は、その値がデータ ソースに渡される前に Parameter の値が .NET Framework データ プロバイダ型に変換されます。Parameter オブジェクトの DbType プロパティを特定の DbType に設定する一般的な方法で Parameter の型を指定することもできます。
Parameter オブジェクトの .NET Framework データ プロバイダ型は、Parameter オブジェクトの Value の .NET Framework 型、または Parameter オブジェクトの DbType から推論されます。Parameter 値として渡されるオブジェクトまたは指定された DbType に基づいて推論される Parameter 型を、次の表に示します。
.NET Framework 型 |
DbType |
SqlDbType |
OleDbType |
OdbcType |
OracleType |
---|---|---|---|---|---|
bool |
Boolean |
Bit |
Boolean |
Bit |
Byte |
byte |
Byte |
TinyInt |
UnsignedTinyInt |
TinyInt |
Byte |
byte[] |
Binary |
VarBinary。バイト配列が VarBinary の最大サイズ (8000 バイト) より大きい場合、この暗黙の変換はエラーになります。8000 バイトを超えるバイト配列の場合は、明示的に SqlDbType を設定してください。 |
VarBinary |
Binary |
Raw |
char |
|
char から SqlDbType への推論はサポートされていません。 |
Char |
Char |
Byte |
DateTime |
DateTime |
DateTime |
DBTimeStamp |
DateTime |
DateTime |
DateTimeOffset |
DateTimeOffset |
SQL Server 2008 の DateTimeOffset。SQL Server 2008 より前のバージョンの SQL Server では、DateTimeOffset から SqlDbType への推論はサポートされていません。 |
DateTime |
||
Decimal |
Decimal |
Decimal |
Decimal |
Numeric |
Number |
double |
Double |
Float |
Double |
Double |
Double |
float |
Single |
Real |
Single |
Real |
Float |
Guid |
Guid |
UniqueIdentifier |
Guid |
UniqueIdentifier |
Raw |
Int16 |
Int16 |
SmallInt |
SmallInt |
SmallInt |
Int16 |
Int32 |
Int32 |
Int |
Int |
Int |
Int32 |
Int64 |
Int64 |
BigInt |
BigInt |
BigInt |
Number |
object |
Object |
Variant |
Variant |
Object から OdbcType への推論はサポートされていません。 |
Blob |
string |
String |
NVarChar。文字列が NVarChar の最大サイズ (4000 文字) より大きい場合、この暗黙の変換はエラーになります。4000 文字を超える文字列の場合は、明示的に SqlDbType を設定してください。 |
VarWChar |
NVarChar |
NVarChar |
TimeSpan |
Time |
SQL Server 2008 の Time。SQL Server 2008 より前のバージョンの SQL Server では、TimeSpan から SqlDbType への推論はサポートされていません。 |
DBTime |
Time |
DateTime |
UInt16 |
UInt16 |
UInt16 から SqlDbType への推論はサポートされていません。 |
UnsignedSmallInt |
Int |
UInt16 |
UInt32 |
UInt32 |
UInt32 から SqlDbType への推論はサポートされていません。 |
UnsignedInt |
BigInt |
UInt32 |
UInt64 |
UInt64 |
UInt64 から SqlDbType への推論はサポートされていません。 |
UnsignedBigInt |
Numeric |
Number |
|
AnsiString |
VarChar |
VarChar |
VarChar |
VarChar |
|
AnsiStringFixedLength |
Char |
Char |
Char |
Char |
|
Currency |
Money |
Currency |
Currency から OdbcType への推論はサポートされていません。 |
Number |
|
Date |
SQL Server 2008 の Date。SQL Server 2008 より前のバージョンの SQL Server では、Date から SqlDbType への推論はサポートされていません。 |
DBDate |
Date |
DateTime |
|
SByte |
SByte から SqlDbType への推論はサポートされていません。 |
TinyInt |
SByte から OdbcType への推論はサポートされていません。 |
SByte |
|
StringFixedLength |
NChar |
WChar |
NChar |
NChar |
|
Time |
SQL Server 2008 の Time。SQL Server 2008 より前のバージョンの SQL Server では、Time から SqlDbType への推論はサポートされていません。 |
DBTime |
Time |
DateTime |
|
VarNumeric |
VarNumeric から SqlDbType への推論はサポートされていません。 |
VarNumeric |
VarNumeric から OdbcType への推論はサポートされていません。 |
Number |
メモ : |
---|
decimal から他の型への変換は縮小変換になるため、decimal 値は最も近い整数値に切り捨てられます。変換結果が対象の型にならなかった場合、OverflowException がスローされます。 |
メモ : |
---|
サーバーに NULL パラメータ値を送信する場合は、null (Visual Basic の場合は Nothing) ではなく、DBNull を指定する必要があります。システムの NULL 値は、値のない空オブジェクトです。DBNull は、NULL 値を表すために使用されます。データベースの NULL 値の詳細については、「NULL 値の処理 (ADO.NET)」を参照してください。 |
パラメータ情報の派生
DbCommandBuilder クラスを使用してストアド プロシージャからパラメータを派生させることができます。SqlCommandBuilder クラスと OleDbCommandBuilder クラスはどちらも静的メソッド DeriveParameters を提供します。このメソッドは、ストアド プロシージャから得られたパラメータ情報を使用して、コマンド オブジェクトのパラメータ コレクションを設定します。DeriveParameters はコマンドの既存のパラメータ情報を上書きします。
メモ : |
---|
パラメータ情報を派生させた場合、情報を取得するためにデータ ソースへのラウンド トリップが 1 つ増えるため、パフォーマンスが低下します。パラメータ情報がデザイン時にわかっている場合は、パラメータを明示的に設定することでアプリケーションのパフォーマンスを改善できます。 |
詳細については、「CommandBuilder でのコマンドの生成 (ADO.NET)」を参照してください。
SqlCommand およびストアド プロシージャでのパラメータの使用
ストアド プロシージャは、データドリブンのアプリケーションに多くの利点を提供します。ストアド プロシージャを使用すると、データベースの操作を単一のコマンドにカプセル化し、最大のパフォーマンスが得られるように最適化し、さらに追加のセキュリティ機能を使用して、セキュリティを強化することができます。ストアド プロシージャは、ストアド プロシージャ名の後にパラメータ引数を記述して SQL ステートメントとして渡すことで呼び出すことができますが、ADO.NET の DbCommand オブジェクトの Parameters コレクションを使用すると、ストアド プロシージャ パラメータをより明示的に定義でき、出力パラメータや戻り値にもアクセスできます。
メモ : |
---|
パラメータ化ステートメントは、sp_executesql を使ってサーバー上で実行されるため、クエリ プランの再利用が可能になります。sp_executesql バッチ内のローカル カーソルまたはローカル変数は、sp_executesql を呼び出すバッチでは認識されません。データベース コンテキストの変更は、sp_executesql ステートメント終了時まで有効です。詳細については、SQL Server オンライン ブックを参照してください。 |
SqlCommand でパラメータを使用して SQL Server のストアド プロシージャを実行する場合は、Parameters コレクションに追加したパラメータの名前が、ストアド プロシージャ内のパラメータ マーカーの名前と一致している必要があります。.NET Framework Data Provider for SQL Server は、SQL ステートメントまたはストアド プロシージャにパラメータを渡す場合の疑問符 (?) プレースホルダをサポートしていません。ストアド プロシージャ内のパラメータは名前付きのパラメータと見なされ、一致するパラメータ マーカーが検索されます。たとえば、CustOrderHist ストアド プロシージャが、@CustomerID という名前のパラメータで定義されているとします。このストアド プロシージャを実行する場合、実行元のコードでも @CustomerID という名前のパラメータを使用する必要があります。
CREATE PROCEDURE dbo.CustOrderHist @CustomerID varchar(5)
例
次の例では、Northwind サンプル データベースにある SQL Server ストアド プロシージャを呼び出す方法を説明します。ストアド プロシージャの名前は dbo.SalesByCategory で、nvarchar(15) データ型の @CategoryName という名前の入力パラメータを持ちます。このコードでは、プロシージャの終了時に接続が破棄されるように、using ブロック内で新しい SqlConnection を作成しています。SqlCommand オブジェクトおよび SqlParameter オブジェクトが作成され、それぞれのプロパティが設定されます。SqlDataReader によって SqlCommand が実行された後、ストアド プロシージャから結果セットが返されて、出力がコンソール ウィンドウに表示されます。
メモ : |
---|
SqlCommand オブジェクトと SqlParameter オブジェクトを作成してから別個のステートメントでプロパティを設定する代わりに、オーバーロード コンストラクタを使用して複数のプロパティを 1 つのステートメントで設定することもできます。 |
Shared Sub GetSalesByCategory(ByVal connectionString As String, _
ByVal categoryName As String)
Using connection As New SqlConnection(connectionString)
' Create the command and set its properties.
Dim command As SqlCommand = New SqlCommand()
command.Connection = connection
command.CommandText = "SalesByCategory"
command.CommandType = CommandType.StoredProcedure
' Add the input parameter and set its properties.
Dim parameter As 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()
Dim reader As SqlDataReader = command.ExecuteReader()
If reader.HasRows Then
Do While reader.Read()
Console.WriteLine("{0}: {1:C}", _
reader(0), reader(1))
Loop
Else
Console.WriteLine("No rows returned.")
End If
End Using
End Sub
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();
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();
}
}
OleDbCommand または OdbcCommand によるパラメータの使用
OleDbCommand または OdbcCommand でパラメータを使用するときは、Parameters コレクションにパラメータが追加されている順序が、ストアド プロシージャ内でパラメータが定義されている順序と一致している必要があります。.NET Framework Data Provider for OLE DB と .NET Framework Data Provider for ODBC は、ストアド プロシージャ内のパラメータをプレースホルダとして処理し、順にパラメータ値を適用します。また、戻り値パラメータは、Parameters コレクションに最初に追加されたパラメータにする必要があります。
.NET Framework Data Provider for OLE DB と .NET Framework Data Provider for ODBC は、SQL ステートメントまたはストアド プロシージャにパラメータを渡す場合の名前付きのパラメータをサポートしていません。この場合は、次の例に示すように疑問符 (?) プレースホルダを使用する必要があります。
SELECT * FROM Customers WHERE CustomerID = ?
したがって、Parameters コレクションに Parameter オブジェクトを追加する順序は、パラメータの疑問符 (?) プレースホルダの位置と完全に対応している必要があります。
OleDb の例
Dim command As OleDbCommand = New OleDbCommand( _
"SampleProc", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OleDbParameter = command.Parameters.Add( _
"RETURN_VALUE", OleDbType.Integer)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OleDbType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OleDbType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OleDbCommand command = new OleDbCommand("SampleProc", connection);
command.CommandType = CommandType.StoredProcedure;
OleDbParameter parameter = command.Parameters.Add(
"RETURN_VALUE", OleDbType.Integer);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add(
"@InputParm", OleDbType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add(
"@OutputParm", OleDbType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;
Odbc の例
Dim command As OdbcCommand = New OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OdbcParameter = command.Parameters.Add("RETURN_VALUE", OdbcType.Int)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OdbcCommand command = new OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection);
command.CommandType = CommandType.StoredProcedure;
OdbcParameter parameter = command.Parameters.Add( _
"RETURN_VALUE", OdbcType.Int);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;