Wie verhindert man doppelte Einträge in einer Datenbank mit PHP?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Auf jeden Fall solltest du zuerst das Design deiner Datenbank überarbeiten, indem du einen Primärschlüssel bestimmst - also eine Kombination aus Spalten (bzw. mindestens eine Spalte), die eindeutig ist.

Um nun zu vermeiden, dass dies zu einem Fehler führt (jeder Eintrag darf dann mit seinem Primärschlüssel ja nur noch einmal vorkommen), falls ein Duplikat entstehen könnte, nimmst du deine Anfragen an die Datenbank vor. Die erste Anfrage (SELECT) sucht nach einem Nutzer, der bereits die selben Daten hat. Wenn kein Ergebnis zurückgeliefert wird, kannst du einen INSERT vornehmen, ansonsten eine Fehlerausgabe an den Nutzer.

Zuletzt noch ein Kommentar zu deinem Code: Dieser ist so überhaupt nicht sicher.

1) Benutze die Funktion isset, um zu prüfen, ob ein entsprechender Key im superglobalen Array vorhanden ist:

if(isset($_POST["vorname"]) && /* .... */

2) Schreibe niemals Daten von außen ungeprüft in einen SQL-Query oder eine andere Art von Evaluationsfunktion (wie eval). Ein Nutzer könnte dies ausnutzen und eigenen Code einschleusen, der dann ausgeführt wird (SQL Injection). Verwende für SQL-Anfragen daher Prepared Statements.


SebastianJustin 
Fragesteller
 23.02.2018, 23:27

Ich kann die eindeutigste Spalte "nick" nicht als Primärschlüssel setzen, kann es daran liegen, dass die Spalte typ text ist? Wenn ja, welchen Typen soll ich anstelle text nehmen?

Und wie Stelle ich die Anfrage mit SELECT? Habe da jetzt über ne halbe Stunde ohne Erfolg rumgewurschtelt...

Die Sicherheit ist mir momentan egal, da ich das sowieso nur zum lernen mache, das kommt dann vlt. wenn ich mit dem Spielerbuch fertig bin. Dann habe ich dank dir, wenigstens eine Anlaufstelle :3

0
regex9  24.02.2018, 00:43
@SebastianJustin

1) Schau dir doch einmal die Fehlermeldung an, die dir dazu sicherlich ausgegeben wird.

2) Dieser Query:

SELECT nick FROM tabelle WHERE nick='spencer'

würde dir alle Einträge mit dem Nicknamen spencer zurückgeben. Die zu selektierenden Spalten begrenze ich auf eine (es könnte jede beliebige in der Tabelle sein), denn du möchtest ja lediglich erfahren, ob es überhaupt einen Eintrag gibt.

Des Weiteren könntest du die Einträge gleich noch via SQL zählen lassen:

SELECT COUNT(nick) FROM tabelle WHERE nick='spencer'

3) Zumindest isset solltest du dir bereits jetzt angewöhnen, da ein direkter Vergleich hier wirklich keine gute Lösung wäre.

0
SebastianJustin 
Fragesteller
 28.02.2018, 18:00

Ich habe einfach nick als Primärschlüssel gesetzt und somit kann man nicht mehr zwei mal den gleichen Nicknamen abschicken, ich lasse das Formular auch nicht prüfen, weil mir das irgendwie egal ist :D

0

Das lässt sich über verschiedene Mechanismen verhindern. Die Frage ist, was du davon genau haben willst. Eine Variante wäre, dass du in der Datenbank einen entsprechenden Index erstellst, z.B. über Name, Nick, Geburtsdatum und diesen Unique machst, dann darf eine Kombination aus Name, NIck und Geburtsdatum nur einmal existieren. Wenn du einen erneuten INSERT machst, bekommst du von der Datenbank einen entsprechenden Fehler und gibst dann an den User einen Fehler aus. Eine andere Variante wäre, dass du das Formular mit einem Hidden-Tag versiehst, das genau einmal verwendet werden darf. Wenn das Formular doppelt abgeschickt wird, dann ist der Tag verbraucht und ein erneuter INSERT wird nicht gemacht.


wotan38  24.02.2018, 12:42

Das mit dem unique Index, wie hier beschrieben, ist die beste Lösung. So wird das auch allgemein gemacht und dafür ist das unique beim Index vorgesehen.

Den Index kannst mit CREATE INDEX einrichten. Dazu musst Du festlegen, was Du genau unter doppelt verstehst. Da Du vermutlich einen Primärschlüssel hast, kannst einen wirklich doppelten Satz gar nicht schreiben, da dieser Schlüssel sich immer unterscheidet. Du musst also die Spalten aussuchen, die für das Doppelte relevant sind und damit diesen Index einrichten. Das geht auch nachträglich. Allerdings müssen doppelte Sätze, falls diese schon vorhanden sind, erst einmal bereinigt werden.

0

Du könntest z.B. den Namen als Primärschlüssel definieren, dann gibt's einen Fehler, wenn Du versuchst ihn doppelt anzulegen, auf den kannst Du dann prüfen und eine Meldung ausgeben.

Oder Du fragst vor dem INSERT ab, ob der Eintrag vorhanden ist.

in dem du via SELECT COUNT(*) vor deinem insert prüfst ob bereits ein datensatz vorhanden ist..


wotan38  02.03.2018, 12:31

Diese Lösung ist nicht nur umständlich, vielmehr auch schlecht. Denn mit der Anzahl der gespeicherten Sätze wird das Einfügen immer langsamer. Wenn Du 1000 Sätze hast, müssen bei jedem Eintrag alle 1000 Sätze durchgenudelt werden. Mit einem Index geht das einfach und unproblematisch.

0