MySQL-Tabelle einfügen, falls nicht vorhanden, andernfalls aktualisieren

105
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

Es funktioniert, wenn das datenumexistiert, aber ich möchte diese Daten als neue Zeile einfügen, wenn das datenumnicht existiert.

AKTUALISIEREN

Das Datum ist eindeutig, aber das ist nicht der Primärschlüssel

OHLÁLÁ
quelle
2
Ist "datenum" einzigartig? Sie können INSERT ... ON DUPLICATE KEY UPDATE verwenden, wenn dies der Fall ist.
Jacob

Antworten:

143

Jai ist richtig, dass Sie verwenden sollten INSERT ... ON DUPLICATE KEY UPDATE.

Beachten Sie, dass Sie kein Datum in die Aktualisierungsklausel aufnehmen müssen, da es sich um den eindeutigen Schlüssel handelt, sodass er sich nicht ändern sollte. Sie müssen alle anderen Spalten aus Ihrer Tabelle einfügen. Mit dieser VALUES()Funktion können Sie sicherstellen, dass beim Aktualisieren der anderen Spalten die richtigen Werte verwendet werden.

Hier ist Ihr Update, das mit der richtigen INSERT ... ON DUPLICATE KEY UPDATESyntax für MySQL neu geschrieben wurde :

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)
Ike Walker
quelle
18
Seien Sie vorsichtig, wenn Sie INSERT ... ON DUPLICATE KEY UPDATE für Tabellen für eine Tabelle mit mehr als einem eindeutigen oder Primärschlüssel verwenden. Entnommen aus der MySQL-Dokumentation : Ab MySQL 5.5.24 wird außerdem eine INSERT ... ON DUPLICATE KEY UPDATE-Anweisung für eine Tabelle mit mehr als einem eindeutigen oder Primärschlüssel als unsicher markiert. (Fehler # 11765650, Fehler # 58637) Fehler 58637 Beschreibung bugs.mysql.com/bug.php?id=58637
Breitband
1
Es kann erforderlich sein, UNIQUEEinschränkungen für die TimestampVerwendung vonALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt
@broadband Sie können einen zusammengesetzten Schlüssel verwenden , um diesen Fehler zu vermeiden
Kareem
16

Versuchen Sie es mit dieser :

Wenn Sie angeben ON DUPLICATE KEY UPDATE, wird eine Zeile eingefügt, die einen doppelten Wert in einem UNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) der alten Zeile verursachen würde. ..

Die ON DUPLICATE KEY UPDATEKlausel kann mehrere durch Kommas getrennte Spaltenzuweisungen enthalten.

Mit ON DUPLICATE KEY UPDATEist der Wert für betroffene Zeilen pro Zeile 1, wenn die Zeile als neue Zeile eingefügt wird, 2, wenn eine vorhandene Zeile aktualisiert wird, und 0, wenn eine vorhandene Zeile auf ihre aktuellen Werte gesetzt ist. Wenn Sie beim Herstellen einer Verbindung zu mysqld das CLIENT_FOUND_ROWSFlag angeben , ist der Wert für betroffene Zeilen 1 (nicht 0), wenn für eine vorhandene Zeile die aktuellen Werte festgelegt sind ...mysql_real_connect()

Jai
quelle
Aber mein Datum ist nicht der Primärschlüssel.
OHLÁLÁ
In meinem Fall, was die Lösung ist, habe ich diese ohne Lösung ausprobiert: INSERT INTO forwind.aggregateddata (Datum, Zeitstempel, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = Datum;
OHLÁLÁ
1
soll datenum einzigartig sein? Wenn ja, fügen Sie einen eindeutigen Index hinzu (falls nicht bereits hinzugefügt). Dann funktioniert es. Informationen zum Anzeigen von EINZIGARTIGEN Indizes finden Sie unter dev.mysql.com/doc/refman/5.1/en/alter-table.html
Jai,
Jetzt habe ich das Datum als einzigartig definiert und es funktioniert gut, danke
OHLÁLÁ
1
Nur ein Link, vielleicht eine Antwort geben.
Andrew
0

Ich hatte eine Situation, in der ich eine Tabelle gemäß zwei Feldern (beide Fremdschlüssel) aktualisieren oder einfügen musste, für die ich keine EINZIGARTIGE Einschränkung festlegen konnte (daher funktioniert INSERT ... ON DUPLICATE KEY UPDATE nicht). Folgendes habe ich letztendlich verwendet:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

Dieses Beispiel stammt aus einer meiner Datenbanken, wobei die Eingabeparameter (zwei Namen und eine Nummer) durch [hasher_name], [hash_name] und [new_value] ersetzt wurden. Das verschachtelte SELECT ... LIMIT 1 ruft den ersten des vorhandenen Datensatzes oder einen neuen Datensatz ab (last_recogs.id ist ein Primärschlüssel für die automatische Inkrementierung) und verwendet diesen als Werteingabe in REPLACE INTO.

Salfter
quelle
REPLACE fügt immer eine neue Zeile ein! es löscht nur das ursprüngliche, bereits existierende!
Jason