0

ユーザー ID (int) によっていくつかのレコードをユーザーと照合しようとしています。ただし、これは動的に行われるため、すべてのレコードを同時に照合できる必要があります (LIKE ワイルドカードに「%」文字を渡します)。以前にこれを行ったことがありますが、偶然この問題に遭遇しました。

Declare 
   @uid varchar = 300

SELECT * FROM items WHERE user_id LIKE @uid

機能しませんが、これは機能します

Declare
   @uid varchar(10) = 300

SELECT * FROM items WHERE user_id LIKE @uid

varchar のサイズが宣言されていない場合、最初のバージョンが機能しないのはなぜですか? エラーが発生しないのはなぜですか?

環境はMSSQL SERVER 2008 R2です

4

1 に答える 1

1

後でコードを保守する必要があるすべての人に代わって、保守しないでください。

varchar が機能しない理由は、それがvarchar(1)1 文字幅に相当するためです。そうは言っても、すべてまたは 1 人のユーザーの取得を許可する場合は、次のことを試してください。

DECLARE @Uid int
-- Get user id 300
SET @Uid = 300
-- Will match on 'User_ID = @Uid'
SELECT * FROM Items WHERE (User_ID = @Uid or @Uid is null) OPTION (RECOMPILE)
-- Get all users
SET @Uid = null
-- Will match on '@Uid is null'
SELECT * FROM Items WHERE (User_ID = @Uid or @Uid is null) OPTION (RECOMPILE)

を使用LIKEすると、サーバーはフィルタリングしているすべての行を文字列に変換し、次に文字列の比較を行う必要がありますが、テーブル スキャンが強制的に実行されます。=withを使用するis nullと、プロセッサーは (うまくいけば)行に関係なく に@Uid is null評価されることを認識します。true


Martin Smith の勧めに従って、私はそれをもう少し詳しく調べることになり、MVP Erland Sommarskog による主題のより完全な議論を見つけました。OPTION (RECOMPILE)最適ではない計画の選択を避けるために、長いものと短いものを必ず含めてください。このアドバイスには注意点があります。注意事項に引っかからないように記事を読むことをお勧めします。

于 2013-02-22T20:11:57.597 に答える