Nadgradil sem svoj sistem in namestil MySql 5.7.9 s php za spletno aplikacijo, na kateri delam. Imam poizvedbo, ki je dinamično ustvarjena in pri izvajanju v starejših različicah MySql deluje dobro. Po nadgradnji na različico 5.7 se pojavi ta napaka:
Izraz #1 seznama SELECT ni v klavzuli GROUP BY in vsebuje
neagregiran stolpec 'support_desk.mod_users_groups.group_id', ki je ni funkcionalno odvisen od stolpcev v klavzuli GROUP BY; to je nezdružljivo s sql_mode=only_full_group_by
Upoštevajte stran v priročniku za Mysql 5.7 na temo Načini SQL strežnika.
To je poizvedba, ki mi povzroča težave:
SELECT mod_users_groups.group_id AS 'value',
group_name AS 'text'
FROM mod_users_groups
LEFT JOIN mod_users_data ON mod_users_groups.group_id = mod_users_data.group_id
WHERE mod_users_groups.active = 1
AND mod_users_groups.department_id = 1
AND mod_users_groups.manage_work_orders = 1
AND group_name != 'root'
AND group_name != 'superuser'
GROUP BY group_name
HAVING COUNT(`user_id`) > 0
ORDER BY group_name
Nekaj sem o tem pobrskal na Googlu, vendar only_full_group_by
ne razumem dovolj, da bi lahko ugotovil, kaj moram storiti, da popravim poizvedbo. Ali lahko samo izklopim možnost only_full_group_by
ali moram storiti še kaj drugega?
Sporočite mi, če potrebujete več informacij.
Nastavitev only_full_group_by
lahko poskušate onemogočiti tako, da izvedete naslednje:
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
MySQL 8 ne sprejema NO_AUTO_CREATE_USER
, zato jo je treba odstraniti.
V GROUP BY
bi dodal samo group_id
.
Pri izbiranju stolpca, ki ni del GROUP BY
, je lahko v skupinah več vrednosti za ta stolpec, vendar bo v rezultatih prostora le za eno vrednost. Zato je treba zbirki podatkov običajno natančno povedati, kako naj te več vrednosti pretvori v eno vrednost. Običajno se to stori z zbirno funkcijo, kot so COUNT()
, SUM()
, MAX()
itd. Pravim običajno, ker večina drugih priljubljenih sistemov podatkovnih baz pri tem vztraja. Vendar je bilo v MySQL pred različico 5.7 privzeto obnašanje bolj prizanesljivo, saj se ne bo pritoževalo in nato poljubno izbralo katero koli vrednost! Ima tudi funkcijo ANY_VALUE()
, ki bi jo lahko uporabili kot drugo rešitev tega vprašanja, če bi res potrebovali enako obnašanje kot prej. Ta prilagodljivost ima svojo ceno, saj je nedeterministična, zato je ne priporočam, razen če imate zelo dober razlog, da jo potrebujete. MySQL zdaj iz dobrih razlogov privzeto vklopi nastavitev only_full_group_by
, zato je najbolje, da se nanjo navadite in poskrbite, da bodo vaše poizvedbe v skladu z njo.
Zakaj torej moj preprost odgovor zgoraj? Naredil sem nekaj predpostavk:
group_id
je edinstven. Zdi se razumno, navsezadnje je to ID.
tudi naslov_skupine
je edinstven. To morda ni tako razumna predpostavka. Če temu ni tako in imate nekaj podvojenih group_names
ter nato upoštevate moj nasvet, da dodate group_id
v GROUP BY
, se vam lahko zgodi, da boste zdaj dobili več rezultatov kot prej, ker bodo skupine z istim imenom zdaj imele ločene vrstice v rezultatih. Po mojem mnenju je to bolje, kot da bi bile te podvojene skupine skrite, ker je podatkovna baza po tihem poljubno izbrala vrednost!
Prav tako je dobra praksa, da vse stolpce označite z imenom tabele ali vzdevkom, če je vpletenih več kot ena tabela...
SELECT
g.group_id AS 'value',
g.group_name AS 'text'
FROM mod_users_groups g
LEFT JOIN mod_users_data d ON g.group_id = d.group_id
WHERE g.active = 1
AND g.department_id = 1
AND g.manage_work_orders = 1
AND g.group_name != 'root'
AND g.group_name != 'superuser'
GROUP BY
g.group_name,
g.group_id
HAVING COUNT(d.user_id) > 0
ORDER BY g.group_name
Če ne želite spreminjati trenutne poizvedbe, sledite spodnjim korakom -
vagrant ssh v vašo škatlo
Vnesite: 2: Vnesite: sudo vim /etc/mysql/my.cnf
Pomaknite se na dno datoteke in vnesite A
za vstop v način vstavljanja
Kopirajte in prilepite
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Vnesite esc
za izhod iz vnosnega načina
Vnesite :wq
za shranjevanje in zaprtje programa vim.
Vnesite sudo service mysql restart
za ponovni zagon MySQL.