我正在创建一个查询(最终将在存储过程中使用),该查询具有在表单中输入哪些条件的多种变体。有时可以有一个条目,有时没有。有时数据字段具有值,有时为NULL。
我的表单中的字段是NAME,SSN和DRLICENSE。
DECLARE @name VARCHAR(30);
DECLARE @ssn VARCHAR(10);
DECLARE @drlic VARCHAR(10);
--(if for example, someone enters data in two of the fields like this...)
SET @name = 'SMITH'
SET @drlic = 'D'
(In stored procedure)
SET @name = @name + '%'
SET @ssn = @ssn + '%'
SET @drlic = @drlic + '%'
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
NAME LIKE CASE WHEN LEN(@name) > 1 THEN @name ELSE NAME END
AND SSN LIKE CASE WHEN len(@ssn) > 1 THEN @ssn ELSE SSN END
AND DRLICENSE LIKE CASE WHEN LEN(@drlic) > 1 THEN @drlic ELSE DRLICENSE END
我的case语句后面的想法是检查变量的使用情况,并在name
,ssn
或drlicense
是部分条目的情况下执行类似的操作。
我的问题是:如何在表列中说明NULL的情况(即,SSN LIKE SSN
为SSN
时NULL
不起作用,因为SSN IS NULL
需要在那里)。
答案 0 :(得分:2)
这不能很好地执行,特别是因为您使用的是LIKE
,但是括号在这里很重要
where ((@name is null or name like '%' + @name + '%') or ( name is null))
and ((@ssn is null or ssn like '%' + @ssn + '%') or (ssn is null))
and ((@drlic is null or DRLICENSE like '%' + @drlic + '%') or (DRLICENSE is null))
这将返回这些列中的NULL
值,无论是否传入参数。如果您不希望NULL
,则只需从每一行中删除or ( name is null))
部分。我不确定你的帖子。
答案 1 :(得分:1)
if length(@foo) <= 1
set @foo = NULL
if length(@bar) <= 1
set @bar = NULL
...
WHERE (@foo is NULL or t.foo = @foo)
AND (@bar is NULL or t.bar like @bar)
OPTION (RECOMPILE)
答案 2 :(得分:1)
您可以内联将通配符添加到参数值,也可以内联添加空检查。也不需要CASE语句。对于每个参数/列值,如果参数为null或列值为null或列值以传入的参数值开头,则结果返回true
。
在哪里声明:
WHERE (Name IS NULL OR @name IS NULL OR Name LIKE @name + '%')
AND (SSN IS NULL OR @ssn IS NULL OR SSN LIKE @ssn + '%')
AND (DRLICENSE IS NULL OR @drlic IS NULL OR DRLICENSE LIKE @drlic + '%')
这里的关键是,如果要使用的传入值是null
或列值是null
(我假设您不想对其进行过滤,则{{1} }}。
答案 3 :(得分:1)
这应该做到:
WHERE (@name IS NULL OR name LIKE @name + '%')
AND (@ssn IS NULL OR ssn LIKE @ssn + '%')
AND (@drlic IS NULL OR drlicense LIKE @drlic + '%')
请注意,例如,如果用户搜索name = foo,则它将返回与foo%
匹配的行,而不是具有NULL名称的行。
答案 4 :(得分:0)
如果我理解正确,那么您想要一个NULL
-安全的相等性。也就是说,您要NULL
匹配NULL
,并且值要匹配值。所以:
where (name = @name or (name is null and @name is null)) and
(ssn = @ssn or (ssn is null and @ssn is null)) and
(drlicense = @drlicense or (drlicense is null and @drlicense is null))
,或者是一个有趣的变体:
where (select count(*)
from (select distinct *
from (values (name, 'name'), (@name, 'name'), (ssn, 'ssn'), (@ssn, 'ssn'), (drlicense, 'drlicense'), (@drlicense, 'drlicense')
v(val, which)
) x
) = 3
这是使用group by
语义来组合NULL
值。
或者,如果您想进行一些混淆:
where nullif(name, @name) is null and nullif(@name, name) is null and
nullif(ssn, @ssn) is null and nullif(@ssn, ssn) is null and
nullif(drlicense, @drlicense) is null and nullif(@drlicense, drlicense) is null
答案 5 :(得分:0)
您可以使用ISNULL()
,在像您这样的情况下非常有用。
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
ISNULL(NAME,0) LIKE ISNULL(ISNULL(@name, NAME),0)
AND ISNULL(SSN,0) LIKE ISNULL(ISNULL(@ssn, SSN),0)
AND ISNULL(DRLICENSE,0) LIKE ISNULL(ISNULL(@drlic, DRLICENSE),0)
如果列值为NULL,则此方法将用列值替换NULL值,然后将两者都设置为0(将为0 = 0,始终为true)。