asp.net - IsNULL 和 Coalesce 的正确用法

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

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

  1. ISNull
  2. Coalesce

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

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

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

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

最佳答案

这已经过散列和重新散列。除了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,这不会发生。有一个内部优化似乎可以确保子查询只被评估一次。我不知道 Microsoft 之外的任何人是否都知道这种优化的确切工作原理,但如果你比较这些计划,你就可以做到这一点。以下是 COALESCE 版本的计划:

enter image description here

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

enter image description here

在 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 版本的计划 - 您可以再次看到代表子查询的整个分支逐字重复:

enter image description here

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

enter image description here

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

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

关于asp.net - IsNULL 和 Coalesce 的正确用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10668140/

相关文章:

c# - 查看 MVC 2 中无法正常工作的数据

c# - ASP.NET 如何在 asp 按钮单击上填充 html 表

SQL Server 2012如何查看数据?

c# - 如何为 Ubuntu 12.04 开发 C#.NET 应用程序

sql - 生成序列号

c# - 将已安装的 C# 应用程序连接到本地 SQL Server 2005 Express - 用户未与受信任的 sql 连接相关联

asp.net - 虚拟目录路径如何区分大小写?

javascript - 通过 jquery post 函数(Web API)将对象从 javascript 传递到 Controller

sql-server - 有没有一种方法可以列出所有对象,例如使用同义词的 View ?

sql-server - win 7 64位需要sql server 2000