2014-10-10 75 views
1

以下是我称为sample的表。如何在where子句中添加空值(比较)

id name grade sign 
1 pinky A  null 
2 smita B  sam 

我想新的记录添加到样品表核对姓名,年级和sign.If记录未找到这些组合后,插入别的没有。

declare @count int 
select @count = count(*) from sample where name = @name and grade= @grade and sign = @sign 
-- @name,@grade and @sign are input para 
if(@count = 0) 
begin 
-- insert 
end 

,当我试图添加一个小指第一个记录,“A”和问题发生null.It给予数为零,并记录得到added.How来处理呢?我的表可能有空值或可能不会有空值。取决于。 我知道null与null的比较,总是false。 (null= null)

你好朋友,谢谢你的帮助。我试了下面的代码。

select @count = count(*) from sample where name = @name and grade= @grade and (sign = @sign OR (Sign IS NULL AND @Sign IS NULL)) 

不过,这并不worked.It给我算的零,而不是1

我试着喜欢这个also.I工作时,我试图添加第一个记录是小指,A和null.Ithas显示我1作为count.Prompt我进一步添加。

select @count = count(*) from sample where name = @name and grade= @grade and (@Sign IS NULL or sign = @sign) 

,但是当我试图添加具有值为“史密塔”,“B”新列失败,null.It给了我一个为count.But是wrong.Record不会为这些组合

存在

经过乌尔查询再次@Mukund

select @count = count(*) from sample where name = @name and grade= @grade and (sign = @sign OR (Sign IS NULL AND @Sign IS NULL)). 
It gave me count as zero instead of 1 when I am trying to add 'pinky',A and null 
+2

'WHERE(签名= @sign OR(注册IS NULL和@ Sign IS NULL))' – GarethD 2014-10-10 10:21:03

+1

你能检查我的解决方案吗? @Swati – Mukund 2014-10-10 10:43:56

+1

我已经添加了一个小提琴到我的答案,看看它是否可以帮助你。 – Banana 2014-10-10 11:07:34

回答

1

使用:

if not exists(
select * from sample where name = @name and grade= @grade and (sign = @sign or (sign is null and @sign is null)) 
) 
    begin 
     insert into sample(name,grade,sign) values (@name,@grade,@sign) 
    end; 

的例子看看SQL Fiddle

6个查询插入,用您的记录2,显示在每种情况下会发生什么。

3

你可以在null使用一些额外的检查:

sign = @sign or (sign is null and @sign is null) 
3

这样做。

select @count = count(*) 
from sample 
where name = @name 
and grade= @grade 
and isnull(sign,'') = @sign 

它会做什么,如果在列中将有任何值为null,那么它将用''代替它,然后将尝试进行比较。如果存在

+0

认为这应该是'isnull(sign,'')= isnull(@sign,'')' – GarethD 2014-10-10 10:22:40

+0

是否有可能使@sign为空。如果是的话,她可以做到。在这两种情况下结果都是一样的。 – Mukund 2014-10-10 10:24:12

+1

根据问题,“@ sign”可能为空 - 结果将不相同。如果'sign'为空并且'@ sign'为空,那么最终会得到'''= null',它是空的,即不是真的。而如果你使用'ISNULL(sign,'')= ISNULL(@sign,'')'并且'sign'和'@ sign'都为null,那么你最终会得到'''='''这是真的。 – GarethD 2014-10-10 11:02:49

0

您的查询易受race condition影响。在多线程环境中,在检索匹配记录的计数和插入另一个线程插入相同记录的新记录之间会发生变化(但不太可能)。

防止这种情况的第一步是添加一个唯一的约束。如果(name, grade, sign)应该是唯一的,那么就应该被限制,因为这样的:

ALTER TABLE sample 
ADD CONSTRAINT UQ_sample__Name_Grade_Sign UNIQUE (Name, Grade, Sign); 

你应该这样做,无论你选择插入记录的方法。这将您的逻辑与数据库集成在一起,并保护它免受任何来自应用程序层的插入错误,例如某人可以运行一个独立的INSERT Sample (Name, Grade, Sign) VALUES ('pinky', 'A', null)查询,这样可以避免重复出现的插入方法。

为了避免陷入竞争条件和获取违反约束的错误,我知道最好的办法是使用MERGEHOLDLOCK

MERGE sample WITH (HOLDLOCK) AS t 
USING (VALUES (@Name, @Grade, @Sign)) AS s (Name, Grade, Sign) 
    ON s.name = t.Name 
    AND s.Grade = t.Grade 
    AND ISNULL(s.Sign, '') = ISNULL(t.Sign, '') 
WHEN NOT MATCHED THEN 
    INSERT (Name, Grade, Sign) 
    VALUES (s.Name, s.Grade, s.Sign);