birdyb
Goto Top

SQL Anywhere: FOREACH möglich?

Hallo zusammen und ein gutes neues Jahr,

ich möchte gerne in unserem ERP-System, bzw. der Datenbank dahinter bestimmte Änderungen in einer Tabelle überwachen und die Änderungen in eine Protokolltabelle schreiben.
Mein Gedankenansatz war es, hier mit einem Trigger auf das UPDATE zu reagieren und dann zu prüfen ob OldRow.Spalte = NewRow.Spalte ist und wenn dies nicht der Fall ist, den Protokolleintrag auszulösen.
Dies soll aber nicht für alle Spalten passieren. Jetzt kann ich natürlich für jede gewünschte Spalte einen if-then-Block in den Trigger schreiben, ich finde das allerdings sehr unübersichtlich.
Daher war meine Überlegung, ob ich nicht eine Liste der zu überwachenden Spalten definieren kann und diese dann mit einer foreach-Anweisung abarbeite.
Leider habe ich dazu bisher keine allzuschlaue Lösung finden können.

Kann mir von euch jemand helfen?

Vielen Dank und beste Grüße

Content-Key: 325283

Url: https://administrator.de/contentid/325283

Printed on: April 24, 2024 at 21:04 o'clock

Member: ukulele-7
ukulele-7 Jan 03, 2017 at 07:18:07 (UTC)
Goto Top
Das ginge höchstens mit dynamischem SQL und müsste dann jedes mal per EXEC() ausgeführt werden. Das würde ich aber als unnötig komplex und vermutlich auch Ressourcen-feindlich einschätzen.

Wenn es wirklich viele Spalten und Tabellen sind empfehle ich dir ein Script zu erstellen das dir die Trigger als Zeichenkette erzeugt. Ich habe damit mitlerweile gute Erfahrungen gemacht aber das ganze war schon recht Zeitaufwendig.
Member: BirdyB
BirdyB Jan 03, 2017 updated at 20:45:13 (UTC)
Goto Top
Danke für den Hinweis. So viele Spalten sind es nicht, da kann ich dann einfach per if-then und copy&paste arbeiten.
Member: ukulele-7
ukulele-7 Jan 04, 2017 at 08:10:51 (UTC)
Goto Top
Hier mal ein Beispiel wie ich es mache.

Log Tabelle:
CREATE TABLE [dbo].[unt_log](
	[pk] UNIQUEIDENTIFIER NOT NULL,
	[fk_unt] UNIQUEIDENTIFIER NOT NULL,
	[datum] DATETIME NOT NULL,
	[benutzer] VARCHAR(20) NOT NULL,
	[spalte] VARCHAR(40) NOT NULL,
	[aktion] VARCHAR(10) NOT NULL,
	[neu] VARCHAR(80) NULL,
	[neu_datum] DATETIME NULL,
	[neu_key] UNIQUEIDENTIFIER NULL,
	[alt] VARCHAR(80) NULL,
	[alt_datum] DATETIME NULL,
	[alt_key] UNIQUEIDENTIFIER NULL
	);

ALTER TABLE [dbo].[unt_log] ADD CONSTRAINT unt_log_pk PRIMARY KEY(pk);

Trigger-Code für jede Spalte:
	IF		UPDATE(bis)
	BEGIN
		INSERT INTO unt_log(pk,fk_unt,benutzer,datum,spalte,aktion,neu,alt,neu_datum,alt_datum)
		SELECT	newid() AS pk,
				i.pk AS fk_unt,
				isnull(i.lasttrigger,i.lastuser) AS benutzer,
				getdate() AS datum,
				'unt.bis' AS spalte,  
				( CASE WHEN i.pk IS NOT NULL AND d.pk IS NOT NULL THEN	'Update'  
				  WHEN i.pk IS NOT NULL AND d.pk IS NULL THEN 'Insert' END ) AS aktion,  
				convert(CHAR(10),i.bis,104) AS neu,
				convert(CHAR(10),d.bis,104) AS alt,
				i.bis AS neu_datum,
				d.bis AS alt_datum
		FROM	INSERTED i
		FULL JOIN DELETED d ON i.pk = d.pk
		WHERE	i.bis IS NOT NULL
		AND		d.bis IS NULL
		OR		d.bis IS NOT NULL
		AND		i.bis IS NULL
		OR		i.bis != d.bis
	END
Jedes mal wenn sich ein Wert in einer Spalte ändert wird der alte und der neue Wert geloggt (als Text). Zusätzlich wird bei Datumswerten und Uniqueidentifiern in einer seperaten Spalte geloggt für Auswertungen. Das erzeugt natürlich eine Menge Daten, ist also je nach Art der Daten vielleicht sinnvoll oder nicht.
Member: BirdyB
BirdyB Jan 04, 2017 at 08:20:50 (UTC)
Goto Top
Super, vielen Dank für deinen Code. Bei mir wird das ganze etwas reduzierter ausfallen. Es geht bei uns um die Auftragstabelle. Zu dieser haben wir ein Dispositions-Log ergänzt, wo die Disponenten manuell Vorkommnisse eintragen können, Wo das System aber auch eingehende Statusmeldungen von Fahrzeugen, etc selbst verarbeitet und hineinschreibt.
Der jetzige Wunsch besteht eben darin, falls ein Mitarbeiter das Einsatzdatum oder das zuständige Personal ändert auch einen Eintrag dort zu machen, damit es nachvollziehbar ist.