srm*_*ark 68 sql t-sql sql-server stored-procedures
我想确保我没有在表格中插入重复的行(例如,只有主键不同).我的所有字段都允许NULLS,因为我已经确定null表示"所有值".由于null,我的存储过程中的以下语句不起作用:
IF EXISTS(SELECT * FROM MY_TABLE WHERE
MY_FIELD1 = @IN_MY_FIELD1 AND
MY_FIELD2 = @IN_MY_FIELD2 AND
MY_FIELD3 = @IN_MY_FIELD3 AND
MY_FIELD4 = @IN_MY_FIELD4 AND
MY_FIELD5 = @IN_MY_FIELD5 AND
MY_FIELD6 = @IN_MY_FIELD6)
BEGIN
goto on_duplicate
END
Run Code Online (Sandbox Code Playgroud)
因为NULL = NULL不是真的.
如何在没有每列的IF IS NULL语句的情况下检查重复项?
小智 69
与@ Eric的答案一样,但没有使用'NULL'符号.
(Field1 = Field2) OR (ISNULL(Field1, Field2) IS NULL)
Run Code Online (Sandbox Code Playgroud)
只有当两个值non-NULL相同且彼此相等或两个值都相同时,才会出现这种情况NULL
Qua*_*noi 48
使用INTERSECT运算符.
NULL如果您的所有字段都有复合索引,那么它是敏感且高效的:
IF EXISTS
(
SELECT MY_FIELD1, MY_FIELD2, MY_FIELD3, MY_FIELD4, MY_FIELD5, MY_FIELD6
FROM MY_TABLE
INTERSECT
SELECT @IN_MY_FIELD1, @IN_MY_FIELD2, @IN_MY_FIELD3, @IN_MY_FIELD4, @IN_MY_FIELD5, @IN_MY_FIELD6
)
BEGIN
goto on_duplicate
END
Run Code Online (Sandbox Code Playgroud)
请注意,如果您UNIQUE在字段上创建索引,您的生活将会更加简单.
Wil*_*Cau 34
在进行MERGE时我需要进行类似的比较:
WHEN MATCHED AND (Target.Field1 <> Source.Field1 OR ...)
Run Code Online (Sandbox Code Playgroud)
附加检查是为了避免更新所有列已经相同的行.为了我的目的,我想NULL <> anyValue成为真,并且NULL <> NULL是假的.
解决方案演变如下:
第一次尝试:
WHEN MATCHED AND
(
(
-- Neither is null, values are not equal
Target.Field1 IS NOT NULL
AND Source.Field1 IS NOT NULL
AND Target.Field1 <> Source.Field1
)
OR
(
-- Target is null but source is not
Target.Field1 IS NULL
AND Source.Field1 IS NOT NULL
)
OR
(
-- Source is null but target is not
Target.Field1 IS NOT NULL
AND Source.Field1 IS NULL
)
-- OR ... Repeat for other columns
)
Run Code Online (Sandbox Code Playgroud)
第二次尝试:
WHEN MATCHED AND
(
-- Neither is null, values are not equal
NOT (Target.Field1 IS NULL OR Source.Field1 IS NULL)
AND Target.Field1 <> Source.Field1
-- Source xor target is null
OR (Target.Field1 IS NULL OR Source.Field1 IS NULL)
AND NOT (Target.Field1 IS NULL AND Source.Field1 IS NULL)
-- OR ... Repeat for other columns
)
Run Code Online (Sandbox Code Playgroud)
第三次尝试(受@ THEn的回答启发):
WHEN MATCHED AND
(
ISNULL(
NULLIF(Target.Field1, Source.Field1),
NULLIF(Source.Field1, Target.Field1)
) IS NOT NULL
-- OR ... Repeat for other columns
)
Run Code Online (Sandbox Code Playgroud)
相同的ISNULL/NULLIF逻辑可用于测试相等性和不等式:
ISNULL(NULLIF(A, B), NULLIF(B, A)) IS NULLISNULL(NULLIF(A, B), NULLIF(B, A)) IS NOT NULL这是一个SQL-Fiddle演示如何工作http://sqlfiddle.com/#!3/471d60/1
Eri*_*ric 32
用途ISNULL:
ISNULL(MY_FIELD1, 'NULL') = ISNULL(@IN_MY_FIELD1, 'NULL')
Run Code Online (Sandbox Code Playgroud)
您可以更改'NULL'喜欢的东西'All Values',如果它更有意义,这样做.
应该注意的是,有两个参数,ISNULL工作方式相同COALESCE,如果你有一些值要测试(ie- COALESCE(@IN_MY_FIELD1, @OtherVal, 'NULL')),你可以使用它们.COALESCE也会在第一个非null之后返回,这意味着如果你期望MY_FIELD1为空,它会(稍微)更快.但是,我发现ISNULL它更具可读性,所以这就是我在这里使用它的原因.
Sha*_*nce 20
IF EXISTS(SELECT * FROM MY_TABLE WHERE
(MY_FIELD1 = @IN_MY_FIELD1
or (MY_FIELD1 IS NULL and @IN_MY_FIELD1 is NULL)) AND
(MY_FIELD2 = @IN_MY_FIELD2
or (MY_FIELD2 IS NULL and @IN_MY_FIELD2 is NULL)) AND
(MY_FIELD3 = @IN_MY_FIELD3
or (MY_FIELD3 IS NULL and @IN_MY_FIELD3 is NULL)) AND
(MY_FIELD4 = @IN_MY_FIELD4
or (MY_FIELD4 IS NULL and @IN_MY_FIELD4 is NULL)) AND
(MY_FIELD5 = @IN_MY_FIELD5
or (MY_FIELD5 IS NULL and @IN_MY_FIELD5 is NULL)) AND
(MY_FIELD6 = @IN_MY_FIELD6
or (MY_FIELD6 IS NULL and @IN_MY_FIELD6 is NULL)))
BEGIN
goto on_duplicate
END
Run Code Online (Sandbox Code Playgroud)
Wordy与IFNULL/COALESCE解决方案相比.但是无需考虑哪些值不会出现在可以用作NULL的数据中的数据.
but*_*ken 10
你可以合并每个值,但它有点畏缩:
IF EXISTS(SELECT * FROM MY_TABLE WHERE
coalesce(MY_FIELD1,'MF1') = coalesce(@IN_MY_FIELD1,'MF1') AND
...
BEGIN
goto on_duplicate
END
Run Code Online (Sandbox Code Playgroud)
您还需要确保该coalesced值不是相关列上的其他有效值.例如,如果MY_FIELD1的值可能是'MF1',那么这将导致大量的虚假命中.
小智 7
如果你想对不相等的值进行比较怎么办?只是在前面提到的比较前使用"NOT"不起作用.我能想到的最好的是:
(Field1 <> Field2) OR (NULLIF(Field1, Field2) IS NOT NULL) OR (NULLIF(Field2, Field1) IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
相等比较:
((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))
Run Code Online (Sandbox Code Playgroud)
不等于比较:只需否定上面的等于比较。
NOT ((f1 IS NULL AND f2 IS NULL) OR (f1 IS NOT NULL AND f2 IS NOT NULL AND f1 = f2))
Run Code Online (Sandbox Code Playgroud)
它很冗长吗?是的。但是它很有效,因为它不调用任何函数。这个想法是在谓词中使用短路来确保相等运算符 (=) 仅用于非空值,否则 null 将在表达式树中向上传播。