Frickelmeister: (mySQL + PERL) Doppelte Einträge vermeiden?

Hola,
ich habe mich gefragt, wie man es am effizientesten schaffen kann, dass doppelte Einträge in einer mySQL DB vermieden werden?
Hier mein normales Einfügescript:

my $input_vor = 'Susi';
my $input_nach = 'SusisNachname';

my $dbh = DBI->connect("DBI:mysql:$database:$dbserver", $user, $pass, {AutoCommit => 0}) or die "Cant connect : $!\n";
my $einfuegen = $dbh->prepare(q{INSERT INTO haupttabelle (vorname,nachname) VALUES (?,?)}) or die $dbh->errstr;

$einfuegen->execute($input_vor,$input_nach) or die $dbh->errstr;
$einfuegen->finish;

print "Content-type:text/html\n\n";
print 'Fertig';
$dbh->disconnect;

Jetzt habe ich versucht, die Zeile mit INSERT INTO irgendwie so abzuändern, dass zB
$dbh->prepare(q{INSERT INTO haupttabelle (vorname,nachname) VALUES (?,?) WHERE vorname NOT "$input_vor" AND nachname NOT "$input_nach"})
oder
$dbh->prepare(q{INSERT INTO haupttabelle (vorname,nachname) VALUES (?,?) WHERE vorname != "$input_vor" AND nachname != "$input_nach"})
oder
$dbh->prepare(q{INSERT INTO haupttabelle (vorname,nachname) VALUES (?,?) WHERE vorname != $input_vor AND nachname != $input_nach})

dortsteht, aber er gibt mir immer eine Fehlermeldung aus. Wie kann man das Problem am Besten angehen?

Frickelmeister.

  1. Hallo Frickelmeister,
    du musst einfach nur BEVOR du einen Eintrag schreibst in der Datenbank nachsehen ob der Eintrag vorhanden ist.
    Also einfach eine SQL abfrage machen nach dem Datenbankfeld, was nicht doppelt sein soll.
    Bekommst du ein Ergebnis zurück, schreibst du danach nichts und schon führst du den Schreibvorgang aus.

    Viele grüße
    Thorsten

    1. Hallo Thorsten,
      du hast eigentlich Recht. Ich denke einfach noch in Flat File Dimensionen, wo ich alles einlesen und überprüfen muss. Ich dachte auch die ganze Zeit daran, die ganze DB einzulesen, deswegen ist mir wohl diese Lösung nicht eingefallen :)

      Frickelmeister.

      1. Hi nochmal,
        ich weiß nicht wo ich hier bei der Überprüfung ansetzen soll? Wie würde die Syntax dafür aussehen, wenn ich nur überprüfen will, ob ein Vorname und Nachname in der DB bereits existiert?

        So kann es glaube ich nicht ganz stimmen.
        my $auslesen = $dbh->prepare("SELECT vorname,nachname FROM haupttabelle WHERE vorname = $vorname AND nachname = $nachname") or die "Cant auslesen : $!\n";

        Ich bräuchte, glaube ich eher einen Rückgabewert, also wenn etwas ausgelesen wurde, mache nichts, wenn nicht, dann schon, aber wie kann ich das am Besten rwealisieren?

        Frickelmeister.

  2. use Mosche;

    ich habe mich gefragt, wie man es am effizientesten schaffen kann, dass doppelte Einträge in einer mySQL DB vermieden werden?

    Bei dieser Fragestelung gibt es zwei Seiten:

    a) dein Datenbanklayout:
    beim erstellen der Tabelle gibst du beim Attribut, welches einzigartig sein soll, "unique" an. Dann _kannst_ du dort nichts doppeltes einfügen.
    Auch möglich, mehrere Felder gemeinsam als einzigartig zu kennzeichnen - das ist üblicherweise der Schlüssel (schau in die MySQL-Dokumentation unter dem Stichwort "Primary KEY").
    Bsp:

    CREATE TABLE blah (
      vorname varchar(80) UNIQUE,
      nachname varchar(80) UNIQUE
     );

    b) dein Programm:

    Du musst (wie im anderen Tip) vorher abfragen, ob der entsprechende Schlüssel (wie gesagt, das ist meistens das "einzigartige" Feld) bereits vorhanden ist. Wenn du damit rechnest, dass es konkurrierende Zugriffe gibt, dann arbeitest du mit Transaktionen (inwiefern MySQL  diese beherrscht, weiß ich nicht. Vor einiger Zeit konnte MySQL dies nicht, habe aber gehört, einige Tabellentypen würden Transaktionen beherrschen. Kann ich persönlich nicht verifizieren, benutze selbst meistens PostgreSQL).

    BEGIN WORK; -- startet die Transaktion
    SELECT dein_schluessel FROM blah WHERE dein_schluessel = "neuer schluessel";
    -- jetzt mit Perl testen, ob es geklappt hat
    INSERT INTO blah VALUES ("neuer schluessel");
    COMMIT;

    c) ggf. hat deine Datenbank Features, die das Select und Insert zusammenfassen - meine mich zu erinnern, dass irgendwo gesehen zu haben, weiß aber nicht, welche DB, und bezweifle, dass dies MySQL war. Im SQL Standard ist es nicht vorgesehen.

    INSERT INTO haupttabelle (vorname,nachname) VALUES (?,?) WHERE vorname NOT "$input_vor" AND nachname NOT "$input_nach"

    INSERT ... WHERE gibt es allgemein nicht.

    use Tschoe qw(Matti);

    --
      Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
    1. Hi,
      nun ich habe es jetzt so gelöst, dass ich einfach abfrage, ob mehr als Null Reihen zurückgeliefert werden. Wenn ja, ist der Name vorhanden, wenn Null, ist er noch nicht vorhanden. Ob diese Sache sehr effizient ist, weiß ich nicht, aber bisher ist es für mich die verständlichste Lösung, die ich mir aus div. Quellen zusammengesammelt habe :)

      my $auslesen = $dbh->prepare("SELECT * FROM haupttabelle WHERE vorname = '$vorname' AND nachname = '$nachname'") or die "Cant auslesen : $!\n";
      $auslesen->execute;

      print "Content-type:text/html\n\n";
      ($auslesen->rows == 0) ? print "Keine Datensätze\n" : print $auslesen->rows ." Datensätze vorhanden\n";

      Frickelmeister.

      1. Hallo,

        Ob diese Sache sehr effizient ist, weiß ich nicht, aber bisher ist es für mich die verständlichste Lösung, die ich mir aus div. Quellen zusammengesammelt habe :)

        Ich finde, da hast Du aber eine schlechte Wahl getroffen. Eindeutigkeit zu gewährleisten ist Teil der Arbeit eines Datenbanksystems, nicht der eines externen Programmes. Einer der wichtigsten Gründe für mich ist der Umstand, dass wenn Du die Datenbank diese Prüfung durchführen lässt, sichergestellt hast, dass es sicher passiert, egal welche Programme (oder Unterprogramme) Diese Daten befüllt. Bedenke, dass meist zu einer Insert-Funktion auch eine Update-Funktion benötigt wird. Du musst also mindestens an zwei Stellen in Deinem Programmcode dieselbe Prüfung durchführen, was bei einer Datenbankseitigen Lösung nicht notwendig ist.

        Von einer verbesserten Performance will ich jetzt gar nicht sprechen.

        Mein Vorschlag: Lerne mit der Datenbank, die Du benutzt umzugehen. Dazu gehört auch das Wissen um Indizes und Constraints.

        Grüße
          Klaus