web-dev-qa-db-ja.com

パラメータ化されたOLEDBソースクエリ

SSISでETLを作成しています。このデータソースで、select * from table_name where id='Variable'。この変数は、ユーザー作成変数として定義したものです。

ソースクエリをSSISスコープ変数と対話させる方法を理解していません。

存在するオプションは

  • テーブル
  • 変数からのテーブル
  • SQLコマンド
  • 変数からのSQLコマンド

私が欲しいのは、パラメータとして変数を持つSQLステートメントを持つことです

13
user1765876

シンプル。データアクセスモードとしてSQL commandを選択します。パラメータープレースホルダーとして疑問符を使用してクエリを入力します。次にParametersボタンをクリックし、Parameter0ダイアログで変数をSet Query Parametersにマップします。

enter image description here

詳細は [〜#〜] msdn [〜#〜] で入手できます。

25
Edmund Schweppe

@Edmundのアプローチに劣る代替方法は、別の変数で式を使用して文字列を作成することです。 @ [User :: FirstName]が既に定義されていると仮定して、別の変数@ [User :: SourceQuery]を作成します。

この変数のプロパティで、EvaluateAsExpressionをTrueに設定してから、"SELECT FirstName, LastName, FROM Person.Person WHERE FirstName = '" + @[User::FirstName] +"'"のような式を設定します。SSIS文字列を作成しているため、二重引用符が必要です。

このアプローチを検討すべきではない2つの大きな理由があります。

キャッシング

このアプローチでは、基本的に同じクエリのN個のコピーを使用して、SQL Serverのプランキャッシュが膨張します。最初に実行され、値が「Edmund」の場合、SQL Serverは実行プランを作成して保存します(ビルドに費用がかかる可能性があるため)。次に、パッケージを実行すると、値は「Bill」です。 SQL Serverは、この計画があるかどうかを確認します。そうではなく、エドモンド用に1つしかないので、計画の別のコピーを作成します。今回はBillにハードコーディングされています。リンスを繰り返し、使用可能なメモリがいくつかの計画をアンロードするまで減少するのを見てください。

パラメーターアプローチを使用すると、計画がSQL Serverに送信されるときに、計画のパラメーター化バージョンを内部で作成する必要があり、指定されたすべてのパラメーターが等しいコストの実行になると想定します。一般的に言えば、これは望ましい動作です。

データベースがアドホックワークロード向けに最適化されている場合(既定ではオフになっている設定です)、すべての計画がパラメーター化されるため、これを緩和する必要があります。

SQLインジェクション

独自の文字列を作成する際に遭遇する他の厄介なことは、SQLインジェクション攻撃にさらされることです。少なくとも、実行時エラーが発生する可能性があります。 「ダルタニャン」という値を持つのと同じくらい簡単です。その一重引用符により、クエリが失敗し、パッケージが失敗します。値を「 '; DROP TABLE Person.Person;-」に変更すると、大きな痛みが生じます。

すべてを安全に引用するのは簡単だと思うかもしれませんが、クエリを実行するすべての場所で一貫して実装する努力は、雇用主が支払っている金額を超えています。さらに、同じことを行うためのネイティブ機能が提供されています。

10
billinkc

OLEDB接続マネージャー(私の場合はSQL Server Native Client 11.0プロバイダー)を使用すると、次のようなエラーをキャッチできます。

SQLコマンドからパラメーターを抽出できません。プロバイダーは、コマンドからのパラメーター情報の解析に役立たない場合があります。その場合、「変数からのSQLコマンド」アクセスモードを使用します。このモードでは、SQLコマンド全体が変数に格納されます。

そのため、OLEDB接続マネージャーのプロパティでデータベース名を明示的に指定する必要があります。それ以外の場合、SQL Server Native Clientは別のデータベース名を使用できます(例:MSSQL Serverのマスター)。場合によっては、クエリで使用される各データベースオブジェクトのデータベース名を明示的に指定できます。例:

select Name
from MyDatabase.MySchema.MyTable
where id = ?
1
iliyesku