这是我的名为sample的表。
id name grade sign
1 pinky A null
2 smita B sam
我想在检查名称,等级和签名后将新记录添加到样本表中。如果找不到这些组合的记录,则不插入其他内容。
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时出现问题。它将计数为零并且记录被添加。如何处理?我的表可能具有空值或者可能没有空值。取消。
我知道null与null的比较,总是假的。(null= null)
朋友们,感谢您的帮助。我尝试了以下代码。
select @count = count(*) from sample where name = @name and grade= @grade and (sign = @sign OR (Sign IS NULL AND @Sign IS NULL))
但它没有用。它给了我数为零而不是1。
我也尝试过喜欢这个。当我尝试添加第一条小指,A和null时,我工作.Ithas将我显示为1计数。请允许我进一步添加。
select @count = count(*) from sample where name = @name and grade= @grade and (@Sign IS NULL or sign = @sign)
但是当我尝试添加具有值'smita','B',null的新列时失败。它给了我一个作为count.But它是错误的。这些组合不存在。
再次检查你的查询@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
答案 0 :(得分:3)
您可以在null
上使用一些额外的支票:
sign = @sign or (sign is null and @sign is null)
答案 1 :(得分:3)
以这种方式做到。
select @count = count(*)
from sample
where name = @name
and grade= @grade
and isnull(sign,'') = @sign
它会做什么,如果列中有任何值为null,那么它将用''替换它。然后会尝试比较。
答案 2 :(得分: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 :(得分: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)
的独立查询,这会绕过您的插入方法,从而避免重复。
为了避免遇到竞争条件并遇到约束违规错误,我知道的最好方法是将MERGE
与HOLDLOCK
一起使用:
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);