2016-11-30 2 views
6

Ich habe eine Tabelle ‚Spiel‘ wieaktualisiert eine Zeile, wenn sonst existiert einfügen

id|user1|user2|paired 
--+-----+-----+--------+ 
1 |U_1 |null |false 

Ich muß einen Datensatz einen neuen Benutzer ‚U_2‘ passen, wo gepaart = false, oder einen neuen Eintrag in der Tabelle erstellen wenn keine ungepaarte Zeile gefunden wird.

Diese db ist mit einem Server verbunden, wo mehrere Benutzer versuchen, gepaart zu werden, so muss ich die bestmögliche Lösung finden, die es schnell macht, so dass es die Tabelle nicht lange blockiert.

die Lösung kam ich mit war

int matchId = select id from match where ((user1 != 'U_2') AND (paired = false)); 

if(matchId > 0) 
then 
    update table match set user2 = 'U_2' where id = matchId; 
else 
    insert new row. 

Bitte einen besseren Weg vorschlagen.

Vielen Dank im Voraus.

+0

Ihre vorhandene Lösung sieht gut aus mir. Das sieht sehr einfach aus. Sehen Sie hier ein spezifisches Leistungsproblem? – worpet

+1

danke für die Antwort. Ich wollte wissen, ob es einen Teigweg dafür gibt. Wenn Sie in einer sehr großen Tabelle nachsehen, wird die Antwortzeit möglicherweise um 2 Mal erhöht. Und es gibt auch die Möglichkeit, dass 2 oder mehr Benutzer dieselbe ID von der ersten Abfrage erhalten. und dann könnten sie am Ende die gleiche Zeile aktualisieren. –

Antwort

8

können Sie

  • eindeutige Indizes hinzufügen, für user1 und user2 Geschwindigkeit zu verbessern und Integrität zu gewährleisten.
  • Verwenden Sie Transaktion, um Kollisionen zu vermeiden.
  • kombinieren, um die Auswahl und Update-Abfrage in einem Update:

    update table match 
    set user2 = 'U_2' 
    where ((user1 != 'U_2') AND (paired = false)) 
    LIMIT 1; 
    
  • überprüfen, ob das Update affected rows hat. Wenn nicht, fügen Sie die neue Zeile ein.

Wenn ich Ihre Intension richtig verstehen, können Sie auch:

  • entfernen Sie die Spalte paired, es scheint überflüssig zu sein, da es immer false wenn user2=null
+0

, aber beide Benutzer können beliebig oft gepaart werden. Und auch so kann ich keine Daten aus der aktualisierten Zeile an den Benutzer senden, der eine Übereinstimmung wünscht. Oder gibt es auch einen Weg dafür? –

+0

Ich stimme der Antwort von code_angel zu. Verwenden Sie update und fügen Sie ein wenn keine betroffenen Zeilen. Wenn das Update erfolgreich war, rufen Sie einfach die Informationen mit einer Auswahl ab (verwenden Sie einen Zeitstempel, um den neuesten Datensatz für diesen Benutzer abzurufen) ODER aktivieren Sie [this] (http://stackoverflow.com/questions/1388025/how-to-get-id- of-the-last-updated-row-in-mysql), um die ID direkt aus dem Update zu erhalten. –

+0

Wenn mehrere Übereinstimmungen zulässig sein sollen, verwenden Sie, wie S. Roose sagte, eine zusätzliche Zeitstempelspalte für eine Übereinstimmung. Sie können den eindeutigen Schlüssel über user1, user2 und timestamp setzen. Oder einfach über user1 und timestamp. Es hängt von Details ab. –

3

ein einzelnes Aussage macht das eine oder das andere:

INSERT INTO match 
    (user1, paired, user2) 
    VALUES 
    ('U_2', false, 'U_2') -- either insert this 
ON DUPLICATE KEY UPDATE 
    user2 = VALUES(user2); -- or update this 

Zusammen mit

PRIMARY KEY(user1, paired) -- a UNIQUE key to control what is "DUPLICATE" 
+0

Nicht für diesen Fall. Es gibt eine Viele-zu-Viele-Beziehung. Es wurde nicht genau definiert, was das OP mit "neue Zeile einfügen" in der Frage bedeutet. Aber aus dem Kontext und den Kommentaren unten ist klar: "Beide Benutzer können beliebig oft gepaart werden" –

Verwandte Themen