PDOException #42000 při relaci na tabulku
- Nich
- Člen | 49
Tabulky si vytvářím tímto skriptem:
CREATE TABLE uzivatel
(
ID_uzivatel INT(11) NOT NULL,
ID_oddeleni INT(11) NOT NULL,
ID_mistnost INT(11) NOT NULL,
jmeno Varchar(50) NOT NULL,
prijmeni Varchar(50) NOT NULL
);
ALTER TABLE uzivatel ADD PRIMARY KEY (ID_uzivatel,ID_oddeleni,ID_mistnost);
ALTER TABLE uzivatel MODIFY COLUMN ID_uzivatel INT NOT NULL AUTO_INCREMENT;
-- Table mistnost
CREATE TABLE mistnost
(
ID_mistnost INT(11) NOT NULL,
ID_oddeleni INT(11) NOT NULL,
oznaceni Varchar(30) NOT NULL
);
ALTER TABLE mistnost ADD PRIMARY KEY (ID_mistnost,ID_oddeleni);
ALTER TABLE mistnost MODIFY COLUMN ID_mistnost INT NOT NULL AUTO_INCREMENT;
-- Table oddeleni
CREATE TABLE oddeleni
(
ID_oddeleni INT(11) NOT NULL,
nazev_oddeleni Varchar(30) NOT NULL,
popis Varchar(100)
);
ALTER TABLE oddeleni ADD PRIMARY KEY (ID_oddeleni);
ALTER TABLE oddeleni MODIFY COLUMN ID_oddeleni INT NOT NULL AUTO_INCREMENT;
-- Create relationships section -------------------------------------------------
ALTER TABLE mistnost ADD CONSTRAINT Patri FOREIGN KEY (ID_oddeleni) REFERENCES oddeleni (ID_oddeleni) ON DELETE CASCADE ON UPDATE CASCADE
;
ALTER TABLE uzivatel ADD CONSTRAINT Obyva FOREIGN KEY (ID_mistnost) REFERENCES mistnost (ID_mistnost) ON DELETE CASCADE ON UPDATE CASCADE
;
ALTER TABLE uzivatel ADD CONSTRAINT Obyva_ FOREIGN KEY (ID_oddeleni) REFERENCES mistnost (ID_oddeleni) ON DELETE CASCADE ON UPDATE CASCADE
;
A vůbec nechápu jak je možné, že tohle funguje bez problému:
$mistnost = $this->mistnost->findOneBy(array("ID_mistnost" => $id));
echo $mistnost->oddeleni->nazev_oddeleni;
Ale tohle:
$user = $this->uzivatel->findOneBy(array("ID_uzivatel" => $id));
echo $user->mistnost->ID_mistnost;
vyhodí chybu: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‚IN (2))‘ at line 1
Jinak k $user->jmeno
se dostanu
v pohodě… Netušíte někdo kde by mohla být chyba?
- Nich
- Člen | 49
SELECT *
FROM `mistnost`
WHERE ( IN (1))
public function findBy(array $by)
{
return $this->getTable()->where($by);
}
public function findOneBy(array $by)
{
return $this->findBy($by)->limit(1)->fetch();
}
Jinak pokud sem se kouknul na tu funkční relaci z místnosti do oddělení tak ten SQL příkaz vypadá takhle:
SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL AND TABLE_NAME = 'mistnost'
SELECT *
FROM `oddeleni`
WHERE (`ID_oddeleni` IN (1))
Nechápu proč se nejde z tabulky uzivatel dostat do tabulky mistnost.
Editoval Nich (10. 10. 2012 12:46)
- Nich
- Člen | 49
Problém je vyřešen, šlo o to, že šli oba odkazy z uzivatel na mistnost. Po smazani sloupce ID_oddeleni je to už v pohodě. On tam je vlastně navíc, protože v tabulce místnost je taky odkaz na oddělení… bohužel mi to takhle vygeneroval ToadData Modeler a pěkně mi tím zavařil :-)
Editoval Nich (10. 10. 2012 16:51)
- Nich
- Člen | 49
No něco je špatně, protože jsem do aplikace dodělal jeden dynamickej select, a výpis tabulky, který je pod formulářem zase vyhazuje: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‚IN (1, 2))‘ at line 1
Stáhl jsem si i nové nette 2.0.6-PHP5.3. Nic se nezměnilo.
Hrubý výpis z laděnky:
SQL ▼
SELECT *
FROM `mistnost`
WHERE ( IN (1, 2))
...\IIS\libs\Nette\Database\Table\Selection.php:517 source ► Nette\Database\Connection-> queryArgs (arguments ▼)
$statement "SELECT * FROM `mistnost` WHERE ( IN (?))" (40)
$params
array(1) ▼ [
0 => array(2) ▼ [
0 => 1
1 => 2
]
]
...\IIS\libs\Nette\Database\Table\Selection.php:467 source ► Nette\Database\Table\Selection-> query (arguments ▼)
$query "SELECT * FROM `mistnost` WHERE ( IN (?))" (40)
...\IIS\libs\Nette\Database\Table\ActiveRow.php:304 source ► Nette\Database\Table\Selection-> offsetExists (arguments ▼)
$key 1
...\IIS\libs\Nette\Database\Table\ActiveRow.php:250 source ► Nette\Database\Table\ActiveRow-> getReference (arguments ▼)
$table "mistnost" (8)
$column "ID_mistnost" (11)
Je to přístup z tabulky uzivatel do mistnosti. Z místnosti do oddělení to opět funguje. Takže už fakt nevím co s tím.
- Nich
- Člen | 49
Tak už jsem na to konečně přišel! Problém byl v tom, že tabulka byla špatně nakonfigurovaná. Pokud se v tabulce vyskytuje více než 1 primární klíč, relace nefungují.
ALTER TABLE uzivatel ADD PRIMARY KEY (ID_uzivatel,ID_oddeleni,ID_mistnost);
//stačí opravit na:
ALTER TABLE uzivatel ADD PRIMARY KEY (ID_uzivatel);
ALTER TABLE uzivatel ADD INDEX (ID_oddeleni,ID_mistnost);
Píšu to sem, kdyby si někdo náhodou lámal hlavu stejně jako já :D
Editoval Nich (11. 10. 2012 13:52)