3

以下はサンプルクエリです。

CREATE PROCEDURE GetModel
(
    @brandids varchar(100), -- brandid="1,2,3"
    @bodystyleid varchar(100) -- bodystyleid="1,2,3"

)
AS
   select * from model
   where brandid in (@brandids) -- use a UDF to return table for comma delimited string
   and bodystyleid in (@bodystyleid)

私の要件は、@brandidsまたは@bodystyleidが空白の場合、クエリはその条件のすべての行を返す必要があるということです。

これを行う方法を教えてください。また、パフォーマンスを最適化するためにこのクエリを作成する方法を提案します。

4

2 に答える 2

5

IN ('1,2,3')と同じではないため、とにかく動的SQLまたは分割関数が必要になりますIN (1,2,3)

分割機能:

CREATE FUNCTION dbo.SplitInts
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN ( SELECT Item = CONVERT(INT, Item) FROM ( 
     SELECT Item = x.i.value('(./text())[1]', 'int') FROM ( 
       SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') 
       + '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y
     WHERE Item IS NOT NULL
   );

コードは次のようになります。

SELECT m.col1, m.col2 FROM dbo.model AS m
LEFT OUTER JOIN dbo.SplitInts(NULLIF(@brandids, ''), ',') AS br
ON m.brandid = COALESCE(br.Item, m.brandid)
LEFT OUTER JOIN dbo.SplitInts(NULLIF(@bodystyleid, ''), ',') AS bs
ON m.bodystyleid = COALESCE(bs.Item, m.bodystyleid)
WHERE (NULLIF(@brandids, '') IS NULL OR br.Item IS NOT NULL)
AND (NULLIF(@bodystyleid, '') IS NULL OR bs.Item IS NOT NULL);

(ここに多くのNULLIF処理を追加したことに注意してください...これらのパラメーターに値がない場合は、「空白」ではなくNULLを渡す必要があります。)

動的SQLは、パラメーターのスニッフィングが原因で計画が不適切になる可能性がはるかに低くなります。

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'SELECT columns FROM dbo.model
WHERE 1 = 1 '
+ COALESCE(' AND brandid IN (' + @brandids + ')', '')
+ COALESCE(' AND bodystyleid IN (' + @bodystyleid + ')', '');

EXEC sp_executesql @sql;

もちろん、@ JamieCeeが指摘しているように、動的SQLをどこかで検索するとわかるように、動的SQLはインジェクションに対して脆弱である可能性がありますしたがって、入力を信頼できない場合は、潜在的なインジェクション攻撃から保護する必要があります。アプリケーションコード内でアドホックSQLをアセンブルする場合と同じように。

SQL Server 2008以降に移行するときは、テーブル値のパラメーターを確認する必要があります(ここの例)。

于 2012-05-25T17:42:01.347 に答える
0
if(@brandids = '' or @brandids is null)
Begin
     Set @brandids = 'brandid'
End

if(@bodystyleid = '' or @bodystyleid is null)
Begin
     Set @bodystyleid = 'bodystyleid'
End

Exec('select * from model where brandid in (' + @brandids + ')
and bodystyleid in (' + @bodystyleid + ')')
于 2012-05-26T11:30:27.147 に答える