20. januar 2010 - 18:01Der er
18 kommentarer og 1 løsning
Hjælp til simpel kode
Hej
Jeg har lavet en relation mellem 2 entiteter.
1 - artikel Har følgende attributer; artikel_id overskrift emne (fungerer som Foreign Key, og kan have en værdi som svarer til emne_id i entiteten 2 - emne) forfatter dato
2 - emne Har følgende attributer; emne_id (emne_id'en skal så karakterisere artiklens emne, eks. mad)
Hvis dette indtil videre ser nogenlunde fornuftigt ud, kunne jeg godt tænke mig at høre et bud på en SQL/php kode, hvorved jeg kunne få emne attributten (den Foreign Key) til at kalde på emnet mad, i entiteten emne?
Er det nogenlunde rigtigt? Eller? Hjælp påskønnes meget!
så går vi fra SELECT column_name(s) FROM table_name1 INNER JOIN table_name2 ON table_name1.column_name=table_name2.column_name til SELECT * FROM artikel INNER JOIN emne ON artikel.emne=emne.emne_id
men der skal nok en WHERE xxx=yyy (fx forfatter='Peter') med for at vælge en speciel type.
og så lad være med at kalde et felt (emne) for det samme som en tabel - det vil bare forvirre dig, når du læser koden.
claes57, jeg er ikke uenig i hvad du siger, men det er ikke et akkurat svar paa spoergsmaalet foreign key. Foreign key er kun indirekte relateret til join, det er primaert et redskab til at sikre referentiel integritet, sikre at dataerne i tabellerne svarer til hinanden. Hvis larsjansen vil at tabellen Emne indeholder alle de emner der er 'tilladte' saa skal han sikre sig mod at brugere i tabellen artikel indsaetter et emne_id som ikke findes i tabellen Emne. Syntaksen er:
Hvis larsjansen vil udvide samlingen af emner saa skal han foerst fylde de nye emner i Emne, derefter kan man i Artikel lave referencer til disse emner. Hvis nogen af uvidenhed eller som fejl proever at indsaette en emnereference i Artikel som ikke findes i Emne saa afviser systemet det direkte.
Man kan sagtens lave Join soegninger uden der er foreign keys, men med de rette foreign keys paa plads vil soegningerne give de forventede resultater.
Sikke noget jeg har rodet mig ud i :) Jeg er ikke sikker på jeg forstår det :) Forstår knap hvad jeg selv skrev.
Nuvel, jeg havde ellers allerede createt et table;
CREATE TABLE `artikel` (
`artikel_id` INT ( 6 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , `overskrift` VARCHAR (32) CHARACTER SET latin1 COLLATE latin1_danish_ci NOT NULL, `emne` VARCHAR ( 32 ) CHARACTER SET latin1 COLLATE latin1_danish_ci NOT NULL , `forfatter` VARCHAR ( 32 ) CHARACTER SET latin1 COLLATE latin1_danish_ci NOT NULL , `dato` DATE NOT NULL
larsjansen, enig at fk skal referere til emne_id. Men saa skal i Artikel tabellen datatypen for emne vaere den samme som for emne_id nemlig INT. Jeg sad lige og puslede med det samme. Spoergsmaal, hvilken database program bruger du? Det ser ud til at mysql slet ikke stoetter foreign key. Jeg laeste at man skal bruge Engine=InnoDB og det har jeg gjort i nedenstaaende, men alligevel kan jeg indsaette vaerdier der ifoelge den foreign key ikke er tilladte. For oejeblikket arbejder jeg i Access og der er der fuld support.
Men jeg lavede, for test, en tabel LarsEmne og en tabel LarsArtikel. Det med character set har jeg ingen forstand paa saa det sprang jeg over, men her er mine skripts:
CREATE TABLE LarsEmne(emne_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, emne VARCHAR(32)) ENGINE=InnoDB;
CREATE TABLE LarsArtikel(artikel_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, overskrift VARCHAR(32), emne INT, forfatter VARCHAR(32), dato DATE, FOREIGN KEY(emne) REFERENCES LarsEmne(emne_id)) ENGINE=InnoDB;
Saa satte jeg tre emner ind i LarsEmne:
INSERT INTO LarsEmne VALUES('', 'Mad og drikke'); INSERT INTO LarsEmne VALUES('', 'Ryge og rejse'); INSERT INTO LarsEmne VALUES('', 'Rende og hoppe');
Det danner saa emne_id numre 1, 2, og 3. Saa skulle den foelgende insert i LarsArtikel afvises, men det goer min mysql ikke:
INSERT INTO LarsArtikel VALUES('', 'overskrift1', 4, 'forfatter1', '2010-1-18');
Herligt stykke arbejde Christian! Det stter jeg pris på.
Jeg er først i dag startet med at rode med databaser, så jeg fatter ikke helt hoved og hale i de forskellige ting.
Jeg har PT. ikke planer om at implementere databasen, og køre den, da jeg blot skal illustrere formålet med databasen, og syntaksen bag... Jeg er slet ikke kommet til at skulle sætte databasen op endnu, det ved jeg ikke hvordan man gør, har heller ikke tid til det eftersom denne opgave afleveres fredag morgen.
Men umiddelbart ser din kode fin ud, jeg håber jeg er i stand til at forklare den i praksis :)
Naa, det er noget du skal snakke dig fra. Saa er "referentiel integritet" et godt "buzzword." I dit tilfaelde er der en en-til-mange relation mellem Emne og Artikel: Et emne kan forekomme i mange artikler, men en artikel kan kun have et emne, og ydermere skal Artiklens emne vaere et der forekommer i Emne. Med den foreign key, ligesom database-softwaren ikke maa tillade at et emne bliver indsat i Artikel der ikke er i Emne saa skal softwaren ogsaa soerge for at et emne ikke kan slettes (eller aendres) i Emne saa laenge der er artikler i Artikel med det emne. Designeren af databasen kan bestemme, hvis et emne skal slettes, om brugeren foerst skal slette artikler med emnet et for et og saa slette emnet i Emne eller om "cascade" er tilladt. Det vil sige at softwaren sletter emnet i Emne og samtidig sletter alle artikler med det emne. Saa hedder koden "FOREIGN KEY(emne) REFERENCES Emne(emne_id) ON DELETE CASCADE". Paa den maade bevares den referentielle integritet ogsaa. Der er ogsaa en ON UPDATE CASCADE saaledes at en aendring i et emne resulterer i en aendring af emnet i alle relevante artikler.
Under alle omstaendigheder held og lykke med din eksamen (eller hvad det er.)
Jeg oprettede dette som svar idet du angiver at jeg har svaret paa hvad du spurgte om. Saa afslutter du maaske spoergsmaalet.
Lige en ting mere, det slog mig at du i indlaeg #6 sagde: "Jeg vil gennem en SQL syntaks, hente oplysninger om hvilket emne en artikel er, via entiteten artikel." Ved at oprette en foreign key henter du ikke nogen oplysninger. Oplysningerne henter du med dit join query (som claes67 forklarede.) Foreign key laver du for at sikre at tabellerne svarer til hinanden saaledes at oplysningerne er paa plads naar der skal soeges. Hvis der ikke var forign key fra Artikel til Emne kunne du risikere at nogen havde puttet et emne i Artikel der ikke bestod i Emne saaledes at en soegning paa det emne ikke ville give noget resultat.
Hvis du vil forvirres (ellers skip de foelgende) saa er der en anden metode til at opnaa det samme, med JOIN. Den metode er tit mere overskuelig naar det kommer til komplicerede soegninger der involverer flere tabeller:
SELECT forfatter, emne FROM artikel JOIN emner ON artikel.emne_id = emner.emne_id
Begge disse queries giver dig en komplet oversigt over alle artikler og deres emner. Hvis du vil have en mere begraenset oversigt, for eksempel over artikler af forfatteren Klodshans, skriver du enten:
SELECT forfatter,emne FROM artikler,emner WHERE artikler.emne_id = emner.emne_id AND forfatter = 'Klodshans'
eller:
SELECT forfatter, emne FROM artikel JOIN emner ON artikel.emne_id = emner.emne_id WHERE forfatter = 'Klodshans'
Og vi snakker stadig teori. Hvis du vil benytte en bestemt database skal du holde regning med de forskellige begraensninger. For eksempel Access vil ikke acceptere JOIN men insistere paa at specificere INNER JOIN, LEFT JOIN, etc. Der findes forskellige JOIN typer alt eftersom precis hvad man vil opnaa. I simple tilfaelde som dit er det INNER JOIN eller blot JOIN som de fleste database systemer accepterer. Jeg naevner det blot saa det ikke kommer bag paa dig hvis nogen til eksamen begynder at snakke om INNER JOIN.
SELECT forfatter, emne FROM artikel JOIN emner ON artikler(!).emne_id = emner.emne_id
?
Da den nu hedder artikler i stedet for artikel. I know, forvirrende at jeg lavede det om. Men var nødt til at omdøbe entiteterne så jeg nemmere kunne holde styr på hvad der var entitet og attribut
Nu begynder det at blive grove loejer - du vil have mig til at taenke saa jeg risikerer hovedpine og at finde boeger frem der var daekket af stoev saa jeg risikerer at faa astma. Men ....
Lad os forestille os at du havde lavet en database der bestod af en tabel med denne struktur (jeg forkorter "forfatter" til "f" for at have det paa en linie):
artikel: id emne f-fornavn, f-efternavn, f-bopael gade nr by
altsaa vaerdien af feltet f-bopael er selv en tabel med tre kolonner, en saakaldt gentagende gruppe.
Denne database ville overhovedet ikke vaere normaliseret. Men hvis du laver en saerskilt tabel for adresse med tre kolonner gade, nr, og by (og maaske en fjerde kolonne for adresse_id) og saa laver en fremmednoegle fra forfatter til adresse saa er du foerste normalform.
Men lad os nu antage at der er en forfatter der hedder Klodshans Jensen som har skrevet syv artikler. For de syv artikler siger tabellen ikke alene at Klodshans er forfatter men ogsaa at han hedder Jensen til efternav. Oplysningen at Klodshans og Jensen hoerer sammen forekommer derved adskillige gange, kaldet redundancy (maaske noget andet paa dansk). At det er spild af database plads er det mindste problem, det giver ogsaa risiko for ved en artikel at komme til at skrive Klodshans Hansen, og saa der der fejl i databasen. Saa man kan fjerne redundancyen ved at lave en saerskilt tabel for forfatter med tre kolonner, forfatter_id, fornavn, og efternavn. Tabellen artikel indeholder saa kun forfatter_id med fremmednoegle til forfattertabellen. Saa indeholder databasen kun paa et sted oplysning om en forfatters navn og efternavn.
Afhaengig af hvad slags redundancy man fjerner (teorien pensler det ud) kommer man til anden eller tredje normale. Saa bestaar der ogsaa en Boye-Codds normale og en fjerde og en femte normale hvor forskellige typer multiple- og kombinerede redundancies fjernes. Men det er special kendskab som jeg vil anse ligger udenfor den nuvaerende opgave.
Hvis du skal fortaelle hvilken normale din database er i saa vil jeg foreslaa svaret: "Tredje normale fordi der ikke er nogen gentagne grupper (tabeller i tabeller) og al redundancy er fjernet." Og saa kan du, hvis du vil vaage dig ud paa det dybe vand, sige: "Fordi databasen er saa begraenset og ukompliceret tilfredsstiller den i princippet ogsaa Boye-Codds normale og fjerde og femte normale."
Tilfoejelse: I det foregaaende indlaeg smuttede "gade nr by" for langt til venstre. De skulle have staaet under f-bopael.
Og saa ville jeg have skrevet, men glemte det, at antagelsen er at din forfatter kolonne i artikel indeholder et enkelt navn paa forfatter fordi fokus er paa artikel og ikke paa forfatter. Hvis du vil udvide databasen saa du fortaeller mere om forfatterne maa du, for at forblive i 3. normale, lave en saerskilt tabel for forfatter og bruge forfatter_id i tabellen artikel og med fremmednoegle til forfatter tabellen.
Hehe, ja det er noget af det gode gamle jeg fandt frem :)
"Hvis du skal fortaelle hvilken normale din database er i saa vil jeg foreslaa svaret: "Tredje normale fordi der ikke er nogen gentagne grupper (tabeller i tabeller) og al redundancy er fjernet.""
Tabeller i tabeller? Den forstår jeg ik. Men ellers giver alt det andet du skrev god mening!
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.