2009-07-09 1 views
2

テーブルを削除するための単純なストアドプロシージャの後です。ここに私の最初の試みです:テーブルを削除するT-SQLストアドプロシージャをどのようにparamateriseしますか?

CREATE PROC bsp_susf_DeleteTable (@TableName char) 
AS 
IF EXISTS (SELECT name FROM sysobjects WHERE name = @TableName) 
BEGIN 
DROP TABLE @TableName 
END 

私はMSクエリアナライザでこれを解析するとき、私は次のエラーを取得する:

単一のテーブルの通常のSQLは次のようになりますので、一種の理にかなって
Server: Msg 170, Level 15, State 1, Procedure bsp_susf_DeleteTable, Line 6 
Line 6: Incorrect syntax near '@TableName'. 

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'tbl_XYZ') 
BEGIN 
    DROP TABLE tbl_XYZ 
END 

(WHERE句内の)tbl_XYZの最初のインスタンスは、その周りに一重引用符があることに注意してください.DROP文の2番目のインスタンスは、そうではありません。変数(@TableName)を使用すると、この区別はできません。

これを行うためにストアドプロシージャを作成できますか?またはIF EXISTSをどこにでもコピーする必要がありますか?

答えて

3

:たとえば、C#で、私のような何かをするだろう。

更新:はい、@sqlを小さくすることができますが、これは簡単な例です。また、SQLインジェクション攻撃に関するその他のコメントにも注意してください。

+0

ありがとうウェイン - 正常に働いた。 – dave

+0

テーブル名はnvarcharなので@SQL nvarchar(max)を作成します。 (実際にはsysnameですが、nvarcharに相当します(数字は128かもしれません) –

+3

大括弧のために@TableNameをエスケープする必要がありますSQL Serverにはこれを行うコマンドがあります@sql = 'drop table' + QuoteName TableName); –

0

EXECを使用して、そのクエリを文字列として実行する必要があります。つまり、テーブル名を渡すときにvarcharを定義し、クエリとtablenameを割り当てて、作成した変数をexecします。

編集:誰かがTableNameではなくSQLを渡すことができ、あらゆる種類のすばらしい問題を引き起こす可能性があるため、私はこれをお勧めしません。詳細については、「SQLインジェクション」を参照してください。

クライアントサイドでパラメータ化されたクエリを作成することをお勧めします。このことができます

declare @sql varchar(max) 
if exists (select name from sysobjects where name = @TableName) 
BEGIN 
    set @sql = 'drop table ' + @TableName 
    exec(@sql) 
END 

希望:あなたは動的SQLを使用することができるはず

// EDIT 2: on second thought, ignore this code; it probably won't work 
SqlCommand sc = new SqlCommand(); 
sc.Connection = someConnection; 
sc.CommandType = Command.Text; 
sc.CommandText = "drop table @tablename"; 
sc.Parameters.AddWithValue("@tablename", "the_table_name"); 
sc.ExecuteNonQuery(); 
+0

マイケルに感謝します。 – dave

+1

正直なところ、格納されたprocの意図的な目的が渡されたarbiraryテーブルを削除する場合、SQL Injecion攻撃はどれくらい悪化する可能性がありますか?なぜなら、あなたがハックを必要とせずにデータベース内のテーブルを削除してしまうと、どうしてsringをエスケープするのでしょうか? – JohnFx

+0

うーん...良い点。しかし、それはしていませんでした。 –

2

私は個人的にこれを行うことに非常に注意します。行政上必要と思われる場合は、これを実行する権利が極めて限られていることを確認してください。さらに、私はprocにテーブル名と日付をコピーさせ、ユーザはそれをロギングテーブルに実行させます。そうすれば、間違ったテーブルを誰が落としたかが分かります。あなたは他の保護も望むかもしれません。たとえば、このprocを使用して削除できない特定のテーブルを指定することができます。

これはすべてのケースですべてのテーブルで機能しません。外部キーが関連付けられたテーブルを削除することはできません。

ユーザまたはデータベース管理者以外の誰もがこのprocを実行することを許可しません。ユーザーがテーブルを削除できるシステム設計をしている場合は、デザインに大きな欠陥がある可能性が非常に高く、再考する必要があります。

また、本当に良いバックアップスケジュールが用意されていて、バックアップから復旧した経験がない限り、このprocを使用しないでください。

+0

これらはすべて非常に優れた点ですが、私の状況はこれらが問題ではないようなもので、私たちは報告データベースを形成するために一晩コピーされた実動データベースを持っています。これらの派生テーブルのみを削除しますが、誤ってゴミ箱を廃棄すると問題はありません。 – dave

関連する問題