Hallo Thomas,
zuerst mal Danke für deine schnelle Antwort.
(Getreu dem Motto: Sind Sie mit meiner Antwort nicht zufrieden, stellen
Sie bitte eine andere Frage - alles noch mal und diesmal vielleicht besser.)
On 20.04.2013 00:48, Thomas 'PointedEars' Lahn wrote:
> Andreas Horn wrote:
>
>> es gibt eine Datentabelle und die dazu gehörige Sicherungstabelle. In
>> der Datentabelle kann ich in einer Spalte den "Delinquenten" und seine
>> Änderungs-DATETIME eintragen. Bei INSERT und bei UPDATE wird das dann im
>> after_insert_tr bzw. im after_update_tr mit den anderen Daten der
>> datentabelle an die Sicherungsdatei angehängt.
>
> Vermutlich sind das Deine benutzerdefinierten Trigger-Namen. In dem Fall
> solltest Du nicht davon ausgehen, dass das jeder ohne Erklärung versteht.
Ich dachte die Namen sind sprechend. Aber Du hast Recht, das ist nicht
immer und bei Jedem so und sollte immer eindeutig beschrieben werden -
will mich bessern (hoffentlich denke ich dann auch dran).
>
>> Wie geht so was denn bei DELETE?
>
> Genauso.
>
>> Werte bei DELETE zu übergeben ist ja witzlos, weil sie mit dem Datensatz
>> ja sowieso gelöscht werden,
>
> Nein. Es gibt bloss keine *neuen* Werte.
Hier ist das genau so, ich sollte mitteilen, dass ich **neue** Werte
meine. Auf die **alten** Werte kann ich ja mit OLD.spaltenname zugreifen.
>
>> deshalb lehnt das DBMS das ja auch ab.
>
> Tut es nicht.
>
>> Wie kann ich das sonst noch machen? Ich habe schon von dem
>> vorherigen setzen einer globalen Variablen gelesen, die dann im Trigger
>> ausgewertet werden kann - das gefällt mir aber gar nicht. Oder muss ich
>> dafür eine Pozedur schreiben, die dann auch den Löschbefehl enthält? Das
>> missfällt mir aber auch.
>
> CREATE TRIGGER `foo` BEFORE DELETE ON `bar`
> FOR EACH ROW INSERT INTO `baz` (`bla`) VALUES (OLD.`bla`)
>
> und anschliessendes
>
> DELETE FROM `bar` WHERE …
>
> funktioniert in MySQL 5.5 auf einer (MyISAM-)Tabelle namens `bar`
> ausgezeichnet, d. h. der (MyISAM-)Tabelle `baz` wird ein entsprechender
> Datensatz hinzugefügt. (Mit InnoDb funktioniert das sicher auch.)
>
So, und jetzt noch mal ausführlich, auch auf die Gefahr hin, dass so
viel Text niemand mehr liest.
Prinzip ist bei mir, dass ich für jede Datentabelle eine
Sicherungstabelle, an die durch einen AFTER Trigger die Veränderungen
angehängt werden.
Die Sicherungstabelle ist genau so aufgebaut, wie die Datentabelle, die
ID der Datentabelle ist darin aber kein UNIQUE und sie hat noch 2
zusätzliche Felder:
eine eigene ID und eine Spalte `action`, in die INSERT, UPDATE oder
DELETE eingetragen wird.
Meine (verkürzte) Datentabelle `tbl_geraetetyp` sieht so aus:
CREATE TABLE `tbl_geraetetyp` (
`id_geraet` int(11) unsigned NOT NULL,
`geraetebezeichnung` varchar(240) COLLATE latin1_german1_ci NOT NULL,
`geaendertam` datetime DEFAULT NULL,
`geaendertvon` varchar(240) COLLATE latin1_german1_ci DEFAULT NULL,
`version` int(11) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id_geraet`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;
Meine (verkürzte) Sicherungstabelle `stbl_geraetetyp` sieht so aus:
CREATE TABLE `tbl_geraetetyp` (
`ids_geraet` int(11) unsigned NOT NULL,
`id_geraet` int(11) unsigned NOT NULL,
`geraetebezeichnung` varchar(240) COLLATE latin1_german1_ci NOT NULL,
`geaendertam` datetime DEFAULT NULL,
`geaendertvon` varchar(240) COLLATE latin1_german1_ci DEFAULT NULL,
`version` int(11) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`ids_geraet`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;
Mein (verkürzter) Trigger `tbl_geraetetyp_before_ins_tr` in der
Datentabelle `tbl_geraetetyp` für BEFORE INSERT sieht so aus:
BEGIN
DECLARE var_geaendertvon VARCHAR(240) DEFAULT '';
SET var_geaendertvon := SUBSTRING_INDEX(USER(),'@',1);
IF 1 = 1 AND NOT "spezialuser" = var_geaendertvon THEN
IF (NOT 'anwendungsname' = var_geaendertvon) THEN
SET NEW.`geaendertvon` := var_geaendertvon;
END IF;
SET NEW.`geaendertam` := NOW(),
NEW.`version` := 1;
END IF;
END;
Mein (verkürzter) Trigger `tbl_geraetetyp_after_ins_tr` in der
Datentabelle `tbl_geraetetyp` für AFTER INSERT sieht so aus:
BEGIN
DECLARE var_geaendertvon VARCHAR(240) DEFAULT '';
SET var_geaendertvon := SUBSTRING_INDEX(USER(),'@',1);
IF 1 = 1 AND NOT "spezialuser" = var_geaendertvon THEN
SET @aktion = "INSERT";
INSERT INTO `stbl_geraetetyp`
VALUES(
NULL,
NEW.`id_geraet`,
NEW.`geraetebezeichnung`,
NEW.`geaendertam`,
NEW.`geaendertvon`,
NEW.`version`,
@aktion
);
END IF;
END;
Mein (verkürzter) Trigger `tbl_geraetetyp_before_upd_tr` in der
Datentabelle `tbl_geraetetyp` für BEFORE UPDATE sieht so aus:
BEGIN
DECLARE var_geaendertvon VARCHAR(240) DEFAULT '';
SET var_geaendertvon := SUBSTRING_INDEX(USER(),'@',1);
IF 1 = 1 AND NOT "spezialuser" = var_geaendertvon THEN
IF (NOT 'anwendungsname' = var_geaendertvon) THEN
SET NEW.`geaendertvon` := var_geaendertvon;
END IF;
SET NEW.`geaendertam` := NOW(),
NEW.`version` := OLD.`version` + 1;
END IF;
END;
Mein (verkürzter) Trigger `tbl_geraetetyp_after_upd_tr` in der
Datentabelle `tbl_geraetetyp` für AFTER UPDATE sieht so aus:
BEGIN
DECLARE var_geaendertvon VARCHAR(240) DEFAULT '';
SET var_geaendertvon := SUBSTRING_INDEX(USER(),'@',1);
IF 1 = 1 AND NOT "spezialuser" = var_geaendertvon THEN
SET @aktion = "UPDATE";
INSERT INTO `stbl_geraetetyp`
VALUES(
NULL,
NEW.`id_geraet`,
NEW.`geraetebezeichnung`,
NEW.`geaendertam`,
NEW.`geaendertvon`,
NEW.`version`,
@aktion
);
END IF;
END;
Einen Trigger `tbl_geraetetyp_before_del_tr` gibt es nicht.
Mein (verkürzter) Trigger `tbl_geraetetyp_after_del_tr` in der
Datentabelle `tbl_geraetetyp` für AFTER DELETE sieht so aus:
BEGIN
DECLARE var_geaendertvon VARCHAR(240) DEFAULT '';
SET var_geaendertvon := SUBSTRING_INDEX(USER(),'@',1);
IF 1 = 1 AND NOT "spezialuser" = var_geaendertvon THEN
SET @aktion = "DELETE";
INSERT INTO `stbl_geraetetyp`
VALUES(
NULL,
OLD.`id_geraet`,
OLD.`geraetebezeichnung`,
NOW(),
var_geaendertvon,
OLD.`version`,
@aktion
);
END IF;
END;
Ich kann nicht davon ausgehen, dass derjenige, welcher einen Datensatz
angelegt oder zuletzt editiert hat hat, auch derjenige ist, der ihn
löscht - und genau den möchte ich fragen können, wenn ich mit irgend
etwas nach dem Löschen nicht klar komme.
Leider meldet sich die Anwendung nicht mit dem Login-Namen des Benutzers
an, sondern mit dem Namen der Anwendung 'anwendungsname', so dass die
Datenbank den Login-Namen des Benutzers explizit genannt kriegen muss.
Bei INSERT und UPDATE kann man dazu Ausdrücke mitgeben:
INSERT tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
WHERE where_condition;
oder
INSERT INTO tbl_name
VALUES (
expr,
...
);
UPDATE tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
WHERE where_condition;
Das geht bei DELETE aber nicht:
DELETE FROM tbl_name
WHERE where_condition;
Und jetzt endlich kommt meine Frage noch mal:
Wie kriege ich an den Trigger `tbl_geraetetyp_after_del_tr` für AFTER
DELETE den Login-Namen des Benutzers übergeben, damit er in der
Sicherungstabelle `stbl_geraetetyp` eingetragen werden kann.
Danke
Andreas