Es ist ja auch richtig, daß du das erwähntest. Ich bin mir noch nicht sicher, was ich mir überhaupt ansehe. Also ob das etwas mit dem zu tun hat, wonach ich suchte. Das stellte ich mir nämlich ähnlich wie bei Excel vor, wo man zum Beispiel in Feld X056 schreiben könnte „addiere die Werte der Zeile von A001 bis A038 und teile sie durch den Wert in Zelle D004“, also natürlich als Formel. Nur das Ergebnis wäre in X056 zu sehen und damit könnte man gleich weiterarbeiten. In die MySQL-Datenbank hätte ich also so etwas geschrieben wie „nehme den Wert LinkerNachbar und teile den durch den Wert RechterNachbar, liefere das Ergebnis zurück“.
Meine Absicht dabei wäre gewesen, ein include() durch eine Datenbankabfrage zu ersetzen. Das weil mit Datenbanken zu arbeiten schneller sein soll als mit Dateien und ich hielt es vor allem dann für sinnvoll, wenn man an der Stelle aus anderen Gründen (die Werte aus den benachbarten Tabellenzellen verwenden zu wollen) sowieso die Verbindung zur Datenbank herstellt.
Stored procedures / functions / routines scheinen mir doch etwas anderes zu sein. Eher eine Art Programmbibliothek mit der man den Funktionsumfang von MySQL etwas erweitern kann.
Aber was ich vorhatte, geht wohl nicht. Zumindest nicht auf eine Weise, die gegenüber einer normalen zusätzlichen Query einen Vorteil hätte. Mehrere Anweisungen in ein mysqli_prepare() zu schreiben geht wohl auch nicht?
Dann muß ich noch nachfragen: Die zusätzliche Tabelle, die du vorschlugst, war die nur als Beispiel für Möglichkeiten, nach denen ich gefragt hatte, oder ist das tatsächlich eine sinnvolle Variante?
Vielleicht habe ich es nicht klar genug gemacht, daß ich nach der sinnvollsten Variante einer Bewertung suche. So ein Bewertungssystem ist nämlich nützlich. Nichtmal unbedingt, um es herzuzeigen, sondern um festzustellen, welche Nutzer sowohl kompetent als auch vertrauenswürdig sind.
Noch eine Verständnisfrage: Solange ich bei einem Schreibvorgang immer nur eine Tabelle aktualisieren muß und nicht mehrere, sind meine Daten nicht redundant und meine Tabellen schon in Normalform?
Ranma
Das stellte ich mir nämlich ähnlich wie bei Excel vor, wo man zum Beispiel in Feld X056 schreiben könnte „addiere die Werte der Zeile von A001 bis A038 und teile sie durch den Wert in Zelle D004“, also natürlich als Formel.
Ah, jetzt verstehe ich, worauf du hinauswolltest. Die Rechnung baut man einfach in die Abfrage ein, da muss man nichts in der Datenbank speichern. Die Query steht steht ja in deinem PHP-Script.
Dann muß ich noch nachfragen: Die zusätzliche Tabelle, die du vorschlugst, war die nur als Beispiel für Möglichkeiten, nach denen ich gefragt hatte, oder ist das tatsächlich eine sinnvolle Variante?
Ich halte dies für die sinnvollste Variante. Ansonsten müsste man die Likes als eine Art Liste in einem Datenfeld speichern. Das Hinzufügen und Zählen der Likes kann dann aber nicht mehr in MySQL erfolgen, dazu müsste man dann entsprechende Funktionen in PHP schreiben.
Noch eine Verständnisfrage: Solange ich bei einem Schreibvorgang immer nur eine Tabelle aktualisieren muß und nicht mehrere, sind meine Daten nicht redundant und meine Tabellen schon in Normalform?
Nein, das lässt sich denke ich nicht daraus folgern. Redundant sind die Daten z.B. dann, wenn statt einem Datensatz mehrere Datensätze geändert werden müssen. Wenn z.B. in einer Datenbanktabelle `buecher` der Name des Autors gespeichert wird und eine Autorin nach ihrer Heirat einen anderen Namen hat, dann muss man ggf. mehrere Datensätze ändern. Besser wäre es, die Autoren in einer eigenen Tabelle `autoren` zu speichern, und in `buecher` einen Fremdschlüssel anzulegen.
Einerseits soll es erstrebenswert sein, wenn Daten nicht redundant sind. Andererseits würde ich mit der zusätzlichen Tabelle die Daten tatsächlich erst redundant machen. Für jeden neuen Beitrag müßte auch eine neue Zeile in die zusätzliche Tabelle und für jeden neuen Registrierten eine neue Spalte.
Außerdem wäre das die erste Tabelle, für die ich neue Spalten anlegen müßte, vielleicht die einzige. Dann braucht mein Skript nur deswegen das Recht zu ALTER TABLE. Andernfalls wäre ich wahrscheinlich mit INSERT, UPDATE und SELECT ausgekommen. Man kann in MySQL einige Rechte abschalten und das hätte ich dann tun und so die Sicherheit nochmal erhöhen können.
Anscheinend machen die kleinsten Features die größte Arbeit. Wenn ich mir die schon mache, dann hätte ich die Bewertungsfunktion dafür schon gerne noch positiv rückgekoppelt. Das heißt, dann will ich den Stimmen derer, die keine Moderationsarbeit verursachen sondern gute Beiträge schreiben, mehr Gewicht geben als den Stimmen derer, bei denen das andersherum ist. Wahrscheinlich speichere ich die Stimmgewichte wiederum in einer weiteren extra Tabelle? Könnte der Inhalt einer Tabellenzelle auf eine andere verweisen, dann wäre vieles einfacher. Bisher waren meine Daten nicht redundant (es sind nur ganz wenige und einfache per Hand in die Datenbank eingefüllte), erst die Idee der Bewertung macht alles kompliziert.
Und bei JOIN braucht es die Varianten mit RIGHT, LEFT, INNER oder OUTER nicht? So weit ich die Syntax inzwischen verstanden habe, gibt es zwar viele Schreibweisen für JOIN, aber praktisch alle sind Synonyme und das dient nur der Kompatibilität mit anderen Datenbanktypen?
Ranma
Für die Bewertungsfunktion benötigst du lediglich INSERT-Abfragen, und falls du Bewertungen rückgängig machen möchtest auch DELETE-Abfragen.
Neben der ID benötigst du noch zwei Spalten für die User-ID und für die Post-ID. Weitere Spalten braucht es nicht.
Und bei JOIN braucht es die Varianten mit RIGHT, LEFT, INNER oder OUTER nicht? So weit ich die Syntax inzwischen verstanden habe, gibt es zwar viele Schreibweisen für JOIN, aber praktisch alle sind Synonyme und das dient nur der Kompatibilität mit anderen Datenbanktypen?
Nein, da gibt es schon Unterschiede. Bei einem INNER-JOIN z.B. werden nur Datensätze ausgegeben, die in beiden Tabellen vorkommen. Bei einem LEFT-JOIN dagegen alle Datensätze, die in der linken Tabelle vorkommen, unabhängig davon, ob sie in der rechten Tabelle vorhanden sind oder nicht.
Ja, tatsächlich, wenn etwas in eine Tabellenzelle paßt, dann paßt es erst recht in eine Tabellenzeile. Das erfordert nur entsprechend mehr Zeilen. Sogar zusätzliche Informationen in weiteren Spalten wären noch möglich. Ich werde wohl die gesamte Struktur meiner Datenbank verändern müssen und überlege noch mal von vorn, welche Tabellen ich brauche.
Anscheinend darf eine Tabelle in MySQL nur eine Spalte vom Format Zeitstempel enthalten. Ich sehe dafür keinen Grund, sondern finde das nur sehr unpraktisch. Für Beiträge hätte ich Erstellungsdatum und zusätzlich das Datum des letzten Updates und / oder das Datum des letzten Zugriffs speichern können. Für Nutzer das Datum der Registrierung, danach noch Anmeldungen und Abmeldungen, um daraus die Zeit online zu berechnen. Oder, falls mal jemand eine Sperre braucht, das Ende der Sperrfrist. Aber es geht wohl nur jeweils eines davon. Das ist echt unpraktisch. Läßt sich das umgehen? Oder gibt es wenigstens einen guten Grund für die Einschränkung?
Ranma
Meinst du das Format TIMESTAMP? das kann mehrfach verwendet werden, siehe erste Antwort in diesem Stack-Overflow-Thread:
http://stackoverflow.com/questions/4851672/one-mysql-table-with-multiple-timestamp-columns
Ansonsten ließen sich auch DATETIME- oder auch INT-Felder nutzen (letztere zum Speichern von Unix-Timestamps); zwar ohne Automatismus, aber die betreffenden UPDATE-Queries können ja um ein entsprechendes Statement erweitert werden.
Ja, TIMESTAMP heißt es und das eigentliche Problem dabei ist wohl, daß ich den von MySQL (also nicht mit den PHP-Funktionen) erstellen lassen wollte/will. MySQL gibt das dann nämlich bei Abfragen schon perfekt fertig als Datum und Uhrzeit formatiert aus. Außerdem ist das ja die korrekte Zeit, weil ein Eintrag erst dann fertig erstellt ist, wenn er in die Datenbank eingetragen ist. Mit phpMyAdmin kann man das auf current timestamp on update einstellen. Falls man das nicht einstellt, dann sollte der einmal erstellte TIMESTAMP bleiben. Demnach wären zwei Felder mit TIMESTAMP sinnvollerweise möglich, aber es ist nur eines möglich.
Laut der verlinkten Anleitung, wo tatsächlich das gleiche Problem beschrieben wird, verwende ich ein inzwischen veraltetes MySQL. Nicht ganz ohne Absicht, weil ich schon möchte, daß mein Skript nicht nur auf meinem eigenem Computer laufen kann. Es gibt für die Version anscheinend einen Trick, aber den habe ich noch nicht verstanden. Mal sehen, was ich davon brauchen kann.
Auch das Attribut UNIQUE macht Schwierigkeiten. Eigentlich dachte ich, das wäre dazu da, um festzulegen, daß sich in dem betreffenden Feld die Werte nicht wiederholen dürfen. Möglicherweise sollte ich diese Einstellung unterlassen, weil sie nur Fehler produzieren kann. Aber ich dachte halt, daß sich so doppelte Einträge verhindern ließen. phpMyAdmin will aber alles, was auf UNIQUE gesetzt wurde, als Schlüssel verwenden und verlangt dafür eine Schlüssellänge. Scheint kein Problem zu sein, weil es auch ein Feld Länge/Wert gibt. Aber alles, was ich da eintrage, wird ignoriert. Nur bei bestimmten Datentypen ist es erforderlich und dann kann ich meistens nur raten, was das bewirken wird.
SQL beschäftigt mich zur Zeit am meisten, auch weil ich jetzt einige Tabellen durch ganz andere ersetzt habe. Manchmal müssen einige Queries direkt nacheinander ausgeführt werden, ohne daß Aktionen einer weiteren Instanz (falls das so heißt, also wenn ein weiterer Client das Skript aufruft) zwischendurch etwas an der betroffenen Tabelle ändern dürfen. Da frage ich mich gerade, ist
LOCK TABLES Tabelle WRITE;
bla;
blub;
UNLOCK TABLES
das Richtige dafür oder soll
SET TRANSACTION;
bla;
blub;
COMMIT
genau das ersetzen?
Anleitungen zu beidem sagen, daß Autocommit zuvor abgeschaltet werden soll, aber eine weitere Anleitung besagt, daß SET TRANSACTION das Autocommit wieder einschaltet. Bei LOCK TABLES weiß man wenigstens, daß man die Tabellen wirkungsvoll gesperrt hat, obwohl die weitere Syntax kompliziert ist. Bei SET TRANSACTION wird erst bei COMMIT ausgeführt, aber ob da dann etwas dazwischenfunken kann? Das Ausschalten und danach wieder Einschalten des Autocommit muß auf jeden Fall außerhalb des Blocks erfolgen und da könnte wiederum eine andere Anweisung dazwischenfunken. Die meisten davon werde ich erst später schreiben, wenn ich glaube verstanden zu haben, was ich da mache.
Eine der Anleitungen, die ich gefunden habe, sagt sogar, daß man bei Transactions in einer ganz bestimmten Reihenfolge mit den mysqli-Funktionen vorgehen muß. Sieht echt kompliziert aus.
Ranma
Ja, TIMESTAMP heißt es und das eigentliche Problem dabei ist wohl, daß ich den von MySQL (also nicht mit den PHP-Funktionen) erstellen lassen wollte/will. MySQL gibt das dann nämlich bei Abfragen schon perfekt fertig als Datum und Uhrzeit formatiert aus.
Das ist aber nicht immer das gewünschte Format. Im deutschsprachigen Raum z.B. wird für gewöhnlich das Format dd.mm.yyyy verwendet, und nicht yyyy-mm-dd
phpMyAdmin will aber alles, was auf UNIQUE gesetzt wurde, als Schlüssel verwenden und verlangt dafür eine Schlüssellänge. Scheint kein Problem zu sein, weil es auch ein Feld Länge/Wert gibt. Aber alles, was ich da eintrage, wird ignoriert. Nur bei bestimmten Datentypen ist es erforderlich und dann kann ich meistens nur raten, was das bewirken wird.
Für welchen Datentyp möchtest du UNIQUE denn einsetzen?
Da frage ich mich gerade, ist
LOCK TABLES Tabelle WRITE;
bla;
blub;
UNLOCK TABLES
das Richtige dafür oder soll
SET TRANSACTION;
bla;
blub;
COMMIT
genau das ersetzen?
Transactions funktionieren nur in Verbindung mit InnoDB
Eine der Anleitungen, die ich gefunden habe, sagt sogar, daß man bei Transactions in einer ganz bestimmten Reihenfolge mit den mysqli-Funktionen vorgehen muß. Sieht echt kompliziert aus.
Hier ist das eigentlich recht einfach erklärt:
http://www.peterkropff.de/site/php/mysqli_transaktionen.htm
Das erklärt doch einiges.
yyyy-mm-dd ist immerhin leicht intuitiv verständlich, anders als das angelsächsische mm/dd/yyyy. Darum scheint yyyy-mm-dd auch sehr international zu sein, weil MySQL aus Schweden stammt (daher die komische Voreinstellung bei den Kollationen und daher weiß ich das) und mir das Format schon als asiatisches Format bekannt war. Also wenn man das Format nicht für jede Region extra anpassen will, dann scheint mir das am besten zu sein.
UNIQUE wollte ich überall einsetzen, wo die Werte sich nicht wiederholen sollen. Zum Beispiel um Doppelpostings zu verhindern, anhand des dann gleichen Textes. Aber das ist vermutlich kein guter Weg dafür.
Noch war ich nicht darauf gestoßen, daß PHP für Transaktionen eigene Funktionen hat. Dann werde ich mir mal die verständlichen Erklärungen zu Gemüte führen. Wären InnoDB bei MySQL nicht standardmäßig voreingestellt, dann wäre ich wohl übel aufgelaufen. Kann man davon ausgehen, daß InnoDB immer zur Verfügung steht? (Also es die nur bei ganz alten Versionen nicht gibt, aber keinen Grund nur einen anderen Datenbanktyp zur Verfügung zu stellen?)
Ranma