Benutzer mit den meisten Antworten
Datum vergleichen

Frage
-
Hey,
ich habe über einen Trigger einen Status zu setzten. Dieser ist von verschiedenen Eigenschaften in der Tabelle abhängig.
Eine IF/ELSE - Verzweigungen würde mich tierisch voranbringen, kann ich die verwenden und wenn ja wie? Im Moment mache ich x-UpdateStatements hintereinander, so dass das letzte trifft, das kann aber doch nicht Sinn und Zweck sein ODER???
Außerdem habe ich das Problem, dass ich ein Datum auf 21 Jahre und einen Tag prüfen muss. 21 Jahre ist kein Problem:
UPDATE Projekt SET Status = 'Erledigt' From Projekt Where Projekt.Anfang < (SELECT DATEADD(year, -21, GETDATE()))
aber was mache ich mit dem einen Tag extra?
Für Hilfe immer dankbar
motofish
Antworten
-
Hallo motofisch,
in der Form lässt sich das mit einem CASE Ausdruck erschlagen:
UPDATE dbo.Projekte SET StatusGL = CASE WHEN Projekte.Zuruecknahme = 1 OR Projekte.Anmeldetag < (DATEADD(day, -1,(DATEADD(year, -21, GETDATE()))) THEN 'Tot' WHEN Projekte.Nichtgk = 1 THEN 'Nichtigk. / Löschung' WHEN /*??? AktenExt. ???*/ Beschwerde = 1 THEN 'Beschwerde' WHEN Projekte.Einspruch = 1 IS NOT NULL THEN 'Einspruch' WHEN Projekte.Erteilungsdatum IS NOT NULL THEN 'Erteilt' WHEN Projekte.Anmeldetag IS NOT NULL THEN 'Angemeldet' ELSE 'Offen' END -- Für Trigger (INSERTED/UPDATED -- ID ist der Primary/Unique Key der Tabelle WHERE Projekte.ID IN (SELECT i.ID FROM inserted)
Ich habe die Reihenfolge umgedreht, da CASE WHEN von oben nach unten ausgewertet wird.
"Gewinnen" wird also der Ausdruck, der als erster zutrifft und wenn keiner der ELSE-Zweig.Für einen Trigger sollte zusätzlich INSERTED abgefragt werden.
Wobei Du diesen Ausdruck auch als Ausdrucks-Spalte in einer Sicht
oder selbst in der Tabelle hinterlegen kannst - wobei GETDATE() nicht
deterministisch ist und ich letzteres deswegen nicht empfehlen würde.Wenn man die Spalte nur gelegentlich sehen muß/will,
wäre eine Sicht einem Trigger vorzuziehen.Gruß Elmar
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 8. Juni 2010 14:47
-
Hallo motofisch,
der Tag ist erledigt, in dem man DATEADD zweimal verwendet (und das SELECT überflüssig):
WHERE Projekt.Anfang < DATEADD(Day, 1, DATEADD(year, -21, GETDATE()))
(wobei GETDATE() auch die aktuelle Uhrzeit enthält).
Allerdings ist eine Aktualisierungsabfrage in einem Trigger, die nicht auf inserted (oder deleted)
zurückgreift kaum zu empfehlen, da sie auf alle Zeilen (für die die Bedingung zutrifft) zugreift.
Das fordert Blockierungen und Deadlocks geradezu heraus.Um die Abfrage auf die veränderten Projekt-Zeilen zu beschränken,
ergänze die Bedingung um eine Abfrage auf den Primärschlüssel:WHERE Projekt.ID IN (SELECT i.id FROM inserted AS i) AND Projekt.Anfang < (SELECT DATEADD(year, -21, GETDATE()))
(vorausgesetzt der Trigger ist auf Projekt selber und die Primärschlüsselspalte heisst ID).Alle weitere Bedingungen kannst Du mit AND/OR und ggf. via weitere JOINS, CASE usw.
einbauen. Um das konkreter zu beschreiben, müsste man Deine Bedingungen kennen.Gruß Elmar
- Bearbeitet Elmar Boye Donnerstag, 27. Mai 2010 16:51 Format
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 8. Juni 2010 14:47
Alle Antworten
-
Hallo motofisch,
der Tag ist erledigt, in dem man DATEADD zweimal verwendet (und das SELECT überflüssig):
WHERE Projekt.Anfang < DATEADD(Day, 1, DATEADD(year, -21, GETDATE()))
(wobei GETDATE() auch die aktuelle Uhrzeit enthält).
Allerdings ist eine Aktualisierungsabfrage in einem Trigger, die nicht auf inserted (oder deleted)
zurückgreift kaum zu empfehlen, da sie auf alle Zeilen (für die die Bedingung zutrifft) zugreift.
Das fordert Blockierungen und Deadlocks geradezu heraus.Um die Abfrage auf die veränderten Projekt-Zeilen zu beschränken,
ergänze die Bedingung um eine Abfrage auf den Primärschlüssel:WHERE Projekt.ID IN (SELECT i.id FROM inserted AS i) AND Projekt.Anfang < (SELECT DATEADD(year, -21, GETDATE()))
(vorausgesetzt der Trigger ist auf Projekt selber und die Primärschlüsselspalte heisst ID).Alle weitere Bedingungen kannst Du mit AND/OR und ggf. via weitere JOINS, CASE usw.
einbauen. Um das konkreter zu beschreiben, müsste man Deine Bedingungen kennen.Gruß Elmar
- Bearbeitet Elmar Boye Donnerstag, 27. Mai 2010 16:51 Format
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 8. Juni 2010 14:47
-
Hallo Elmar,
vielen Dank für die Antwort.
Das mit den Deadlocks ist eines der Probleme, die ich durchaus sehe. Ich arbeite mich in die Thematik Trigger und Co. erst ein und gehe Schritt für Schritt vor. Ich habe gelesen, dass man auf den bearbeiteten Datensatz über die Tabelle inserted zugreifen kann. Damit könnte ich immer nur auf den Datensatz zugreifen, den ich benötige. Lt. Anleitung ist inserted auch im Fall des Updatetriggers zugreifbar.
Leider habe ich bisher noch NIE einen erfolgreichen Zugriff auf inserted mit anschließender Verwendung in dem Update-Statement geschafft.
Konkret:
meine Projekte haben die Stati 'Begonnen', 'in Arbeit', und 'Erledigt. Die Einträge werden gesetzt, wenn der Beginn 21 Jahre und 1 Tag zurückliegt -> Erledigt, wenn Bit 'unterwegs' gesetzt ist -> in Arbeit bzw. Wenn dies alles nicht und nur das Anfangsdatum eingetragen ist -> 'Begonnen'
Das ist ein sehr rudimentäres Beispiel, das aber in etwa mein Problem abbildet. Am liebsten würde ich jetzt mit If arbeiten, habe aber keine Möglichkeit in Triggern bzw. T-SQL gefunden. Ich könnte mir schon vorstellen, eine Stored Procedure zu schreiben, bin aber in dem Thema noch gar nicht drin. Sollte eigentlich erst später kommen.
Wenn hier noch ein Tipp möglich wäre, wie ich weiterkomme wäre klasse!
Danke
motofish
-
CREATE TRIGGER [dbo].[tr_StatusGL_Insert_Update] ON [dbo].[Projekte] FOR INSERT, UPDATE AS BEGIN SET NOCOUNT ON; Update dbo.Projekte SET StatusGL = 'Offen' Update dbo.Projekte SET StatusGL = 'Angemeldet' From dbo.Projekte Where Projekte.Anmeldetag IS NOT NULL Update dbo.Projekte SET StatusGL = 'Erteilt' From dbo.Projekte Where Projekte.Erteilungsdatum IS NOT NULL Update dbo.Projekte SET StatusGL = 'Einspruch' From dbo.ProjekteWhere Projekte.Einspruch = 1 Update dbo.Projekte SET StatusGL = 'Beschwerde' From dbo.Projekte Where AktenExt.Beschwerde = 1 Update dbo.Projekte SET StatusGL = 'Nichtigk. / Löschung' From dbo.Projekte Where Projekte.Nichtgk = 1 Update dbo.Projekte SET StatusGL = 'Tot' From dbo.Projekte Where Projekte.Zuruecknahme = 1 Update dbo.Projekte SET StatusGL = 'Tot' From dbo.Projekte Where Projekte.Anmeldetag < (DATEADD(day, -1,(DATEADD(year, -21, GETDATE()))) END
So sieht das nu bei mir im Moment aus und ist sicherlich nicht das gelbe vom Ei. Aber danke für die Ermutigung mit dem Anfängercode ...
Gruß
motofish
-
Hallo motofisch,
in der Form lässt sich das mit einem CASE Ausdruck erschlagen:
UPDATE dbo.Projekte SET StatusGL = CASE WHEN Projekte.Zuruecknahme = 1 OR Projekte.Anmeldetag < (DATEADD(day, -1,(DATEADD(year, -21, GETDATE()))) THEN 'Tot' WHEN Projekte.Nichtgk = 1 THEN 'Nichtigk. / Löschung' WHEN /*??? AktenExt. ???*/ Beschwerde = 1 THEN 'Beschwerde' WHEN Projekte.Einspruch = 1 IS NOT NULL THEN 'Einspruch' WHEN Projekte.Erteilungsdatum IS NOT NULL THEN 'Erteilt' WHEN Projekte.Anmeldetag IS NOT NULL THEN 'Angemeldet' ELSE 'Offen' END -- Für Trigger (INSERTED/UPDATED -- ID ist der Primary/Unique Key der Tabelle WHERE Projekte.ID IN (SELECT i.ID FROM inserted)
Ich habe die Reihenfolge umgedreht, da CASE WHEN von oben nach unten ausgewertet wird.
"Gewinnen" wird also der Ausdruck, der als erster zutrifft und wenn keiner der ELSE-Zweig.Für einen Trigger sollte zusätzlich INSERTED abgefragt werden.
Wobei Du diesen Ausdruck auch als Ausdrucks-Spalte in einer Sicht
oder selbst in der Tabelle hinterlegen kannst - wobei GETDATE() nicht
deterministisch ist und ich letzteres deswegen nicht empfehlen würde.Wenn man die Spalte nur gelegentlich sehen muß/will,
wäre eine Sicht einem Trigger vorzuziehen.Gruß Elmar
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 8. Juni 2010 14:47