mysql interne relaties vraag
deze interne relaties opgesteld. alle tabellen zijn met engine MyISAM
ik heb nu bv. :
3 id's in News_item
4 id's in News_category
en in News_itemcat (koppeltabel):
Nu mijn probleem: als ik een categorie wis in News_category (vb 2) dan blijft de relatie in de koppeltabel gewoon bestaan en krijg je corrupte data.
Hoe kan ik dit het best oplossen?
Engine MyISAM wil ik veranderen als het nodig is ;-)
(Als het echt niet kan, dan moet ik overal ingewikkelde query's gaan toepasssen maar ik hou het liever zo simpel mogelijk)
Alvast bedankt,
Hipska
ik heb met PMA 2.9.2 ik heb nu bv. :
3 id's in News_item
4 id's in News_category
en in News_itemcat (koppeltabel):
Nu mijn probleem: als ik een categorie wis in News_category (vb 2) dan blijft de relatie in de koppeltabel gewoon bestaan en krijg je corrupte data.
Hoe kan ik dit het best oplossen?
Engine MyISAM wil ik veranderen als het nodig is ;-)
(Als het echt niet kan, dan moet ik overal ingewikkelde query's gaan toepasssen maar ik hou het liever zo simpel mogelijk)
Alvast bedankt,
Hipska
Gewijzigd op 01/01/1970 01:00:00 door Hipska BE
ALs je geen beschikking hebt over InnoDB, dan zal je het toch met query's moeten doen, maar dat is helemaal niet zo ingewikkeld:
Wanneer je een categorie wist, doe je dat aan de hand van een id die je (neem ik aan) meegeeft in een GET variabele.
Voor de koppeltabel betekend dat:
Edit:
En voor het verwijderen, zal je inderdaad even alle newsitem_id's op moeten halen, dus dat doe je voordat je de bovenstaande DELETE query uitvoerd. Dit kan ook eenvoudig met een subquery:
En voor het verwijderen, zal je inderdaad even alle newsitem_id's op moeten halen, dus dat doe je voordat je de bovenstaande DELETE query uitvoerd. Dit kan ook eenvoudig met een subquery:
Code (php)
1
2
3
2
3
<?php
$sql = "DELETE FROM News_item WHERE id IN(SELECT item FROM News_itemcat WHERE cat=".$_GET['cat'].")";
?>
$sql = "DELETE FROM News_item WHERE id IN(SELECT item FROM News_itemcat WHERE cat=".$_GET['cat'].")";
?>
Gewijzigd op 01/01/1970 01:00:00 door Robert Deiman
die query die je toont had ik ook al in gedachten, maar dacht dat een DB het ook automatisch kon ;)
Hipska schreef op 25.01.2007 10:48:
ik heb de besdhikking over innodb, maar hoe doe ik het precies?
die query die je toont had ik ook al in gedachten, maar dacht dat een DB het ook automatisch kon ;)
die query die je toont had ik ook al in gedachten, maar dacht dat een DB het ook automatisch kon ;)
Zie ook even mijn edit, het kan eenvoudig in zijn geheel met 2 querys. Maar voor de InnoDB engine verwijs ik naar deze tutorial:
http://phphulp.nl/php/tutorials/3/274/
restrict en no action zijn in feite hetzelfde. Restrict zegt: het mag niet. No action wil het laten gebeuren, maar dat kan niet want dan zouden relaties kapot gaan. Dus in beide gevallen gebeurt niks en krijg je een error.
Set null doet heel duidelijk wat ie zegt (als het veld van de source tabel een NULL optie heeft!).
Cascade speelt het spelletje gewoon mee. Als je een rij verwijdert uit de reference tabel, verwijdert ie gewoon alle rijen uit de source tabel die erbij horen (ON DELETE) of hij update alle waarden in de source tabel als het id in de reference tabel wordt aangepast.
Het is veel zoek en probeer en denk werk om een goed InnoDB model te maken, maar als ie af is heb je een mooi systeempje. Subqueries, bah, nooit meer nodig. Zet je ON DELETE op CASCADE en alle bijbehorende rijen uit welke tabel dan ook worden automatisch verwijderd.
Artikel is handig ja
Mocht je er, na het lezen van dit artikel, niet uitkomen: Stuur me ff een PB'tje, dan kan ik evt. het artikel aanpassen als dat nodig. InnoDB is inderdaad wat je nodig hebt.
ik neem idd de optie innodb ;)
--- EDIT ---
Ik ben er nog niet helemaal uit. Ik heb nu deze code:
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--
-- Tabel structuur voor tabel 'News_category'
--
CREATE TABLE News_category (
id int(11) NOT NULL auto_increment,
naam varchar(255) NOT NULL,
datum datetime NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id),
UNIQUE KEY naam (naam)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_comment'
--
CREATE TABLE News_comment (
id int(11) NOT NULL auto_increment,
titel varchar(255) NOT NULL,
bericht text NOT NULL,
datum datetime NOT NULL,
item int(11) NOT NULL,
auteur int(11) NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_item'
--
CREATE TABLE News_item (
id int(11) NOT NULL auto_increment,
titel varchar(255) NOT NULL,
bericht text NOT NULL,
datum datetime NOT NULL,
auteur int(11) NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_itemcat'
--
CREATE TABLE News_itemcat (
item int(11) NOT NULL,
categorie int(11) NOT NULL,
UNIQUE KEY itemcategorie (item,categorie)
) ENGINE=INNODB COMMENT='Koppeltabel item <-> categorie';
-- Tabel structuur voor tabel 'News_category'
--
CREATE TABLE News_category (
id int(11) NOT NULL auto_increment,
naam varchar(255) NOT NULL,
datum datetime NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id),
UNIQUE KEY naam (naam)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_comment'
--
CREATE TABLE News_comment (
id int(11) NOT NULL auto_increment,
titel varchar(255) NOT NULL,
bericht text NOT NULL,
datum datetime NOT NULL,
item int(11) NOT NULL,
auteur int(11) NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_item'
--
CREATE TABLE News_item (
id int(11) NOT NULL auto_increment,
titel varchar(255) NOT NULL,
bericht text NOT NULL,
datum datetime NOT NULL,
auteur int(11) NOT NULL,
edit timestamp NULL default NULL on update CURRENT_TIMESTAMP,
ip varchar(15) NOT NULL default '000.000.000.000',
PRIMARY KEY (id)
) ENGINE=INNODB;
-- --------------------------------------------------------
--
-- Tabel structuur voor tabel 'News_itemcat'
--
CREATE TABLE News_itemcat (
item int(11) NOT NULL,
categorie int(11) NOT NULL,
UNIQUE KEY itemcategorie (item,categorie)
) ENGINE=INNODB COMMENT='Koppeltabel item <-> categorie';
ik wil nu de tabellen koppelen volgens de manier op onderstaand PDF bestand:
http://idisk.mac.com/hipska-Public/Selecta_News.pdf
als er een categorie verwijderd word, dan moeten alle koppelitems wissen, maar niet de bijhorende items (omdat een item meerdere categoriën kan bevatten)
Gewijzigd op 01/01/1970 01:00:00 door Hipska BE
nu nog 1 vraagje, wat zou ik best doen met nieuwsberichten die van een user zijn die verwijderd word?
Quote:
als er een categorie verwijderd word, dan moeten alle koppelitems wissen
Dat betekend dus dat je in je koppeltabel een foreign key hebt die wijst naar categorie, met als eigenschap "ON DELETE CASCADE". Je wilt dan uiteraard niet dat de artikelen verwijderd worden, maar dat gebeurt ook niet als je het model goed opstelt:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
CREATE TABLE News_itemcat (
item int(11) NOT NULL,
categorie int(11) NOT NULL,
UNIQUE KEY itemcategorie (item,categorie)
FOREIGN KEY(item) REFERENCES News_item(id) ON DELETE CASCADE,
FOREIGN KEY(categorie) REFERENCES News_category(id) ON DELETE CASCADE
) ENGINE=INNODB COMMENT='Koppeltabel item <-> categorie';
item int(11) NOT NULL,
categorie int(11) NOT NULL,
UNIQUE KEY itemcategorie (item,categorie)
FOREIGN KEY(item) REFERENCES News_item(id) ON DELETE CASCADE,
FOREIGN KEY(categorie) REFERENCES News_category(id) ON DELETE CASCADE
) ENGINE=INNODB COMMENT='Koppeltabel item <-> categorie';
(ik heb deze SQL niet geprobeerd). Het idee is als volgt:
- Leg een relatie op "item", deze wijst naar News_item->id. Als er een News_item wordt verwijderd, wordt deze ook automatisch uit de koppeltabel verwijderd. Je dwingt op deze manier af dat News_items in je koppeltabel ook echt bestaan.
- Leg een relatie op "categorie", deze verwijst naar News_category->id. Als er een News_categorie wordt verwijderd, wordt deze ook automatisch uit de koppeltabel gegooid. News_items worden hierdoor niet geraakt.
Quote:
nu nog 1 vraagje, wat zou ik best doen met nieuwsberichten die van een user zijn die verwijderd word?
Normaal gesproken verwijder je een user niet maar de-activeer je hem. Als een user echt verwijderd wordt horen zijn berichten ook verwijderd te worden, dit kan echter inconsistente gegevens opleveren (denk bijv. aan een forum, van threads waarin de gebruiker actief was). Overweging: userid op NULL zetten, user de-activeren, alles verwijderen....de keuze is echt afhankelijk van je systeem :)
ipv userid user nickname meegeven? is dit ook een mogelijkheid?
Hipska schreef op 25.01.2007 14:37:
ipv userid user nickname meegeven? is dit ook een mogelijkheid?
Geef een id mee, dat werkt sneller en beter en minder kans op fouten.
Een nickname is aan een id gekoppeld, haal gewoon die ID op en gebruik die.
maar als user verwijderd is, dan is het niet meer gekoppeld aan id.
Wat je óók nog kunt overwegen is om hem NULL te maken als de user verwijderd word (ON DELETE SET NULL), met een left join kun je dan toch alle reacties ophalen, je mist dan alleen een gebruikersnaam...
dus de categorieën selecteren bij een nieuwsbericht toevoeging is geen probleem, ook niet bij het editten trouwens.
Maar als iemand nu een categorie wil verwijderen van een newsitem, hoe doe ik dat dan het best? ik krijg alle geselecteerde checkboxen binnen via een array
Quote:
Niet verwijderen. Dat zou mijn keuze zijn.Maar als iemand nu een categorie wil verwijderen van een newsitem, hoe doe ik dat dan het best?
Wanneer je de boel niet meer wilt weergeven, dan pas je gewoon de status van een categorie aan. Met verwijderen zul je ook alle gekoppelde gegevens moeten verwijderen of moeten accepteren dat je niets meer hebt aan deze gegevens. Het verband raak je tenslotte kwijt.
Vandaar mijn keuze om vrijwel nooit iets weg te gooien, maar gewoon de status aan te passen. Een paar miljoen records staan zelden in de weg, maak je daar dus niet al te druk over. Helaas heeft MySQL wat moeite met het toepassen van meerdere indexen, in MySQL zou je dus tegen performance-problemen aan kunnen lopen die zijn gerelateerd aan indexen.
Maar zorg eerst maar eens dat je dat probleem krijgt (paar miljoen records), dan weet je tenminste zeker dat je een succesvol systeem hebt gebouwd.
En als oplossing kun je natuurlijk altijd PostgreSQL gaan gebruiken...
het nieuwsitem hoort niet meer tot een bepaalde categorie, en dan moet dat vinkje weg,
mijn vraag is, hoe zet ik dat dan om in de DB?
zie: http://casteleyn.no-ip.info:8080/~Hipska/Selecta/news/index.php?type=item&act=edit&id=3
het nieuwsitem hoort niet meer tot een bepaalde categorie, en dan moet dat vinkje weg,
mijn vraag is, hoe zet ik dat dan om in de DB?
zie: http://casteleyn.no-ip.info:8080/~Hipska/Selecta/news/index.php?type=item&act=edit&id=3
Gewoon een kolom 'status' toevoegen aan de tabel News_itemcat en daar een bool inzetten, true of false. Klaar ben je.
ik krijg de geselecteerde cat's binnen op een array...
Hipska schreef op 13.02.2007 21:55:
Hoe je de boel ontvangt, heeft niets te maken met de manier waarop je gegevens opslaat. Dat zijn echt 2 totaal verschillende dingen.dan heb je nog niet geantwoord hoe ik het dan het best doe,
ik krijg de geselecteerde cat's binnen op een array...
ik krijg de geselecteerde cat's binnen op een array...
Wat jij ontvangt, zijn de waardes die zijn aangevinkt. Die sla je op of je zet de status op 'true'. De overige waardes in de database die betrekking hebben op dit item, zet je op status 'false'.