【问题标题】:IsNULL and Coalesce proper usageIsNULL 和 Coalesce 正确使用
【发布时间】:2012-05-19 19:16:37
【问题描述】:

因为我们有两个选项来拦截来自数据库的空值...

  1. ISNull
  2. 合并

以下是上述两个函数的查询写法...

Select IsNull(Columnname, '') As validColumnValue From TableName

Select Coleasce(Columnname, '') As validColumnValue From TableName

查询 - 在哪种情况下应该首选哪个以及为什么?

【问题讨论】:

标签: asp.net sql-server-2008 sql-server-2005


【解决方案1】:

这已被散列并重新散列。除了the tip I pointed out in the comment 和上面发布的链接和解释@xQbert 之外,这里的请求是使用子查询对 COALESCE 与 ISNULL 的解释。让我们考虑这两个查询,它们的结果是相同的:

SELECT COALESCE((SELECT TOP (1) name FROM sys.objects), N'foo');

SELECT ISNULL((SELECT TOP (1) name FROM sys.objects), N'foo');

(关于使用没有 ORDER BY 的 TOP 到 /dev/null/ 的评论。)

在 COALESCE 案例中,逻辑实际上被扩展为这样的:

SELECT CASE WHEN (SELECT TOP (1) ...) IS NULL
    THEN (SELECT TOP (1) ...)
    ELSE N'foo'
END

使用 ISNULL,这不会发生。有一个内部优化似乎可以确保子查询只被评估一次。我不知道微软以外的任何人是否知道这种优化是如何工作的,但如果你比较计划,你就可以做到这一点。以下是 COALESCE 版本的计划:

这是 ISNULL 版本的计划 - 注意它是多么简单(并且扫描只发生一次):

在 COALESCE 情况下,扫描发生两次。这意味着子查询被评估两次,即使它没有产生任何结果。如果添加 WHERE 子句以使子查询产生 0 行,您将看到类似的差异 - 计划形状可能会发生变化,但您仍会看到双重查找 + 查找或扫描 COALESCE 案例。这是一个稍微不同的例子:

SELECT COALESCE((SELECT TOP (1) name FROM sys.objects 
    WHERE name = N'no way this exists'), N'foo');

SELECT ISNULL((SELECT TOP (1) name FROM sys.objects 
    WHERE name = N'no way this exists'), N'foo');

这次 COALESCE 版本的计划 - 你可以再次看到代表子查询的整个分支逐字逐句重复:

还有一个更简单的计划,使用 ISNULL 完成大约一半的工作:

您还可以在 dba.se 上查看此问题以进行更多讨论:

我的建议是这样的(您可以在提示和上述问题中看到我的原因):信任但验证。我总是使用 COALESCE(因为它是 ANSI 标准,支持两个以上的参数,并且不会像数据类型优先级那样做不可靠的事情)除非我知道我使用子查询作为其中之一表达式(我不记得曾经在这样的理论工作之外做过),或者我遇到了一个真正的性能问题,只是想比较一下 COALESCE 与 ISNULL 是否有任何实质性的性能差异(在子查询案例之外,我还没有找到)。由于我几乎总是将 COALESCE 与类似数据类型的参数一起使用,因此我很少需要做任何测试,除了回顾我过去所说的(我也是 the aspfaq article that xQbert pointed out 的作者,7 年前)。

【讨论】:

  • +1 面对现实,你只是喜欢关于 coalesce 和 isnull 的讨论!但说真的,这里有一些非常深入的东西。
  • @AaronBertrand 在前两张图片中,第一张是:(2*49.9),第二张是(1*99.8)......那么有什么区别吗?如果我走 100 英尺或 50 +50 有什么关系?请解释一下.... :)(我很讨厌阅读处决计划...)
  • @Royi 这些是百分比。如果你走 200 英尺,每 100 英尺就是你行程的 50%。如果你只走 100 英尺,那就是你旅行的 100%。你认为你走的距离是一样的,因为这两种情况下的百分比加起来都是 100?
  • @AaronBertrand 你有没有适合阅读这些执行计划的好文章? (只有当你很快...)谢谢。
  • Grant Fritchey 有一本很棒的免费电子书。对不起,我在打电话,你必须搜索。
【解决方案2】:

开始幽默:第 1 次,第 2 次永远不会起作用,因为拼写错误:D 结束幽默

---清理响应---

isNull(value1,value2)的特点

  • 仅支持 1 次评估,如果第一个为 null,则使用第二个,因此如果它也为 null,则返回 null!
  • 是非 ANSI 标准。这意味着如果数据库可移植性是一个问题,请不要使用这个
  • isnull(value1,value2) 将返回 Value1 的数据类型
  • 将返回所选值的数据类型,并在无法进行隐式转换时失败

Coalesce 的特点(Value1、Value2、value3、value...)

  • 支持Null的多重估值;基本上会从列表中拉入第一个非空值。如果列表中的所有值都为 null,则返回 null。
  • 是 ANSI 标准,这意味着数据库可移植性不应该成为问题。
  • 将返回所选值的数据类型,如果选择中的所有字段不返回相同的数据类型,则会失败。

所以直接回答这个问题: 是否需要开发 SQL 则视情况而定

  • 独立于数据库; coalesce 使用起来更正确。
  • 允许进行多次评估; coalesce 更正确(当然你可以一遍又一遍地嵌入 isnull ......)但是把它放在性能显微镜下,coalesce 可能会赢。 (我没有测试过)
  • 您是否使用支持 isNull 的数据库引擎? (如果不使用合并)
  • 您希望如何处理类型转换?是否隐含。

---原创------ is null 仅支持 2 次评估

coalesce 支持更多... coalesce (columnName1, ColumnName2, ColumnName3, '')

coalesce 返回类似于案例评估的数据类型,而 isnull 返回列表中第一个的数据类型。 (我觉得很有趣!)

至于何时使用哪个。您必须通过查看 SQL 2008 和 2005 上的执行计划进行调查,不同的版本不同的引擎不同的执行方式。

此外,coalesce 是 ansii 标准,isnull 是特定于引擎的。因此,如果您希望在 dbengine 之间具有更大的可移植性,请使用 coalesce。

更多信息here aspfaqhere msdn blog

【讨论】:

  • 我需要一些时间来仔细阅读您的参考资料。我会尽快更新你,如果觉得有用就接受。
  • 在大多数情况下,执行计划是相同的。我知道有一个例外:当其中一个表达式是子查询时,它将变为CASE WHEN <subquery> IS NOT NULL THEN <subquery>...,这意味着子查询将被计算两次。希望没有多少人说COALESCE(<subquery>, <subquery>, ...
  • 你能详细解释一下吗?我实际上从未在Coalesce 中使用过SubQuery 概念。
【解决方案3】:

你可以考虑一下。

  1. ISNULL函数需要两个参数:要检查的值和空值的替换

    2.COALESCE 函数有点不同 COALESCE 将接受任意数量的参数并返回第一个非NULL 值,我更喜欢COALESCE 超过 ISNULL 'cause 符合 ANSI 标准,而 ISNULL 不符合。

    希望您找到问题的答案。

【讨论】:

    猜你喜欢
    • 2015-01-12
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2010-10-22
    • 2016-12-16
    相关资源
    最近更新 更多