2009-07-24 6 views
0

単純な問題ですが、少なくとも単純な解決策はありません。少なくとも私は頭の上の1つを考えることはできませんが、ソリューション。 名前が変数で定義されているテーブルを検索する

私は、このストアドプロシージャは、このストアドプロシージャを想定し、テーブル上の選択(基本的な形で)んています

SELECT * FROM myTable 

、大丈夫それが検索する必要のあるテーブル名を除いて、十分に簡単

-- Just to give some context to the variables I'll be using 
DECLARE @metaInfoID AS INT 
SET @metaInfoID = 1 

DECLARE @metaInfoTable AS VARCHAR(200) 

SELECT @metaInfoTable = MetaInfoTableName FROM MetaInfos WHERE MetaInfoID = @MetaInfoID 

DECLARE @sql AS VARCHAR(200) 
SET @sql = 'SELECT * FROM ' + @metaInfoTable 

EXEC @sql 

だから、私は、これは最終的に悪いです認識し、そして私は、SQLインジェクション攻撃を行うことができる場所すぐに見ることができます知られていないので、私たちはこれにかなり似何かになってしまいました。だから、質問は、ダイナミックSQLの構築なしで同じ結果を達成する方法はありますか?または私はスーパーでなければならないでしょうか、クライアントのコードではスーパースーパーですか?

答えて

1

(誰かがMetaInfoTableName列を妨害した場合を想像)。しかし、はい、あなたはSQLステートメントでそれを使用しようとする前に、値を検証する必要があります。

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE [email protected]) 
    BEGIN 
     -- Execute the SELECT * FROM @metaInfoTable dynamic sql 
    END 

これは、その名前のテーブルが存在することを確認します。あなたがINFORMATION_SCHEMAに問い合わせているときにこれを行うことには、明らかにオーバーヘッドがあります。 @metaInfoTableには特定の文字のみが含まれていることを確認することもできます。

-- only run dynamic sql if table name value contains 0-9,a-z,A-Z, underscores or spaces (enclose table name in square brackets, in case it does contain spaces) 
IF NOT @metaInfoTable LIKE '%^[0-9a-zA-Z_ ]%' 
    BEGIN 
     -- Execute the SELECT * FROM @metaInfoTable dynamic sql 
    END 
+0

それはやるのが一番いいようです。どうもありがとう :) – Sekhat

0

説明した制約があると、私はアーキテクチャのパフォーマンスにわずかな違いがある2つの方法を提案します。

クライアント&再建築で選択し

私はあなたからそのデータを取得するテーブルを決定するために、発信者/クライアントを強制的に小さな再建築に可能な限り検討すべきであることをお勧めしたい

。テーブル名を別のテーブルに保持するのはcode smellです。

ここでは、@MetaInfoIDがwebapp、データアクセスブロックなどから渡されていると仮定しています。それで、SELECTを実行するテーブルのロジックを格納する必要があります。私はクライアントがその@MetaInfoIDに基づいて呼び出すストアドプロシージャ(GetCustomersまたはGetProducts)を知っている必要があります。 GetCustomersMetaInfo()GetProductsMetaInfo()GetInvoicesMetaInfo()のようなDALの新しいメソッドを作成して、適切なsprocsを呼び出します(動的SQLは必要なく、DBのメタテーブルのメンテナンスは必要ありません)。

おそらく、システムを少し改造してみてください。 SQL Serverの

あなたは絶対にDBでこの検索をしなければならない、とあなたが持っているテーブルの数に応じて、あなたは(必要なだけ)IF文の一握りを行うことができればlike:

IF @MetaInfoID = 1 
SELECT * FROM Customers 

IF @MetaInfoID =2 
SELECT * FROM Products 
-- etc 

これはおそらく維持する悪夢になるでしょう。

おそらく、各MetaInfoにストアドプロシージャを書くことができます。この方法では、事前コンパイルの利点が得られます。ここではSQLインジェクションは発生しません。あなたは、フロントアップテーブル名がわからない場合は、動的SQLを使用する必要が

IF @MetaInfoID = 1 
EXEC GetAllCustomers 
IF @MetaInfoID = 2 
EXEC GetAllProducts 
+0

残念ながら、これは残念ながら私たちのシステムでは実用的ではありません。ユーザは、クライアントからメタ情報テーブルを効果的に作成します。このテーブルは、システム内の他のアイテムに対してユーザ定義可能な特別な情報を保存するために使用されます。現在のコードベースは、作成したメタ情報テーブルの名前と一致するフードの下にSQLテーブルを作成するため、これらのテーブルを別のテーブルに保存する必要があります。システムは現在かなり大きくなっているので(数年の歳月のため)、そのアーキテクチャーの大きな変化は現在カード上にない..... ..... – Sekhat

+0

... SQLインジェクションの問題は私が遭遇したことだこれらのメタタグを横切って検索機能をWebサービスを通じて公開したいと思っています。残念ながら、この変数は空の文字列クライアント側として "MetaTableName"変数を公開しています。今はSQLインジェクションは、上記のコードではまったく起こらないかもしれません。なぜなら、メタテーブル名がmetaInfoTablesテーブルに存在しないと失敗するはずですが、私は実際にそれを偶然に残すつもりはありません。 – Sekhat

関連する問題