Neočekávaná chyba: ‚id‘ is ambiguous
- Eda
- Backer | 220
Zdarec.
Mějme databázové schéma mnoha tabulek s rozmanitými vazbami mezi nimi
obsahující mimo jiné tyto dvě tabulky:
Například v presenteru mějme tento kód.
$item = $this->db->table('table1')
->where('id', 5)
->fetch();
Všechno je v pořádku, vyhledáváme podle ID v první tabulce. Může se ale stát, že v našem systému mnoha tabulek budeme chtít začít filtrovat záznamy i podle hodnot z druhé tabulky (což je filozofie Nette\Database, pokud se nepletu :-) ).
$item = $this->db->table('table1')
->where('id', 5)
->where('table2:columnFromTable2', 1)
->fetch();
Všechno na první pohled vypadá ok, skript ale skončí chybou
Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous
,
protože se vygeneroval dotaz:
SELECT `table1`.*
FROM `table1`
INNER JOIN `table2` ON `table1`.`id` = `table2`.`id`
WHERE (`id` = ?) AND (`table2`.`columnFromTable2` = ?)
Prosím tedy o opravu, spočívající v přidání názvu bázové tabulky před vyhledávané parametry, které nemají explicitně uvedenou tabulku jinou.
Jen pro úplnost: verze Nette 2.0.10.
- Tomáš Votruba
- Moderator | 1114
Ahoj, to už by zřejmě bylo příliš magické. Pokud přidáš druhou
tabulku, resp. specifický sloupec z ní, je potřeba odlišit id
v té první. (Nepoužívám NDB, ale v NotORM je praxe stejná.)
$item = $this->db->table('table1')
->where('table1.id', 5)
->where('table2:columnFromTable2', 1)
->fetch();
@enumag: fixed, díky.
Editoval Schmutzka (11. 3. 2013 16:57)
- Eda
- Backer | 220
Schmutka:
Přijde mi naopak magické, nebo spíš trošku nešťastné, že přidáním
podmínky z cizí tabulky dotaz spadne kvůli nějaké původní podmínce.
V ještě horším případě (vyměním podmínku
->where('user1.name', 'Honza')
za
->where('user2.name', 'Honza')
) se bude brát úplně jiný
sloupec než původně, skript naopak nespadne a dokud si nevšimneme
nekonzistence dat v databázi, bude nám takovýto dotaz potajnu dělat
například neplechu v uživatelích. Může to způsobovat nečekané chyby,
proto by měl být výklad toho, co znamená ->where('id', 5)
jednoznačný. Tohle je přesně věc, kterou si myslím, že by měla vrstva
Nette\Database od uživatele odstínit.
To opravdu při každém dotazu preventivně před každý sloupec ve
where
přidáváte název bázové tabulky? Co když dotaz někdy
v budoucnu rozšíříte? A nebo, co hůř…, když budete mít nějaký
systém, který bude where
kritéria nějak dynamicky
přidávat? :-)