executescalar mysql_DbCommand.ExecuteScalar 方法的返回值[通俗易懂]

executescalar mysql_DbCommand.ExecuteScalar 方法的返回值[通俗易懂]DbCommand.ExecuteScalar方法执行查询,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。语法:publicabstractObjectExecuteScalar()返回值:类型:System.Object,结果集中第一行的第一列。备注:使用ExecuteScalar方法从数据库中检索单个值(例如一个聚合值)。与使用ExecuteRe…

大家好,又见面了,我是你们的朋友全栈君。

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页)。

s8846357.jpg

然后在 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 的有一行的查询结果。

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148494.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【11】进大厂必须掌握的面试题-持续集成面试

    Q1。持续集成是什么意思? 我将建议您通过对持续集成(CI)进行小的定义来开始此答案。这是一种开发实践,要求开发人员每天多次将代码集成到共享存储库中。然后,每个签入均由自动构建进行…

    2020年10月20日
    324
  • linux修改用户密码命令_linux更改用户密码的命令

    linux修改用户密码命令_linux更改用户密码的命令Linux修改用户密码使用的Linux版本是:ubuntu-18.10-live-server-amd64知道一个用户名密码时,修改用户密码,各个版本下都是通用的;重置密码的时候,版本不同,可能操作的地方不一样了。如果一个账号的密码都不记得了(这通常是需要修改用户密码最多的情况),那就需要重置密码,相对就比较复杂一些,放在最后讲。但凡知道一个用户的密码,那就好办。(普通用户登录的情况下,也可以修改root用户的密码。)1.知道一个账号的密码这就是正常情况下,修改用户密码。1.1知道roo

    2025年9月21日
    6
  • 软件设计——UML建模-流程图、时序图、部署图

    在学习过程中,先整理自己看到的资料!如何绘制业务流程图:http://www.uml.org.cn/RequirementProject/201207111.aspUML建模之时序图(Sequence Diagram):http://www.cnblogs.com/ywqu/archive/2009/12/22/1629426.html【UML 建模】UML入门 之 交互图 – 时序图 协作图详解:

    2022年2月25日
    51
  • Anaconda详细安装及使用教程(带图文)

    Anacond的介绍Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。 因为包含了大量的科学包,Anaconda 的下载文件比较大(约 531MB),如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版(仅包含conda和 Python)。Conda是一个开源的包、环境管理器,可以用于…

    2022年4月7日
    61
  • 作业调度和进程调度的辨析题_进程调度的功能有哪些

    作业调度和进程调度的辨析题_进程调度的功能有哪些很多学习完《操作系统原理》这门课程的小伙伴都应该对“FCFS(先到先服务)”、“SJF(短作业优先)”等调度算法原理比较熟悉。但是在实际做题的时候,往往一不小心就把概念搞错,不容易区分“作业调度”和“进程调度”的区别。下面我主要针对这两个概念进行解析并给出经典习题解答。PS:本博客并不详解每种调度算法的原理,因此有这方面需求的小伙伴可以直接pass了。1、作业调度作业调度又称为高级调度,频度较低。其主要工作是将位于外存后备队列中的某个(或某几个)作业调入内存,排在就绪队列上。注意了,这个时候仅仅是将作

    2022年9月29日
    3
  • 被虐后,分享一点点JVM调优原理相关的知识和经验

    怕什么真理无穷进一步有近一步的欢喜‍‍本文只介绍一些原理和思路的内容,希望对你与所帮助!‍‍先了解原理,然后在进行调优。一定要记住的是任何的调优都不是一蹴而就,不要指望改动一个参数就达到调…

    2022年3月1日
    56

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号