当 NULL 值可能存在时,如何检查 SQL server 2012 中是否存在记录?

How do you check if a record exists in SQL server 2012 when NULL values are possible?

当列值可能是 NULL 时,您将如何处理 SQL Server 2012 中的 SELECT 语句?

如果记录不存在,我试图通过 JDBC 有条件地插入记录,如果记录存在,则 return 与记录关联的 ID。为简单起见,我选择使用 SELECT 查询,然后是 INSERT 查询。

我的 SELECT 查询看起来像这样,除了 (a, b, c, d, e) 对应有意义的名称(发挥你的想象力)。

SELECT id 
FROM dim_repository 
WHERE a = ? 
  AND b = ? 
  AND c = ? 
  AND d = ? 
  AND e = ?

但是,如果 (a)NULL 那么查询将 return 一个空结果集,因为 (a) = NULL 不是一个有效的查询(即因为不同的动词是用于 NULLs 和标量值)。

修复查询的唯一方法是添加如下条件选择吗?

SELECT id 
FROM dim_repository 
WHERE (a = ? OR a IS ?) 
  AND (b = ? OR b IS ?) 
  AND (c = ? OR c IS ?) 
  AND (d = ? OR d IS ?)
  AND (e = ? OR e IS ?)

这种方法是有效的,尽管由于我正在使用的 table 有 16 个不同的列,我对在我的 SELECT 调用中使用 30 个条件语句犹豫不决。

如果您知道有一些不可能的值可以替换为 NULL,例如自动递增列的 0,您可以使用 ISNULL():

WHERE a = ISNULL(@parameter,0) AND ...

但是,通过在 NULL 检查中添加额外的 AND 子句来明确说明您正在做什么是最安全的:

WHERE (a = @parameter OR @parameter IS NULL) AND ...

编辑: 最近 activity 促使我重新阅读我接受的答案,但我不知道自己在写它时在想什么。当然,如果你小心的话它会起作用,但这不是一个好的解决方案。相反,应该使用 intersectexcept 特性,因为它们旨在优雅地处理空值比较:

declare @a int = null;
declare @b int = null;

select Data.*
from (values
    (1, 1)
  , (1, null)
  , (null, 1)
  , (null, null)
) as Data (a, b)
where exists (
          select @a, @b
          intersect
          select Data.a, Data.b 
      );

我还注意到@hvd 实际上在评论中分享了这个解决方案,所以我希望你听从了他的建议而不是我的!

原始(糟糕)答案: 我认为这符合您的要求,但您 必须小心 关于您选择哪个值作为后备。这里零的选择很糟糕,因为 0 可能是 table.

中的有效值
declare @i1 int = null;
declare @i2 int = null;

select Data.*
from (values
    (1, 1)
  , (1, null)
  , (null, 1)
  , (null, null)
) as Data (a, b)
where Coalesce(Data.a, 0) = Coalesce(@i1, 0)
  and Coalesce(Data.b, 0) = Coalesce(@i2, 0);