我有一个包含多个列的表。我想要一个存储过程,如果这些值的参数不为null,将为每个值过滤Select *语句。我是否必须写一个像sql server字符串或其他什么,如果该参数不为null,只需将参数值附加到字符串?或者是否有一种更简单的内置机制用于此类事情?我知道你必须为Oracle做字符串事情。但ms sql server总是让我感到更加用户友好。在我进入鸽子之前,我想我会先检查一下。
由于
答案 0 :(得分:5)
简单路由,假设col
不可为空,或者它是,并且您不希望NULL行匹配:
WHERE col LIKE COALESCE(@param, col)
-- or the longer version:
WHERE (col LIKE @param OR @param IS NULL)
(其中@param
为NULL
或类似'%asdf%'
。
如果col
可以为空并且你做想要NULL行匹配,你可以试试这个:
WHERE COALESCE(col, 'x') LIKE COALESCE(@param, col, 'x')
还有其他方法可以做到这一点,因为这可能会导致基于参数化设置的错误计划以及第一次缓存时使用的参数(由于“参数嗅探”,这会导致计划选择不当) ,但这可能在很大程度上与此无关,因为你的WHERE
子句无论如何都会强制进行表扫描。
当计划质量成为问题时,常见的替代方法是使用动态SQL,例如
DECLARE @sql NVARCHAR(MAX) = N'SELECT ... FROM ... WHERE 1 = 1';
IF @param IS NOT NULL
BEGIN
SET @sql += ' AND col LIKE ''' + REPLACE(@param, '''', '''''') + '%''';
END
在这种情况下,确保启用optimize for ad hoc workloads
设置会很有帮助。
有关参数嗅探和动态SQL的信息,请参阅Erland Sommarskog的这些帖子:
http://www.sommarskog.se/query-plan-mysteries.html
http://www.sommarskog.se/dynamic_sql.html