MY.L6.SQL_MODE_LOOSE_GROUP_BY — a GROUP BY that returns a value from a row nobody chose
- Category: idiom
- Level: 6
- Confidence: deterministic
- Downtime class: none
- Stability: stable
- Suites: audit
- Applies to: MySQL 8.4
- Not transferable to MariaDB: this page describes MySQL 8.4 behavior. MariaDB answers the same driver and does not share these semantics, so SQLens refuses it outright rather than reasoning about it — see drivers/unsupported.
Without ONLY_FULL_GROUP_BY, a GROUP BY may select a column that is neither grouped nor
aggregated, and the server returns an arbitrary row's value for it.
Not random enough to notice in development. Not stable enough to rely on.
Flagged
SET GLOBAL sql_mode = 'NO_ZERO_DATE';
Preferred
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
Why four rules and not one
Four independent guards live in the single sql_mode variable, and a project may legitimately
accept one while wanting the others.
Under a single id, one ignore-list entry would silence all four — and whoever added it could not say afterwards which one they had accepted. Each flag therefore gets its own rule, its own id and its own consequence, because a shared "a flag is missing" message would tell a reader what is wrong without telling them why it matters.
What is read, and what is not
Only the server's value. Laravel sets sql_mode per connection from the connection's strict
flag, so an application connection can be strict while the server hands something laxer to
everything else that connects — a queue worker with different config, a migration run by hand, a
reporting tool.
A flag is matched exactly, never as a substring: NO_ZERO_DATE is contained in
NO_ZERO_IN_DATE, and a substring check would report a server carrying only the second as if it
carried both.
An empty sql_mode is called out on its own. It is a legal value and a deliberate-looking one, and
reporting it as "one flag missing" would understate a server running with every guard off at once.
A value the server withholds is reported as undetermined with a reason, never as a pass.
Sources
- Server SQL modes — MySQL 8.4
- Server system variables — MySQL 8.4