DbCommand.ExecuteScalar 方法

执行查询,并返回查询所返回的结果集中第一行的第一列。 所有其他的列和行将被忽略。

语法: public abstract Object ExecuteScalar()

返回值: 类型: System.Object,结果集中第一行的第一列。

备注: 使用 ExecuteScalar 方法从数据库中检索单个值(例如一个聚合值)。 与使用 ExecuteReader 方法然后使用 DbDataReader 返回的数据执行生成单个值所需的操作相比,此操作需要的代码较少。如果找不到结果集中第一行的第一列;则返回 null 引用(在 Visual Basic 中为 Nothing)。 如果数据库中的该值为 null,此查询将返回 DBNull.Value。

准备测试用例

让我们这实际测试一下吧,首先准备好以下 create-table-Keywords.sql :

1 CREATE TABLEKeywords (2 keyword_id SERIAL PRIMARY KEY,3 keyword VARCHAR(40) NOT NULL,4 UNIQUE KEY(keyword)5 )

上面的 SQL 语句来源于《SQL反模式》一书 第17章 可怜人的搜索引擎 第5节 解决方案:使用正确的工具 (第159页)。

然后在 openSUSE 12.1 操作系统的 MySQL 5.5.16 数据库中执行以下 SQL 命令:

ben@vbox:~/work/SQL-Antipatterns> mysql -u test -ppwd-for-test test

mysql> source create-table-Keywords.sql;

Query OK, 0 rows affected (0.18 sec)

mysql> desc Keywords;

+------------+---------------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+------------+---------------------+------+-----+---------+----------------+

| keyword_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |

| keyword | varchar(40) | NO | UNI | NULL | |

+------------+---------------------+------+-----+---------+----------------+

2 rows in set (0.01 sec)

mysql> insert into Keywords (keyword) values ('crash');

Query OK, 1 row affected (0.10 sec)

在 MySQL Client 中测试

接着在 MySQL Client 中执行以下三个 SQL select 语句:

mysql> select keyword_id from Keywords where keyword = 'crash';

+------------+

| keyword_id |

+------------+

| 1 |

+------------+

1 row in set (0.01 sec)

mysql> select keyword_id from Keywords where keyword = 'aborted';

Empty set (0.00 sec)

mysql> select max(keyword_id) from Keywords where keyword = 'aborted';

+-----------------+

| max(keyword_id) |

+-----------------+

| NULL |

+-----------------+

1 row in set (0.01 sec)

mysql>

第一个 select 语句返回一个确实存在的 keyword_id 值,第二个 select 语句返回空结果集,第三个 select 语句返回的结果集中有一行数据,但是其值是 NULL,这是因为 SQL MAX() 函数在起作用。注意由于 Keywords 表的 keyword 列有 unique 索引,上面三个 select 语句返回的结果集中最多只能有一行,不可能有多行。

在 ADO.NET 中测试

我们使用以下 C# 程序 Tester.cs 来测试上述三个 SQL select 语句:

1 usingSystem;2 usingMySql.Data.MySqlClient;3

4 namespaceSkyiv.Test5 {6 static classTester7 {8 static voidMain()9 {10 Test("SELECT keyword_id FROM Keywords WHERE keyword = 'crash'");11 Test("SELECT keyword_id FROM Keywords WHERE keyword = 'aborted'");12 Test("SELECT MAX(keyword_id) FROM Keywords WHERE keyword = 'aborted'");13 }14

15 static void Test(stringsql)16 {17 using (var conn = new MySqlConnection("server=localhost;user=test;password=pwd-for-test;database=test"))18 using (var comm =conn.CreateCommand())19 {20 conn.Open();21 comm.CommandText =sql;22 var result =comm.ExecuteScalar();23 Console.WriteLine("Type:{0,-13} DBNull:{1,-5} null:{2,-5} Value:[{3}]",24 (result == null) ? "(null)": result.GetType().ToString(),25 result isDBNull, result == null, result);26 }27 }28 }29 }

使用 Mono 2.10.6 编译和运行,结果如下所示:

ben@vbox:~/work/SQL-Antipatterns> dmcs Tester.cs -r:/home/ben/repo/dll/MySql.Data.dll && mono Tester.exe

Type:System.UInt64 DBNull:False null:False Value:[1]

Type:(null) DBNull:False null:True Value:[]

Type:System.DBNull DBNull:True null:False Value:[]

ben@vbox:~/work/SQL-Antipatterns>

从上述运行结果中,我们可以看出:

对于第二个 select 语句,DbCommand.ExecuteScalar 方法的返回值是 null,调用者需要使用 result == null 来判断。

对于第三个 select 语句,DbCommand.ExceuteScalar 方法的返回值是 DBNull.Value,调用者需要用 result is DBNull 或者 result == DBNull.Value 来判断。

对 ADO.NET 的 DbCommand.ExecuteScalar 方法的调用者来说,select keyword_id 和 select MAX(keyword_id) 都是一样方便的,只不过要注意根据所使用的 SQL 语句来选择使用 result == null 还是使用 result is DBNull 来判断查询结果是否为空。所以我建议使用 select keyword_id 这种 SQL 语句,以减少一个 SQL MAX() 调用,提高运行效率。

当然,如果使用 result == null || result is DBNull 来判断查询结果是否为空就更保险了,能够适应这两种 SQL 语句的写法,但是运行效率就稍微低了一点。

如果是使用 DbCommand.ExcuteReader 方法来获得查询结果:

对于第二个 select 语句,需要判断 DbDataReader.Read 方法的返回值来决定查询结果是否为空。

对于第三个 select 语句,DbDataReader.Read 方法的返回值总是 true,而是通过 DbDataReader.IsDBNull 方法来判断查询结果是否为空。

当然,对于查询结果最多只有一行一列的情况是不推荐使用 DbCommand.ExcuteReader 方法的。只有查询结果有可能有多行,或者查询结果有多列的情况下,才需要使用 DbCommand.ExcuteReader 方法。

《SQL反模式》中的用法

在《SQL反模式》一书第159页是在以下存储过程中使用 MAX() 函数的:

1 CREATE PROCEDURE BugsSearch(keyword VARCHAR(40))2 BEGIN

3 SET @keyword =keyword;4 PREPARE s1 FROM 'SELECT MAX(keyword_id) INTO @k FROM Keywords WHERE keyword = ?';5 EXECUTE s1 USING @keyword;6 DEALLOCATE PREPARES1;7 IF (@k IS NULL) THEN

8 --(这里省略若干语句)

9 END IF;10 --(这里再次省略若干语句)

11 END

看来这里的 MAX() 函数是不能省略的,虽然 Keyswords 表的 keyword 列上有 unique 索引,查询结果中不可能有多行,但是查询结果可能为空集,所以需要使用 MAX() 函数将空的查询结果转换为值为 NULL 的有一行的查询结果。

参考资料

executescalar mysql_DbCommand.ExecuteScalar 方法的返回值相关推荐

  1. java gettext返回值_012-关于EditText中的getText()方法的返回值类型以及string的转换问题(转)...

    EditText中的getText()方法的返回值为CharSequence,如果我们想要获得string类型数据的话,需要在后边加上.toString 另外,String类型转为int:Intege ...

  2. document.getElementsByTagName()方法的返回值

    document.getelementsbytagname()方法的返回值 /* document.getelementsbytagname()方法的返回值中取出某个特定的元素.一开始以为它的返回值是 ...

  3. Spring-AOP @AspectJ进阶之绑定连接点方法的返回值

    文章目录 概述 实例 概述 在后置增强中,可以通过returning绑定连接点方法的返回值 实例 代码已托管到Github-> https://github.com/yangshangwei/S ...

  4. setTimeout() 方法的返回值

    setTimeout() 方法的返回值 setTimeout() 方法的返回值是一个唯一的数值,这个数值有什么用呢?如果你想要终止 setTimeout() 方法的执行,那就必须使用 clearTim ...

  5. C#为什么支持协变的参数只能用于方法的返回值?支持逆变的参数只能用于方法参数?...

    "TParent不能安全转换成TSub",是这两个问题的共同原因. 我们定义一个接口IFoo. interface IFoo<T>     {         void ...

  6. 函数式接口作为方法的返回值类型案例

    类似地,如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式.当需要通过一 个方法来获取一个java.util.Comparator 接口类型的对象作为排序器时,就可以调 ...

  7. Spring MVC 中的 controller层的方法的返回值类型

    Controller方法的返回值可以有以下几种: 1.返回ModelAndView 返回ModelAndView时最常见的一种返回结果.需要在方法结束的时候定义一个ModelAndView对象,并对M ...

  8. controller调用另一个controller中的方法 获取返回值_必须掌握!你知道 Spring 中运用的 9 种设计模式吗 ?...

    Spring中涉及的设计模式总结,在面试中也会经常问道 Spring 中设计模式的问题.本文以实现方式.实质.实现原理的结构简单介绍 Sping 中应用的 9 种设计模型,具体详细的刨析会在后面的文章 ...

  9. Java面试题:IO流中read()方法为什么返回值是int

    Question:IO流中read()方法为什么返回值是int? anwser:因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte, ...

最新文章

  1. 美团某程序员爆料:绩效背c的都要签pip!网友:pip就是变相劝退!
  2. 基于Springboot实现图书管理系统
  3. [转]thinkphp 模板显示display和assign的用法
  4. BrowserLog——使用Chrome控制台作为Log查看器
  5. 【Bapi】客户主数据快捷修改
  6. 一个历史遗留问题,引发的linux内存管理的‘血案’
  7. 第三次作业-Scrum
  8. [POJ 3709] K-Anonymous Sequence(斜率优化dp / 动态维护凸包)
  9. SDN精华问答 | SDN的核心技术是什么?
  10. a=a+b和a+=b的区别
  11. 内温的整体优先效应实验_[心理学复习.doc
  12. BFS广度优先算法, DFS深度优先算法,Python,队列实现,栈实现
  13. Type Cast的翻译,强转不如造型
  14. MySQL – iBatis – 文件存储
  15. 在利用计算机高级语言进行,2016计算机一级考试多选题专项训练及答案
  16. Windows 32位下cocos2d-x2.2.0Android环境搭建
  17. Addon SuperEdge 让原生 K8s 集群可管理边缘应用和节点
  18. 萨班斯法案:由来、影响及争论
  19. linux系统中的挂载点:
  20. PHP 登录TPlink路由器

热门文章

  1. 全球最有创意的50张图片(原创整理)
  2. qq udp tcp机制
  3. NFS+mount挂载
  4. linux ipvsadm命令详解
  5. vue elementUI 之 this.$confirm 用法
  6. 回归分析(stata实例详细解答过程)
  7. 树莓派ubuntu设置静态ip地址
  8. 幻想神域服务器维护,幻想神域 10月21日官网服务器瘦身计划说明
  9. 飞翔机器人动态壁纸_长臂机器人(HandyBot)官方下载_长臂机器人官方安卓v1.0下载_快吧游戏...
  10. PyTorch最佳实践,教你写出一手风格优美的代码