空值和 MERGE 语句:我需要将值设置为无穷大。如何?
在具有 MERGE
代码的 SQL Server 中,一切都很好,除非有 2 个可为空的列。
如果我传递一个空值并且目标不为空,则 MERGE 不会看到差异(针对 null = false 进行评估)。如果我在双方(源和目标)上使用 IsNull ,则可以工作,但存在可能错误评估值的问题。
最后一句话的意思是,如果我说:
WHEN MATCHED AND NOT (IsNull(tgt.C, 0) = IsNull(src.C, 0)) THEN
那么如果 tgt.C 为 null 并且 src.C = 0,则不会执行任何更新。无论我选择什么替代值,我都会遇到这个问题。
我还尝试了“AND NOT (...true...)”语法,因为 BOL 声明针对 null 的评估结果为 FALSE。然而,它们似乎实际上导致 NULL,并且不会导致我的多部分语句变为 false。
我认为一种解决方案是使用 NaN 或 -INF 或 +INF 因为这些在目标中无效。但我找不到在 SQL 中表达这一点的方法。
有什么想法如何解决这个问题吗?
编辑:
以下逻辑解决了问题,但它很冗长并且不会进行快速评估:
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';
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';
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在 SQL Server 2022 中,您可以使用
在以前的版本中,您可以使用
如果您需要跨多个列执行此检查,第二个版本仍然可以更紧凑。
有关此问题的更多信息,请参阅本文 。
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.
您可以更改合并语句的 ON 部分,检查源和目标何时为空。
You can change the ON part of the merge statement, putting in a check for when both source and target are null.
事实上,这样效果更好。只需添加另一个替换值作为 OR :-
Actually, this works better. Just add another substitution value as an OR :-
您是否尝试过
SET ANSI_NULLS OFF
,这将使NULL=NULL
返回true? 这可能会产生其他问题,但它可能是脚本级解决方法(运行过程后将其关闭然后再打开)。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).当您有多个列想要检查它们是否不同时,这也有效,并且可能会更好。
This works as well and may be better when you have multiple columns that you want to check if they are different.
您可以在 ON 子句中检查 null:
You can check for null in the ON Clause:
当值为 null 时,为什么不使用一个极不可能存在的值,而不是使用 0?
EG (IsNull(tgt.C, 2093128301)。
数据类型是 int,所以你有很多东西可以玩……
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......