2010-04-20 50 views
1

我想用下面的SQL來避免動態SQL構造:使用COALESCE來避免動態SQL?

SELECT CommentID, Comment, 
FROM Comments 
--if Author id is not null then filter upon author id otherwise get all comments (ignore author id) 
WHERE AuthorID LIKE COALESCE(@AuthorId, '%') 
    --if comment type is present filter upon it, otherwise get all comments (ignore comment type condition) 
    AND CommentType LIKE COALESCE(@CommentType, '%') 

我想知道的是解決這個問題,即安全的方式?

編輯: 這裏是滿足我的需要忽略搜索參數,如果是零,如果存在應用它最終代碼:

SELECT CommentID, Comment, 
FROM Comments 
--if @AuthorId is not null then filter upon @AuthorId otherwise get all comments (ignore author id) 
WHERE AuthorID = COALESCE(@AuthorId, AuthorID) 
    --if @CommentType is present filter upon it, otherwise get all comments (ignore comment type condition) 
    AND CommentType = COALESCE(@CommentType, CommentType) 

回答

3

如果AuthorId或CommentType是可以爲空的,這將不起作用。相反,你應該使用OR:

SELECT CommentID, Comment, 
FROM Comments 
WHERE (@AuthorId Is Null Or AuthorId = @AuthorId) 
    And (@CommentType Is Null Or CommentType Like @CommentType) 

順便說一句,如果AUTHORID和CommentType不可爲空,那麼你可以使用COALESCE像這樣:

SELECT CommentID, Comment, 
FROM Comments 
WHERE AuthorId = Coalesce(@AuthorId, AuthorId) 
    And CommentType = Coalesce(@CommentType, CommentType) 

美中不足的是,這是完全匹配的,而不是以像LIKE一樣的通配符匹配。

+0

評論表中沒有字段可爲空,我相信我可以安全地使用提議的代碼? – krul 2010-04-20 17:39:50

+0

@krul - 如果您沒有過濾的字段可以爲空,那麼您可以使用Coalesce,但它會導致完全匹配。如果您需要通配符匹配,那麼您需要使用我提供的第一種方法。 – Thomas 2010-04-20 17:43:40

+0

@krul - 你當然可以混搭。對於完全匹配的列使用Coalesce,對於那些你想要通配符匹配的地方使用'@Foo Is Null或Foo Like @ Foo'構造。 – Thomas 2010-04-20 17:45:26

0

我看不錯,但在這種特殊情況下,你可以ISNULL代替合併。

只是想我會指出,如果AuthorID或CommentType爲null,我不認爲你會返回任何值。

+0

感謝您的快速響應,我會等待看看是否有更多的意見和批准您的答案... – krul 2010-04-20 17:38:09

+1

ISNULL和COALESCE有效地做同樣的事情,除了COALESCE可以處理兩個以上的參數。另外,由於COALESCE是ANSI標準,我會建議不要使用ISNULL。 – Thomas 2010-04-20 17:39:34

+0

在發佈我的編輯之前,我沒有看到Thomas的回答。誠實! – wcm 2010-04-20 17:41:05