[SQL] PostgreSQL und INSERTs



  • Ich habe folgende Tabelle

    my_table (
      user_id INTEGER (UNIQUE)
      ...
    )
    

    Auf dieser Tabelle führe ich folgendes INSERT-Statement aus.

    INSERT INTO my_table ( user_id ) VALUES ( 1 ), ( 2 ), ( 1 );
    

    Logischerweise bekomme ich dabei einen UNIQUE CONSTRAINT Fehler. Ich könnte natürlich die INSERTs auf verschiedene Statements au´fteilen und vorher jeweils prüfen ob ein Datensatz mit der jeweiligen user_id schon vorhanden ist. Bei mehreren hundert Datensätzen ist das jedoch nicht wirklich performant.

    Ich will eigendlich nur, dass Datensätze mit neuen user_id-Werten eingefügt werden und existierende ignoriert werden. Geht das irgendwie? Ich stehe grad ziemlich auf dem Schlauch 😞



  • Den Datentyp auf SERIAL oder BIGSERIAL setzen und die Arbeit vom DBMS machen lassen. Die id wird dann automatisch eingefügt, die Zählweise wird durch die automatisch erstellte Sequenz definiert.



  • Hallo john,
    vielleicht war mein Beispiel nicht optimal 😉
    user_id ist ein Fremdschlüssel, also fällt das mit dem SERIAL schon mal weg.
    Ziel ist es mehrere hundert INSERTs mit einem Statement zu machen und UNIQUE CONSTRAINTs zu ignorierern.

    Trotzdem danke.



  • Solange Du nicht vorher nachschaust welche Datensätze schon existent sind, wird es immer wieder zu Kollisionen kommen. Ergo nachschauen mußt Du so oder so. Das einzige was mir spontan einfällt ist, daß man eine SQL-Funktion schreiben könnte, die den Datensatz einfügt falls er noch nicht existent ist, und alternativ nichts macht.

    Das UNIQUE CONSTRAINT außer Kraft zu setzen ist jedenfalls nicht sinnvoll.



  • Du könntest einen Trigger BEFORE INSERT erstellen, der im Falle eines bereits existierenden Datensatzes diesen entfernt.



  • Was spricht gegen eine INSERT ... SELECT - Anweisung. Dann könntest du über das SELECT die Fremdschlüssel anziehen und die Duplikate eliminieren. Allerdings müssten die einzufügenden Daten über das SELECT ermittelt werden können.



  • Hi frenki, die Idee mit Triggern klingt nicht schlecht. Werde ich mir bei Gelegenheit mal ansehen.

    Damit der Teil meiner Anwendung erstmal funktioniert, führe ich jetzt für jedes Insert ein eigenes Statement aus und fange Unique Constraints ab.



  • Herrmann schrieb:

    Hi frenki, die Idee mit Triggern klingt nicht schlecht. Werde ich mir bei Gelegenheit mal ansehen.

    Damit der Teil meiner Anwendung erstmal funktioniert, führe ich jetzt für jedes Insert ein eigenes Statement aus und fange Unique Constraints ab.

    Das ist auch die richtige Lösung.

    Ein Insert-Statement fügt entweder eine Zeile ein oder das Resultat einer anderen Query. Diese Syntax mit mehreren Zeilen, wie Du sie vorschlägst, mag bei der einen oder anderen Datenbank funktionieren, aber Standard ist es nicht und daher wird es von Postgresql auch nicht unterstützt.

    Wenn Du einen Datensatzt nur anlegen möchtest, wenn er noch nicht existiert, gibt es genau 2 Möglichkeiten: entweder Du schaust vorher mit einem Select nach oder du rennst gegen den Fehler und ignorierst ihn.



  • Es Zeile für Zeile zu machen ist vielleicht die "richtige" Lösung, aber eine sehr sehr langsame Lösung.

    Ich würde eher versuchen irgendwie sicherzustellen dass in den neu einzufügenden Zeilen keine doppelten IDs vorkommen (das soll das Programm machen welches diese SQL Statements generiert), dann die Daten in eine Temp-Tabelle laden, und dann mittels "INSERT ... SELECT ... WHERE NOT EXISTS (...)" nur die "nötigen" Zeilen einfügen.

    Bei "vielen" Zeilen sollte das deutlich schneller gehen als pro Zeile ein eigenes SQL Statement rauszutreten.


Anmelden zum Antworten