SQLite“;计数(*)";被认为是有害的?
考虑以下简单示例:SQLite“;计数(*)";被认为是有害的?,sql,database,sqlite,Sql,Database,Sqlite,考虑以下简单示例: prompt% sqlite3 test.db sqlite> create table employee ( employee_id integer primary key, first_name varchar2(32) not null, last_name varchar2(32) not null ); sqlite> insert in
prompt% sqlite3 test.db
sqlite> create table employee (
employee_id integer primary key,
first_name varchar2(32) not null,
last_name varchar2(32) not null
);
sqlite> insert into employee (first_name, last_name) values ('Bill', 'Smith');
sqlite> insert into employee (first_name, last_name) values ('Sally', 'Jones');
sqlite> insert into employee (first_name, last_name) values ('Bill', 'Jones');
sqlite> select first_name, count(*) from employee;
结果如何
天真的人可能会认为:
Bill|2
Sally|1
但是有经验的人会注意到SELECT查询缺少“GROUPBY”子句。Oracle在提供此查询时,实际上会抛出一个错误:
SQL ERROR: ORA-00937: not a single-group group function
然而,SQLite并没有抱怨,而是产生了:
Bill|3
我觉得这是假的。。。我认为,显示总行数可能有意义,但简单地选择最后一个“first_name”似乎相当武断,而且有潜在的危险
这是一个bug还是一个我无法理解的特性?SQLite没有提供类似的安全网有什么原因吗?仅此而已:
如果SELECT语句是没有GROUP BY的聚合查询
子句,然后计算结果集中的每个聚合表达式
一旦跨越整个数据集。中的每个非聚合表达式
结果集对任意选择的数据行计算一次
数据集。每一行使用相同的任意选择行
非聚合表达式
通过计算聚合创建的结果集数据的单行
结果集中的非聚合表达式构成
不带GROUPBY子句的聚合查询。不带属性的聚合查询
GROUPBY子句始终只返回一行数据,即使
有零行输入数据
简言之,没有安全网。如果需要,请不要忘记GROUP BY。如果没有选择所有行,则使用没有
GROUP BY
子句的聚合函数是没有意义的。想想看,你到底在数什么?您需要按名字从员工组中选择名字、计数(*)
如果所有记录都被视为在一个组中(并且您只需要记录的数量,或者最大值,或者其他任何值),那么使用不带GROUP BY
的聚合是有意义的。这里没有意义的是first\u name
的值。这看起来像是一个bug,或者至少是一个非常糟糕的SQL实现。它的实现与MySQL@mwigdahl完全相同。因为,可以使用MIN
或MAX
为非聚合表达式选择行。这是完全不标准的,但在某些情况下很有用。