[pgSQL] Foreign key probleempje
Nu wil ik op studenten een FK maken dat alle records uit vakken_studenten worden verwijderd als er een student wordt verwijderd. Nu krijg ik deze melding:
Code (php)
1
ERROR: there is no unique constraint matching given keys for referenced table "vakken_studenten"
Ik snap zo niet wat deze error in houdt. mijn SQL:
Jouw FK staat precies verkeerdom, je wilt niet op studenten een FK maken, maar op vakken_studenten die verwijst naar de studenten. Vanuit vakken_studenten ga je verwijzen naar het id van de student en die is uniek. Probleem opgelost.
Heeft verder ook niks met PostgreSQL te maken, gaat in iedere database op deze manier.
Dus als ik het goed begrijp maak ik FK's aan op het child-object? Ik wil dus dat als er een student verwijderd wordt, dat dan alle relaties(in dit geval zijn vakken waar hij aan mee doet) worden verwijderd. Ik zal eens kijken, hartelijk dank alvast.
;)
pgFrank schreef op 15.04.2008 14:23:
Ja, een child wijst naar de parent, de parent weet nergens van, ontkent in alle toonaarden dat het childs heeft. Een database keert dan ook geen kinderblijslag uit, er valt voor de parent dus niets te winnen. Alleen maar gezeik aan je kop, zit niemand op te wachten. Ontkennen dus.
;)
;)
een parent doet dus alleen iets als een child er om zeurt:P
Quote:
Jep, dat klopt. Als je ON DELETE CASCADE gebruikt en je verwijdert het records waar de FK's naar verwijzen, zullen alle records met die FK ook verwijderd worden. Andersom is dat natuurlijk niet het geval, als je een record met een FK verwijdert, zal het record waar de FK naar verwijst gewoon blijven bestaan...Dus als ik het goed begrijp maak ik FK's aan op het child-object?
Jurgen schreef op 15.04.2008 14:24:
Nee, zelfs dan niet. Een parent heeft geen enkele relatie met een child, een child heeft een relatie met de parent. Dat is dus enkelvoudig, van de child naar de parent. Nooit andersom.een parent doet dus alleen iets als een child er om zeurt:P
Met CASCADE zorg je er voor dat de child zijn parent in de gaten houdt en daar zelf vervolgacties op neemt. Verwijder je de parent, zal de child zichzelf ook verwijderen. Met RESTRICT zal een child er voor zorgen dat je een parent niet kan verwijderen, maar dat wordt dus door de child afgedwongen en niet door de parent. Een parent heeft tenslotte geen childs, een child heeft een parent.
Raar maar waar.
Code (php)
1
2
2
ERROR: insert or update on table "vakken_studenten" violates foreign key constraint "fk_studenten"
DETAIL: Key (student_id)=(1) is not present in table "studenten".
DETAIL: Key (student_id)=(1) is not present in table "studenten".
Hij violate zijn eigen CONSTRAINT? (ik heb de naam wel even veranderd, fk_vakken bestond nl. al).
SQL:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--Studenten
CREATE TABLE pdotest.studenten
(
id serial NOT NULL,
voornaam character varying,
achternaam character varying,
klas_id bigint,
CONSTRAINT pk_studenten PRIMARY KEY (id),
CONSTRAINT fk_studenten_klassen FOREIGN KEY (klas_id)
REFERENCES pdotest.klassen (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
WITH (OIDS=FALSE);
ALTER TABLE pdotest.studenten OWNER TO jurgen;
-- Koppel tabel studenten en vakken
CREATE TABLE pdotest.vakken_studenten
(
id serial NOT NULL,
vak_id bigint,
student_id bigint,
CONSTRAINT pk_vakken_studenten PRIMARY KEY (id),
CONSTRAINT fk_vakken FOREIGN KEY (vak_id)
REFERENCES pdotest.vakken (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
WITH (OIDS=FALSE);
ALTER TABLE pdotest.vakken_studenten OWNER TO jurgen;
CREATE TABLE pdotest.studenten
(
id serial NOT NULL,
voornaam character varying,
achternaam character varying,
klas_id bigint,
CONSTRAINT pk_studenten PRIMARY KEY (id),
CONSTRAINT fk_studenten_klassen FOREIGN KEY (klas_id)
REFERENCES pdotest.klassen (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
WITH (OIDS=FALSE);
ALTER TABLE pdotest.studenten OWNER TO jurgen;
-- Koppel tabel studenten en vakken
CREATE TABLE pdotest.vakken_studenten
(
id serial NOT NULL,
vak_id bigint,
student_id bigint,
CONSTRAINT pk_vakken_studenten PRIMARY KEY (id),
CONSTRAINT fk_vakken FOREIGN KEY (vak_id)
REFERENCES pdotest.vakken (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
WITH (OIDS=FALSE);
ALTER TABLE pdotest.vakken_studenten OWNER TO jurgen;
De tabel vakken_studenten heeft 2 FK's nodig, eentje naar de studenten en eentje naar de vakken. Het id kun je in deze tabel weggooien, die heb je normaal gesproken niet nodig, een PK op de combinatie van student en vak lijkt mij voldoende.
Ja maar een PK is uniek, een student kan dus meerdere vakken hebben, dan heb je toch een unieke sleutel nodig om elk record te identificeren?
Gewijzigd op 01/01/1970 01:00:00 door Frank -
het kan namelijk ook zo zijn:
Edit: Hoe maak ik dus een PK combinatie aan?
Gewijzigd op 01/01/1970 01:00:00 door Jurgen assaasas
Of wil jij stiekum een waarde toekennen aan de volkomen waardeloze waarde van id? nr. 1 is ouder dan nr. 2 en de volgorde is altijd 1 en dan pas 2! Zo ja, dan ben je fout bezig.
pgFrank schreef op 15.04.2008 15:16:
Prachtig, wat wil je daar dan aan wijzigen? Ziet er goed uit.
Of wil jij stiekum een waarde toekennen aan de volkomen waardeloze waarde van id? nr. 1 is ouder dan nr. 2 en de volgorde is altijd 1 en dan pas 2! Zo ja, dan ben je fout bezig.
Of wil jij stiekum een waarde toekennen aan de volkomen waardeloze waarde van id? nr. 1 is ouder dan nr. 2 en de volgorde is altijd 1 en dan pas 2! Zo ja, dan ben je fout bezig.
Nee dat is niet nodig, maar in dit idee zit er geen PK op de tabel. Wordt er dan automatisch de combinatie gepakt van de 2 om ze scheiden van de andere records?
CONSTRAINT pk_vakken_studenten PRIMARY KEY (vak_id, student_id),
pgFrank schreef op 15.04.2008 15:23:
Je kunt toch een PK maken op basis van deze 2 kolommen?
CONSTRAINT pk_vakken_studenten PRIMARY KEY (vak_id, student_id),
CONSTRAINT pk_vakken_studenten PRIMARY KEY (vak_id, student_id),
Dankje, dat wist ik namelijk niet!
Edit: Ik heb het gewijzigd zoals je zei, alleen werkt het constraint nog steeds niet, wat ik heb gedaan (ik werk met PGadmin3).
1. Wijzig de tabel vakken_studenten.
2. Voeg constraint toe(secundaire sleutel).
3. naam: fk_studenten_vakken.
4. lokale kolom: student_id.
5. reffereert: studenten.id
6. selecteer bij DELETE en UPDATE beide CASCADE
En vervolgens krijg ik weer de error dat hij zijn eigen constraint overschrijdt.
Gewijzigd op 01/01/1970 01:00:00 door Jurgen assaasas
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
CREATE TABLE studenten
(
id serial NOT NULL,
voornaam character varying,
achternaam character varying,
klas_id bigint,
CONSTRAINT pk_studenten PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
CREATE TABLE vakken
(
id serial NOT NULL,
naam TEXT,
CONSTRAINT pk_vakken PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
-- Koppel tabel studenten en vakken
CREATE TABLE vakken_studenten
(
vak_id bigint,
student_id bigint,
CONSTRAINT pk_vakken_studenten PRIMARY KEY (vak_id, student_id),
CONSTRAINT fk_vakken FOREIGN KEY (vak_id)
REFERENCES vakken (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT fk_studenten FOREIGN KEY (student_id)
REFERENCES studenten (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE CASCADE
)
WITH (OIDS=FALSE);
(
id serial NOT NULL,
voornaam character varying,
achternaam character varying,
klas_id bigint,
CONSTRAINT pk_studenten PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
CREATE TABLE vakken
(
id serial NOT NULL,
naam TEXT,
CONSTRAINT pk_vakken PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
-- Koppel tabel studenten en vakken
CREATE TABLE vakken_studenten
(
vak_id bigint,
student_id bigint,
CONSTRAINT pk_vakken_studenten PRIMARY KEY (vak_id, student_id),
CONSTRAINT fk_vakken FOREIGN KEY (vak_id)
REFERENCES vakken (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT fk_studenten FOREIGN KEY (student_id)
REFERENCES studenten (id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE CASCADE
)
WITH (OIDS=FALSE);
De schemanaam mag je er zelf weer even inzetten.
Gewijzigd op 01/01/1970 01:00:00 door Jurgen assaasas
handleiding. Er past maximaal 1 GB aan data in 1 veld, je hebt dus de nodige ruimte tot je beschikking.
Ben wel benieuwd wat voor voor- of achternaam je hebt wanneer dit 1 GB aan data oplevert... ;)
Offtopic: Wanneer je geen beperking wilt opleggen aan de lengte van een string, kun je gewoon het datatype TEXT gebruiken. Dat heeft verder geen negatieve invloed op bv. geheugengebruik. Zie verder de Ben wel benieuwd wat voor voor- of achternaam je hebt wanneer dit 1 GB aan data oplevert... ;)