DbCommand.ExecuteScalar 方法

MSDN 对DbCommand.ExecuteScalar方法是这样描述的:

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

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

Keywords (2 keyword_id SERIAL PRIMARY KEY,3 keyword VARCHAR(40) NOT NULL, (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 testmysql> 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 using System; 2 using MySql.Data.MySqlClient; Skyiv.Test 5 { Tester 7 { Main() 9 {);););13 }Test(string sql)16 {))18using (var comm = conn.CreateCommand())19 {20 conn.Open();21comm.CommandText = sql;22var result = comm.ExecuteScalar();, : result.GetType().ToString(),25result is DBNull, 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.exeType: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.ExecuteScalar 方法

相关文章:

你感兴趣的文章:

标签云: