Daten löschen mit Versionskontrolle

HonkTonk

Grünschnabel
Hallo,

ich habe eine Tabelle mit ca. 10000 Datensätze in MySQL 4.1. Diese Tabelle hat unteranderem eine Spalte ID (int) und eine Spalte Version (int). In meiner Anwendung (Mehrbenutzer Client-Server) lass ich mir jetzt eine Auswahl dieser Datensätze anzeigen, die ich dann zum löschen markiere. Wenn ich dann meinen Löschen-Button drücken möchte ich, dass die ausgewählten Datensätze mit einem Befehl gelöscht werden. Es muss aber geprüft werden, dass sich während ich die Datensätze markiert habe kein anderer die Daten geändert hat, sprich die Versionsnummer für jeden Datensatz noch die ist, die ich habe.
Gibt es hierfür eine Möglichkeit

Bin für jede Lösung dankbar!!

Gruß
Honk
 
Merk' Dir bevor Du mit dem markieren anfängst (also wahrscheinlich beim erzeugen der Liste) die höchste Versionsnummer. Dann:
SQL:
DELETE FROM `tabelle` WHERE (`zum_loeschen_markiert`) AND (`version` <= [meine letzte Version])
 
Zuletzt bearbeitet von einem Moderator:
Das Problem ist, dass jeder Datensatz unter Umständen eine unterschiedliche Versionsnummer hat. Und in der Zeit in der ich die Datensätze selektiert habe bis zum abschicken der Lösch-Anweisung könnte ja ein anderer Benutzer einen der selektierten Daten geändert haben.
Ich hab auch schon überlegt, die Datensätze zu sperren, wenn ich sie selektiere. Aber da ist das Problem, was passiert, wenn der Client abstürtzt?
Sonst vielleicht noch jemand eine Idee
 
Oha, ich verstehe. Das macht die Sache natürlich komplizierter.
Es gäbe elegante Lösugen mit einer temporären Tabelle, allerdings geht das nur, wenn die Connection zwischen dem Erzeugen der Auswahlliste und dem tatsächlichen Löschen erhalten bleibt, was bei einer klassischen Web-Anwendung nicht der Fall ist.
Deshalb hier eine andere Idee:

Beispiel-Tabelle:
Code:
+----+---------+--------+
| id | version | name   |
+----+---------+--------+
| 1  | 8       | Hans   |
| 2  | 15      | Peter  |
| 3  | 0       | Mickey |
| 4  | 6       | Lars   |
| 5  | 4711    | John   |
| 6  | 815     | Paul   |
| 7  | 33      | George |
| 8  | 128     | Ringo  |
| 9  | 42      | Ede    |
+----+---------+--------+

Auswahl an Datensätzen die angezeigt werden sollen, um sie zum löschen markieren zu können:
SQL:
SELECT
  CONCAT(`id`, '|', `version`) AS `marker`,
  `name`
FROM
  `tabelle`
Dabei wird dann dies zurückgegeben:
Code:
+--------------+--------+
| marker       | name   |
+--------------+--------+
| 1|8          | Hans   |
| 2|15         | Peter  |
| 3|0          | Mickey |
| 4|6          | Lars   |
| 5|4711       | John   |
| 6|815        | Paul   |
| 7|33         | George |
| 8|128        | Ringo  |
| 9|42         | Ede    |
+--------------+--------+

Die Anwendung sammelt jetzt von den zum Löschen markierten die "Marker" zusammen, packt Hochkommas drumrum und verkettet diese mit Kommas.
Angenommen, die ersten 5 Sätze werden markiert, dann ergibt dies folgenden String:
'1|8','2|15','3|0','4|6','5|4711'

Des weiteren angenommen, die Versionsnummer der Sätze 2 und 4 hätten sich inzwischen erhöht, dann sähen die Daten inzwischen so aus:
Code:
+----+---------+--------+
| id | version | name   |
+----+---------+--------+
| 1  | 8       | Hans   |
| 2  | 16      | Petra  |
| 3  | 0       | Mickey |
| 4  | 7       | Lisa   |
| 5  | 4711    | John   |
| 6  | 815     | Paul   |
| 7  | 33      | George |
| 8  | 128     | Ringo  |
| 9  | 42      | Ede    |
+----+---------+--------+

Jetzt kommt der Lösch-Befehl:
SQL:
DELETE FROM `tabelle` WHERE CONCAT(`id`, '|', `version`) IN ('1|8','2|15','3|0','4|6','5|4711')

'2|15' und '4|6' gibts nicht mehr, diese bleiben also unbehelligt.

Das ist sicher nur eine von mehreren Lösungen, aber die ist mir halt als erstes eingefallen. Ich hoffe, das Beispiel hat meine Wirren Gedanken verständlich gemacht.
 
Zuletzt bearbeitet von einem Moderator:
Hallo ManicMarble,

das klingt nicht schlecht Werd ich gleich mal ausprobieren. Wie sieht es hierbei mit der Performance aus? Ich habe wie gesagt knapp 10000 Datensätze in der Tabelle. Ich werds aber auf jeden Fall mal probieren. Danke aber schon mal!
Wie würde die Lösung mit der temporären Tabelle aussehen?
 
10.000 Datensätze sind für MySQL eigentlich ein Kinderspiel. Falls es jedoch deutlich mehr werden, sagen wir mal so ab 100.000, sind Deine Bedenken berechtigt: das DELETE-Statement verwendet eine Funktion in der WHERE-Klausel, das kostst Performance und da hilft auch indizieren nichts.
Das erste was mir hierzu einfällt: Ein eigenes, indiziertes Feld, das das Ergebnis von CONCAT(`id`, '|', `version`) enthält und das über einen UPDATE-Trigger aktuell gehalten wird. Trigger würde allerdings Upgrade auf MySQL 5.0 erfordern...
 
Ach so, Deine Frage bzgl. temporärer Tabelle hatte ich vergessen.

Ganz grob:
Temp. Tabelle anlegen mit allen Sätzen die zur Auswahl angeboten werden sollen und mit den Feldern `tmpid`, `id` und `version`, wobei `tmpid` die eigene auto_increment-Spalte der temp. tabelle ist.
Auswahl der zu löschenden Sätze über diese temp. Tabelle (ggf. mit LEFT JOIN auf die Originaltabelle, um mehr Felder anzuzeigen).
In der Anwendung die `tmpid`s der zu löschenden Sätze merken.
DELETE-Statement mit JOIN auf die Temp.-Tabelle.
Temp. Tabelle droppen.
 

Neue Beiträge

Zurück