Jackery IFA Fireplace
Mobile

SQL Wie Datenbank aufbauen ?

rony

Commodore Pro
🎅Rätsel-Elite ’10
Registriert
Jan. 2007
Beiträge
4.987
Hallo,

ich brauch mal gedanklich einen kleinen anstoß :/

ich baue eine Webseite in der Leute Tagesordnungen für Disskusionen erstellen können.

Dabei können allerhand leute Tagesordnungspunkte einsenden, welche öffentlich einsehbar sind - regestrierte benutzer, können sich dann aus diesen punkten Tagesordnungen "zusammenklicken".
Bzw. so soll es werden.

Dabei weiß ich gerade nicht, wie ich die Datenbnak anlegen soll, bzw. wie gespeichert werden soll.

So hat jeder eintrag eine ID, jeder Benutzer hat eine ID und jede TO hat eine ID.

Nun soll man die Tagesordnungen einem Benutzer zuteilen, un TO-Punkte einer TO, oder eben einer anderen....
Also jeder TO-Punkt darf auch in anderen TOs auftauchen...

Ich hoffe mal, ich konnte es verständlich schreiben ^^...
 
Und wie gestaltet sich der Gedankensanstoss nun genau?

Ich kann dir z.B sagen, dass du - umso komplexer eine DB aufgebauen werden soll - dich mit der Normalisierung auseinander setzen solltest: http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)

Nachdem du dich genau festgelegt hast, welche Informationen in deiner DB gespeichert werden sollen, kannst du Testweise im Access die einzelnen Tabellen und Relationen aufbauen. (Edit: Siehe Post oben ;) )

Im Access kannst du dann die Tabellen anzeigen und wirst feststellen, ob und wo realisiert werden muss. (Du musst das nicht zwingend im Access machen, aber dort ist es relativ einfach.)

Gruss David
 
Tabellen:

-Benutzer
-Benutzer/Listenzuordnung (nur beide IDs der Tabellen)
-Listen
-Tagesordnungspunkte
-TOinListen (auch wieder die IDs. Evtl mit Sortierungsnummer)

Das wäre mal ein Ansatz meines Erachtens nach
Ergänzung ()

Also immer für die Tabellen noch zwischentabellen für die m:n-Zuordnung
 
Kennst du dich mit relationalen Datenbanken und deren Normalformen (http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)) aus? Es existiert verschiedene Stufen von Normalisierung alle mit dem Ziel Redundanz der Daten zu vermeiden.

Für gewöhnlich geht man hin und zeichnet sich das ganze grob auf. Es geht erst einmal darum welche Objekte gibt es, für diese müssen Tabellen angelegt werden, wie sind die Beziehungen untereinander d.h. evtl. müssen da Beziehungstabellen erstellt werden und dann die Frage wie sind die Beziehungen mengenmäßig (1:1, 1:n, n:m). Abhängig davon wie diese Beziehung aussieht benötigst du zwingend eine Zwischentabelle (n:m) oder kannst sie wie unten im Comment Beispiel in die eigentliche Tabelle integrieren.

Die Benamung von Tabellen und deren Felder bzw. generell Programmcode passiert im Regelfall auf Englisch, du kannst aber auch deutsche Namen verwenden, da wird dir keiner Weh tun ;) (ist nur nicht good style).

Beispiel:
Table: Comments
PK ID (hast du so definiert)
FK UserID
FK Tagesordnungspunkt (besser Name sollte vlt. gefunden werden -> Englisch)
Comment

Die FKs sind alles PKs aus anderen Tabellen, deswegen bezeichnet man sie als FK (PK = Primary Key, FK = Foreign Key).

In dem Beispiel besteht ein Kommentar aus dem eigentlichen Text, einer eindeutigen ID und hat eine Zuweisung zur Person der ihn erstellt sowie den TPO wo er dazu gehört.

Bei den TPOs gehst du genauso vor. Du hast deine Tabelle mit allen TPOs und zu diesen eine Relation Tabelle welche eine TPO Ansammlung ist.

[Nachtrag]
Als Eckpunkt sage ich mal eine Datenbank sollte mindestens bis zur dritten Normalform normalisiert sein d.h. bis dahin lies dich auf alle Fälle ein und arbeite damit bis du es verstehst.

Ich möchte dich noch einmal drauf hinweisen, dass es wichtig ist dir erst einmal zu überlegen welche Objekte du überhaupt anlegen/speichern möchtest. Mit Verständnis von Normalform und ERM, was du dir aneignen musst, kommt das Datenbankdesign dann fast von alleine.
 
Zuletzt bearbeitet:
die tabellen für die benutzer und die TO-Punkte hab ich schon seit einiger zeit fertig...

Jetzt sollte es an die tabelle für die TOs gehen.... aber ich glaube, ja.... so manche sachen dämmern mir gerade.
An einen zwischenschritt hatte ich garnicht gedacht. Bzw, eine extra tabelle die nur für die zuordnungen verantwortlich ist.

Das ist echt eine gute idee :)

Ich senniere da mla etwas drüber - ggf. schreibe ich wenn ich auf probleme stoße ^^
 
so... ich habe da gerade ein brett vorm kopf...

ich habe nun eine tabelle - welcje ich "zusammen" nennen.
In dieser speicher ich jeweils die ID der Tagesordnungen, Benutzer und Tagesordnungspunkte

[TABLE="width: 500"]
[TR]
[TD]ID[/TD]
[TD]TO_ID[/TD]
[TD]B_ID[/TD]
[TD]TP_ID[/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]3[/TD]
[TD]5[/TD]
[TD]12[/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]3[/TD]
[TD]5[/TD]
[TD]4[/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]4[/TD]
[TD]4[/TD]
[TD]23[/TD]
[/TR]
[/TABLE]

So sieht das dann aus....

Nun gibt es in meiner kleinen beispeiel tabelle, zwei Tagesordnungen - Nr. 3 und 4.

Jetzt ist es so, dass ich mit MySQL schon alle Daten aus den jeweiligen Tabellen heraus bekomme:

SELECT * FROM `tagesordnung` , `zusammen` , `benutzer` , `tagesordnungspunkte` WHERE `del` = 0
AND `benutzer`.`ID` = `zusammen`.`B_ID`
AND `tagesordnung`.`ID` = `zusammen`.`TO_ID`
AND `tagesordnungspunkte`.`ID` = `zusammen`.`TP_ID`

Aber natürlich werden mir nun alle Tagesordnungen angezeigt.

Ich denke mal, ich muss es nun in PHP lösen, dass diese zusammengefasst, angezeigt werden.
Hat dort jemand einen kleinen tipp :)
 
Bei dieser Tabelle entfernt man für gewöhnlich die ID da die drei Felder TO_ID, B_ID und TP_ID ja eindeutig den Eintrag beschreiben? Ist dies der Fall sollten die drei Felder zusammen auch den Primary Key stellen. Nenne diese Tabelle BITTE anders, Zusammen ist absolut nichtssagend.

Deine SQL Syntax ist interessant. Das ist Pre-T-SQL Syntax oder? Funktioniert das so überhaupt in MySQL? Schau dir bitte die Verwendung von INNER JOINs an. Man Selektiert auf eine Tabelle, alle anderen werden über die jeweilig notwendige FK_PK Relation gejoint. Damit fallen die meisten WHERE Klausen auch raus.

Was ist dein Problem mit dem erhaltenden Record Set (bitte ändere unbedingt die Syntax auf JOINs)? Willst du auf spezielle Werte filtern? Was willst du in PHP zusammen fassen?
 
moment, moment ^^

das sind jetzt ein paar vokabeln, die ich nicht kenne...

Es mag sein, dass es eine alte Syntax ist... hatte es so mal vor jahren gelernt... ist aber schon sehr lange her ^^
Funktionieren tut das auf jeden fall.

Also mein problem ist gerade, dass TO nr. 3 nun zweimal angezeigt wird. ich möchte das aber nur einmal anzeigen lassen - weil sie exestiert ja auch nur einmal, aber es gibt eben zwei einträge dafür in der "zusammen" tabelle (ja, der name ist etwas unglücklich :/ ).

Konkret soll da:

Name der TO | Benutzername | anzahl der Einträge

stehen.
 
Ok. Ich weiß was du grundlegend möchtest. Die Frage ist jetzt: Was soll dir die Abfrage grundlegend geben d.h. was ist die Tabelle mit den primären Daten die du haben möchtest? Möchtest du die Einträge aus Zusammen anzeigen, die vorhandenen Tagesordnung oder Benutzer?

Das dies so noch funktioniert grenzt fast an ein Wunder ;). Man hat es abgeschafft da es einfach zu Problemen führt da den Überblick zu behalten (wenn ich mich recht erinnere). Tatsächlich ist es jetzt das Verständnisproblem was ich habe.

Schau dir bitte erst einmal korrekte T-SQL Syntax an. Fang mit einfachen SQL SELECTs (http://www.w3schools.com/sql/sql_select.asp) an und baue dir die aktuelle Abfrage dann mit INNER JOINs (http://www.w3schools.com/sql/sql_join_inner.asp) zusammen.

Wenn du mir dann noch sagst, was dein Ziel erst einmal ist, kann ich dir ein Beispiel erstellen.
 
puh...

ok... ich versuch das mal - die jetztigen SQL abfragen hab ich mir immer im via PHPMyAdmin zusammen gebaut :)

wenn ich nun

Code:
SELECT `to_name` , `username` FROM `tagesordnung` , `user`

schreibe, werden mir alle Tagesordnungen und alle benutzernamen angezeigt - soweit auch klar.

Wenn ich jedoch nun

Code:
SELECT `to_name` , `username` FROM `tagesordnung` , `user` INNER JOIN `zusammen` ON `tagesordnung`.`ID`=`zusammen`.`TO_ID`

schreiben will, funktioniert das nicht, und bricht mit der fehlermeldung "#1054 - Unknown column 'tagesordnung.ID' in 'on clause'" ab.

---

Ich versuch es nochmal etwas besser auszuformulieren :)

Fremde leute, wie auch Regestrierte Benutzer sollen, Tagesordnungspunkte schreiben können - das funktioniert. Dabei werden die Tagesordnungspunkte nicht mit den Angemeldeten Benutzern verknüpft - soll auch so sein :)

Nun sollen aber Regestrierte Benutzer, die möglichkeit erhalten, sich aus den eingesendeten Tagesordnungspunkten, sich EIGENE Tagesordnungen "zusammen zu klicken".
Dafür gibt es vor jedem TO-Punkt einen kleine Checkbox.
Diese zusammen geklickte TO wird auch mit einem namen versehen.

Jeder nutzer soll die möglichekit erhalten, mehere Tagesordnungen für sich zu erstellen (später sollen auch noch zugriffsrechte eingebaut werden... aber später ^^).

Jeder Tagesordnungspunkt kann auch in meheren Tagesordnungen (TOs) vertreten sein. Sie sind dann also nicht exklusiv auf eine TO begrenzt.

---

Ich hoffe, dass war nun verständlicher :)
 
Das hat mir allerdings gehofen, jetzt verstehe ich das System besser. Was ich jetzt noch gerne wissen möchte ist: was hat das mit der Zusammen Tabelle zu tun? In dieser verknüpfst du ja die TOs und TPOs mit dem zugehörigen Benutzer. Wieso?

Die Tagesordnungspunkte hängen an der Tagesordnung, welche vom Benutzer abhängig ist. Ist dies der Fall sollte die Benutzer ID in die Tagesordnung abgelegt werden (Benutzer HAT Tagesordnung; Tagesordnung HAT Einträge). Die TO_ID wäre dann eindeutig (muss eindeutig sein), da keine Person zwei solcher TOs haben kann/wird. In der Tabelle Zusammen entfällt das dann. Die Tabelle Zusammen stellt dann die Liste für die TPOs einer persönlichen TO dar?

Die ID benötigt man in der Zusammen Tabelle soweit ich das sehen kann gar nicht, da ein Eintrag eindeutig über TO_ID und TPO_ID identifiziert wird, bei dir wäre dazu noch die B_ID notwendig. Diese ist ja aber nicht notwendig, da die TO ja überhaupt erst vom Benutzer abhängt.
 
Hio,

du hast recht, die B_ID sollte besser in der Tagesordnungstabelle abgelegt sein - das macht wirklich viel mehr sinn :)

Also nurnoch zwei Spalten - TO_ID und TPO_ID in der tabelle "zusammen"?

Vielen Dank schonmal, dass du dir zeit nimmst :)
 
Ja genau. In Zusammen (die Tabelle könnte man vlt. ToTpoList nennen). Mit ein bisschen Glück löst das sogar schon dein "Abfrageproblem".

Jetzt dann noch mal die Frage: Was willst du jetzt Abfrage (wolltest du oben mit dem SQL Befehl abfragen)? Eine Abfrage von Zusammen wäre dann z.B. so:
SELECT * FROM zusammen;

Willst du Informationen aus anderen Tabellen dazu haben, geht das z.B. so:
SELECT * FROM zusammen
INNER JOIN tagesordnung ON zusammen.TO_ID = tagesordnung.ID
INNER JOIN tagesordnungspunkte ON zusammen.TP_ID = tagesordnungspunkte.ID;

Schau mal ob diese Abfrage funktioniert, hab die grundlegenden Befehle auch immer automatisch erstellen lassen und weiß daher nicht sicher wie man multiple JOINs schreibt ;).
 
Bei der Zuordnungtabelle einfach mehrere Primary Keys vergeben. So umgeht man die zusätzliche IDs.
Zu deinen Joins:

Ich schreibe das immer ohne nervige Join angaben so: (oben lag dein Fehler wahrscheinlich an den Hochkommata bei 'tabelle'.'ID')
SELECT * FROM zusammen, tagesordnung, tagesordnungspunkte
WHERE zusammen.TO_ID = tagesordnung.ID
AND zusammen.TP_ID = tagesordnungspunkte.ID

Achja: Hinter dem FROM müssen immer ALLE Tabellen stehen die weiter unten gebraucht werden :)
Sollte so hinhauen. Teste mal.
 
Ganz ehrlich, wo kommt diese Syntax plötzlich her? Ich habe 2004 ein Buch über SQL gelesen und damals wurde vor genau dieser Syntax abgeraten. Seit dem hab ich das auch nicht mehr gesehen.

Die Verwendung von Table JOINs hat auch praktische Gründe z.B. behält man bei der JOIN Syntax den Überblick was man JOINT und was man im WHERE filtert. Dazu kann man bei Bedarf ein INNER JOIN ganze einfach in LEFT/RIGHT JOINs verwandeln, das geht mit der anderen Syntax nicht so einfach.

Als Hilfe könnt ihr mal Adminer als Oberfläche probieren. Vielleicht erstellt dessen Automatismus ANSI konforme SQL Syntax. Die Installation ist denkbar einfach. Einfach die einzelne Datei auf euren Webserver kopieren und im Loginfenster die SQL Logindaten eingeben.
 
Zuletzt bearbeitet:
soa... ich habe mich heute abend nochmal dran gesetzt...

jetzt gibt es aber leider noch eine kleine hürde...

ich habe jetzt einmal ein "INSERT INTO..." für die tabelle "tagesordnung", in der dann Name der TO und user ID gespeichert werden.

Und einmal ein "INSERT INTO..." fpr die weitere tabelle "zusammen", in der nun die ID der TO reinkommt, und die zugehörige Tagesordnungspunkt.

Ich denke mal, das mit den Tagesordnungpunkten sollte gehen - komme aber gedanklich gerade nicht damit klar, wie ich nun die ID der gerade angelegten TO rausbekomme... eine möglichkeit wäre, wenn jede TO einen eineindeutigen namen hätte. Wäre sicher eine möglichkeit, geht es auch anders ? :)
 
Die ID der TO ist eindeutig und muss auch darüber referenziert werden.

In PHP gibt es eine Funktion (http://stackoverflow.com/questions/3001610/getting-id-of-row-just-inserted-into-mysql-database) um die letzte ID der Tabelle zu erfahren. Es geht mit mysql_insert_id().

Würde es sowas nicht geben hättest du eine SQL Abfrage über die Benutzer ID und den Namen der TO (der sich in den Millisekunden ja nicht geändert hat) erstellen können. Also ein SELECT ID FROM Tagesordnung WHERE B_ID=Wert AND TO_NAME='Wert'.
 
Zuletzt bearbeitet:
rony12 schrieb:
wie ich nun die ID der gerade angelegten TO rausbekomme...
Also jetzt ist meiner Meinung nach die Frage wie sauber du programmieren willst.

Entweder:
SELECT max(ID) FROM TO
//TO anlegen mit max(ID)+1
--> du weißt die ID

Oder:
//TO anlegen, ID steht auf AutoIncrement
SELECT max(ID) FROM TO
--> du weißt die ID

Ganz professionell holst du dir die höchste ID (könnte man aus Geschwidigkeitsgründen in eine extra-DB auslagern, aber ist bei dir ja eh alles recht klein denke ich mal) legst einen Schutz auf die Table damit keiner die nächste eintragen oder nun die höchste abfragen kann, setzt die ID+1 ein und hebst den Schutz auf die Tabelle wieder auf...

Also würde ich sagen eine der beiden oberen Lösungen oder die mit PHP (kannte ich noch nicht). Vllt gibt es auch einen Befehl und den Autoincrement-wert aus der DB zu holen...Dann müsstest kein MAX() machen

Alternativtipp: Man könnte auch noch speichern wann ein TO angelegt wurde...gibt viele möglichkeiten

Neue Idee:
SELECT id FROM to ORDER BY id DESC LIMIT 1 :)
Muss man sich aber erst genaue Gedanken machen wenn es um high-performance etc. geht
 
Zuletzt bearbeitet:
rony12 schrieb:
komme aber gedanklich gerade nicht damit klar, wie ich nun die ID der gerade angelegten TO rausbekomme..

Es ist unsauber die eindeutige Identifikation der Tupel extern zu übernehmen.
Jedes DBMS hat so etwas wie Sequenzen. Im MySQL kannst du bei der Tabellenerstellung folgendes schreiben:
Code:
CREATE TABLE testtable
(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (id),
  something VARCHAR(30) NOT NULL
)

Das erstellt eine Testtabelle, die keine Nullwerte des Primärschlüssels erlaubt und ihn automatisch bei jedem Insert erhöht. Wesentlich sauberer als das selbst zu machen.

Zum Einfügen in diese Testtabelle schreibt man nun:
Code:
INSERT INTO testtable (something) 
VALUES ('Test')
Die id wird einfach automatisch generiert.

te one schrieb:
Muss man sich aber erst genaue Gedanken machen wenn es um high-performance etc. geht
SQL ist eine deklarative Sprache, deshalb kümmert sich der Anfrage-Optimierer um Performance.
Deine beiden Statements sollten (bei einem guten Optimierer) genau gleich schnell ablaufen.
 
Zurück
Oben