PDOException #42000 při relaci na tabulku

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Nich
Člen | 49
+
0
-

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?

jtousek
Člen | 951
+
0
-

Jaký SQL dotaz to generuje?

Nich
Člen | 49
+
0
-
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
+
0
-

Problém byl pravděpodobně v tom, že na tabulku místnost vedly z uživatele dva odkazy.

jtousek
Člen | 951
+
0
-

Verze Nette? Můžeš zkusit aktuální master z GitHubu?

Nich
Člen | 49
+
0
-

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)

hrach
Člen | 1834
+
0
-

!!! Ale to nemeni nic na tom, ze je to chyba! :|

Nich
Člen | 49
+
0
-

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
+
0
-

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)

talpa
Člen | 44
+
0
-

nj, nekdy mam pocit ze databaze tu snad nikdo nepouziva, podle mnozstvi chyb v nette database