2013-04-30 6 views
15

OKは、私は、検索ストアドプロシージャ内のコード行を持っている:動的SQLをエスケープするより洗練された方法ですか?

SET @where = 'job_code = ''' + REPLACE(@job_code, '''', '''''') + '''' 

と私は合理化したい2つの操作が基本的にあります - 単一引用符で連結した値を囲む第1のビーイング。明らかに、上記のステートメントでは、を2つ使用して''をエスケープしてから、'という文字列を終了して、実際の値を連結することができます。より良い方法が必要です!

操作の2番目はREPLACE(@job_code, '''', '''''')で、フィールドにある単一引用符をエスケープします。

このコード行を全体的に書く上で、よりエレガントな方法はありませんか?

は、私はそれがESCAPEキーワードだと思ったんが、それはLIKE声明にしっかりと結ばれていますので、何もそこに行きます。

+0

動的SQLを連結するのではなく、動的SQLに渡すことを考えましたか?ハードコーディングされた値は、パラメータスニッフィングの問題を回避するのに適していますが、ワークロードに応じて、これはもっと簡単なオプションです。 –

+0

@ Love2Learn、それは私が考えているものではありませんが、それについて考えた後、私はストアドプロシージャをそのままの状態に保ち、どの消費者にも使用できるようにしたいと思っています。そのような仮定を加えることは、それを消耗させることをより困難にするでしょう。 –

+3

'' 'に変数を使うと読みやすくなりますが、それほど大きな改善はありません。 –

答えて

26

あなたはsp_executesqlをを使用する場合は、SQLクエリを実行する方法がわかりませんこのようなものになる可能性があります。

EXECUTE sp_executesql 
      N'SELECT * FROM YouTable WHERE job_code = @job_code', 
      N'@job_code varchar(100)', 
      @job_code = @job_code; 
+0

これは興味深いオプションです。興味深いシナリオをいくつか扱います。この方法で 'null'値を扱うようにSQLを書くことができます。if文には分岐が少なくなり、同時に何かをエスケープする必要はありません。興味深い私の友人! –

+2

+1:これは私が描いていた解決策であり、それについての素敵なことは、あなたがエスケープについて心配することなく、とにかく@job_codeを設定できるということです。 –

+4

プランの再利用とプランキャッシュの膨らみが少なくなるという利点が追加されました。 – StrayCatDBA

2

あなたは、定数を宣言することができます:

declare @SQ as char(1) = '''' 

SET @where = 'job_code = ' + @SQ + REPLACE(@job_code, @SQ, @SQ + @SQ) + @SQ 
+0

+1私がまだ考えていなかった解決策。私はそれをやりたいとは思っていません。私が今使っているものよりもいいですね(**個人的に言えば**)。でも+1にもかかわらず! –

+0

うん、もし私がそれをやってもいいのかどうか分かりません。まだ読むのは簡単ではありませんが、それはオプションです。 –

+0

申し訳ありませんが、私は厳しいように見えますが、これは豚の口紅です。 ErikZの答えは、最もクリーンなソリューションであり、MSがダイナミックSQLを生成する方法であり、SQL Server 2000でも同様です。http://msdn.microsoft.com/en-us/library/aa172445%28v=sql.80% 29.aspx – DeanOC

2

あなたはあなたの典型的なシナリオを処理する関数を定義することができ、何かのように:

create function WrapAndReplaceQuotes (@input as varchar(max)) 
returns varchar(max) 
as 
begin 
    return '''' + replace(@input, '''', '''''') + '''' 
end 

SET @where = 'job_code = ' + WrapAndReplaceQuotes(@job_code) 
+0

これは確かに 'SET'文をよりエレガントにするでしょう。これを少し考えてみましょう。 –

5

パラメータ化されたクエリの答えはprobです本当に正しい答えですが、元の質問に答えるには、あなたが望むのはQUOTENAME()です。具体的には、単一引用符のバージョン:

SET @where = 'job_code = ' + QUOTENAME(@job_code, '''') 

は、この上の長さの制限に注意していますデータベース・オブジェクトの名前を引用することを目的とされていないとして、しかし、(入力が128個の文字を意味し、sysnameです)汎用メカニズムです。

関連する問題