当前位置:  开发笔记 > 后端 > 正文

在SQLite GROUP BY查询的SELECT列表中包含额外的列是否安全?

如何解决《在SQLiteGROUPBY查询的SELECT列表中包含额外的列是否安全?》经验,为你挑选了1个好方法。

我有一个名为"message"的简单SQLite表:

sequence INTEGER PRIMARY KEY
type TEXT
content TEXT

我想获取每种类型的最后一条消息的内容(由其序列决定).令我惊讶的是,以下简单查询有效:

SELECT MAX(sequence), type, content
FROM message
GROUP BY type

很惊讶,因为我知道MSSQL或Postgres会拒绝在SELECT列表中包含一个不属于GROUP BY子句或聚合函数的列,我必须进行连接,如下所示:

SELECT m.sequence, m.type, m.content
FROM
(
    SELECT MAX(sequence) as sequence, type
    FROM message
    GROUP BY type
) g
JOIN message m
ON g.sequence = m.message_sequence

我的问题是:在SQLite中使用第一个更简单的查询形式是否安全?直觉上它选择与"MAX(序列)"值匹配的"内容"值是有道理的,但文档似乎根本没有谈到这一点.当然,如果序列不是唯一的,那么结果将是未定义的.但是,如果序列是唯一的,就像我的情况一样,这是保证还是仅仅是一个可以改变的幸运实现细节?



1> Bill Karwin..:

您可以"安全地"使用这些查询,也就是说,如果额外的列在功能上依赖于您分组的列,则不会产生不明确的结果:

SELECT c.parent_id, COUNT(*), p.any_column
FROM child_table c 
JOIN parent_table p USING (parent_id)
GROUP BY c.parent_id;

上面的例子可以在SQLite中使用,并产生一个明确的结果,因为p.any_column每组不可能有多个值.但是,此查询严格违反SQL标准,大多数品牌的RDBMS都会引发错误.

但是,编写一个产生模糊结果的查询太容易了.为每个组命名一个具有多个值的列时,无法控制结果集中返回的值.

在实践中,MySQL返回第一行中相对于物理存储的值,SQLite返回最后一行的值.但它完全依赖于实现而且不可靠.如果任一软件的下一个版本更改其内部,则升级后可能会得到不同的查询结果.所以最好不要依赖这种行为.


关于你的例子,哪里content应该"直观地"得到sequenceMAX 行的值.但这真的很直观吗?考虑以下其他情况:

SELECT MAX(sequence), MIN(sequence), type, content
FROM message
GROUP BY type

那么哪一行现在提供的价值content?哪一行sequence是MAX,sequence哪一行是MIN?

如果您使用非唯一列(例如date),并且有多个行具有相同的MAX值date,但是不同的值,该content怎么办?

SELECT MAX(date), type, content
FROM message
GROUP BY type

什么样的其他聚合函数AVG()SUM()?可能是聚合的值对应于表中没有单独的行.那么现在哪一行应该提供的价值content

SELECT AVG(sequence), type, content
FROM message
GROUP BY type

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有