In SQL Server with a MERGE
code, everything is fine except when there are 2 nullable columns.
If I pass a null value and the target isn't null, MERGE doesn't see a difference (evals against null = false). If I use IsNull on both sides (source & target) that works, but has the issue of potentially mis-evaluating a value.
What I mean by the last statement is, if I say:
WHEN MATCHED AND NOT (IsNull(tgt.C, 0) = IsNull(src.C, 0)) THEN
then if tgt.C is null and src.C = 0, no update will be performed. No matter what substitute value I choose, I'll have this problem.
I also tried the "AND NOT (...true...)" syntax since BOL states that evaluations against null result in FALSE. However, it seems they actually result in NULL and do not result in my multi-part statement becoming false.
I thought one solution is to use NaN or -INF or +INF since these are not valid in target. But I can't find a way to express this in the SQL.
Any ideas how to solve this?
EDIT:
The following logic solves the problem, but it's verbose and won't make for fast evals:
declare @i int, @j int
set @j = 0
set @i = 0
if ISNULL(@i, 0) != ISNULL(@j, 0) OR
((@i is null or @j is null) and not (@i is null and @j is null))
print 'update';
9条答案
按热度按时间polhcujo1#
In SQL Server 2022 you can use
In previous versions you can use
The second version can still be more compact if you need to do this check across multiple columns.
See this article for more on this issue.
z9smfwbn2#
You can change the ON part of the merge statement, putting in a check for when both source and target are null.
nhaq1z213#
Actually, this works better. Just add another substitution value as an OR :-
eni9jsuy4#
Have you tried
SET ANSI_NULLS OFF
, which will makeNULL=NULL
return true? This may create additional issues but it could be a script-level workaround (turn it off then on once you run your proc).ajsxfq5m5#
rm5edbpk6#
This works as well and may be better when you have multiple columns that you want to check if they are different.
czq61nw17#
You can check for null in the ON Clause:
wrrgggsh8#
Instead of using 0 when the values are null, why not use a value that is highly unlikely to exist? EG (IsNull(tgt.C, 2093128301).
The datatypes are int so you have a lot to play with......
6tdlim6h9#