T-SQL IF条件未按预期工作

时间:2010-10-01 21:58:57

标签: sql sql-server tsql sql-server-2008 if-statement

我有一个将记录插入表中的存储过程。我在表上创建了一个唯一的键约束,以避免重复记录。

无论是否定义了唯一键约束,我使用IF()条件(在INSERT语句之前)来检查可能已存在的重复记录。

但是,我用来检查重复记录的条件语句似乎对INSERT是否执行没有影响。 - 即当提交给sproc的重复记录时,抛出“违反UNIQUE KEY约束......”异常。

以下是我的样本:

BEGIN       
    if
        (SELECT Count(f1)
        FROM table
        WHERE f1 = @f1
        AND f2= @f2) 
    <= 0
    BEGIN
        INSERT INTO table
        (f1,f2)
        VALUES
        (@f1, @f2)

        RETURN @@IDENTITY
    END
END

我的语法有问题吗?或者,也许,我会以错误的方式解决这个问题?

5 个答案:

答案 0 :(得分:3)

Count(field)计算非空值 这可能与计算行数的count(*)不同。

但我不鼓励在这里使用count 看看this question

答案 1 :(得分:3)

如果您使用的是SQL Server 2008或更新版本,则应使用MERGE语句:

MERGE INTO table AS t
USING (VALUES (@f1, @f2)) AS s (f1, f2)
    ON s.f1 = t.f1
        AND s.f2 = t.f2
WHEN NOT MATCHED BY t THEN
    INSERT (f1, f2) VALUES (@f1, @f2)

答案 2 :(得分:2)

这更安全并发:

INSERT INTO table
SELECT @f1, @f2, @f3
  FROM TABLE WITH (UPDLOCK, HOLDLOCK)
 WHERE NOT EXISTS(SELECT NULL
                    FROM table
                   WHERE f1 = @f1
                     AND f2 = @f2
                     AND f3 = @f3) 

或者,如果您想保留决策逻辑(但并发安全性较低),请使用NOT EXISTS:

IF NOT EXISTS(SELECT NULL
                FROM table
               WHERE f1 = @f1
                 AND f2 = @f2
                 AND f3 = @f3) 
BEGIN

    INSERT INTO table
      (f1,f2, f3)
    VALUES
      (@f1, @f2, @f3)

    RETURN @@SCOPE_IDENTITY

END

答案 3 :(得分:1)

感谢您输入OMG / Martin,但事实证明我的问题的根源是由于参数值为null。

具体做法是:

--sproc params
@f1 int,
@f2 nvarchar(30),
@f3 datetime = null --<<a null value will screw up the IF() condition

IF(SELECT COUNT(f1)
FROM table
WHERE f1 = @f1
AND f2 = @f2
AND f3 = @f3)
<1

BEGIN
  INSERT INTO....
END

请注意,@ f3 param的默认值为null。因此,在sproc的调用者没有传递@ f3参数的情况下,即使存在匹配的@ f1,@ f2和null @ f3,IF()条件也将返回0(零)。 p>

例如:假设表格已经有

的记录
f1   f2   f3
--------------
45   foo  NULL

现在调用者通过发送它来激活sproc:

@ F1 = 45

@ F2 = FOO

(注意来电者未指定@ f3)

当IF()条件被触发时,它将返回0(零)。奇怪,是吗?直觉上,我认为条件会返回1,因为params与表中的现有值完全匹配。

为了使问题更加混乱(对我来说,无论如何),即使IF()成功(返回零),我收到“违反UNIQUE KEY约束......”异常。实际上,由于我认为param值与表中的现有记录完美匹配,因此抛出异常并不令我感到惊讶 - 对我而言,令人困惑的部分是为什么IF()条件与违反异常相矛盾的原因

顺便说一句,OMGPonies,我尝试使用你的建议(EXISTS),并出现相同的症状。显然,NULL因子会让事情变得模糊。

答案 4 :(得分:0)

SET NOCOUNT ON  
SELECT * FROM table  
WHERE f1 = @f1
        AND f2= @f2  

IF @@ROWCOUNT = 0  
BEGIN  
 INSERT INTO table  
        (f1,f2)  
        VALUES  
        (@f1, @f2)  


    RETURN @@IDENTITY  
END