Benutzer mit den meisten Antworten
Trigger- Daten in eine Tabelle eingeben

Frage
-
Hallo Liebe Leute,
könnt ihr mir sagen, was an diesem Trigger nicht stimmt?
if (OBJECT_ID ('t_reich_arm', 'T')) is not null
drop trigger t_reich_arm
go
create trigger t_reich_arm on personal
after insert
as
Declare @geld int
set @geld = (select verdienst from inserted)
IF @geld >= 2500
insert into reich (vorname, verdienst)
select I.vorname, I.verdienst
from inserted I
else
insert into arm (vorname, verdienst)
select I.vorname, I.verdienst
from inserted I
Wenn ich die Daten in die Tabelle Personal eingebe, dann sehe ich ordnungsgemäß alle Daten. In den Tabellen reich und arm sind keine Daten vorhanden. Die Abfrage wird auch fehlerlos abgeschlossen.
Was habe ich bei dem Trigger falsch gemacht.
Viele Grüsse:
Arek
Arek
Antworten
-
Hallo Arek,
grundsätzlich funktioniert es, es sind aber die typischen Basic-Fehler enthalten.
1. Objekt Kürzel von Triggern ist TR, nicht einfach nur T =>
if (OBJECT_ID ('t_reich_arm', 'TR')) is not null
2. Ein Trigger feuert je Transaktion, nicht je Datensatz, Dein Trigger geht aber davon aus, das es nur einen Datensatz gibt. Es könnte sein, das 2 Datensätze mit einmal Verdienst < 2500 und einmal mit > 2500 eingefügt wird; dann macht Dein Trigger irgendwas, nur nicht gerade das gewünschte.
Leg mal eine neue Testdatenbank an und probiere dort mal folgendes Skript aus:
CREATE TABLE dbo.personal (vorname varchar(30), verdienst int); CREATE TABLE dbo.reich (vorname varchar(30), verdienst int); CREATE TABLE dbo.arm (vorname varchar(30), verdienst int); GO create trigger t_reich_arm on dbo.personal after insert as Declare @geld int set @geld = (select verdienst from inserted) IF @geld >= 2500 insert into reich (vorname, verdienst) select I.vorname, I.verdienst from inserted I else insert into arm (vorname, verdienst) select I.vorname, I.verdienst from inserted I GO INSERT INTO dbo.personal (vorname, verdienst) VALUES ('Olaf', 1234); GO SELECT * FROM dbo.personal; SELECT * FROM dbo.arm; SELECT * FROM dbo.reich; GO -- Mulit Insert INSERT INTO dbo.personal (vorname, verdienst) VALUES ('Peter', 2345), ('Maria', 3333); GO SELECT * FROM dbo.personal; SELECT * FROM dbo.arm; SELECT * FROM dbo.reich;
Übrigens, ist in Deiner Tabelle "Verdienst" ein Integer Wert, wie im Trigger, oder doch eher ein Dezimal/Money Typ?
Olaf Helper
[ Blog] [ Xing] [ MVP]- Als Antwort vorgeschlagen Christoph Muthmann Dienstag, 17. Juni 2014 06:50
- Als Antwort markiert Ionut DumaModerator Donnerstag, 3. Juli 2014 13:23
-
Hallo Arek,
neben der von Olaf gegebenen Antwort:
Ein Trigger ist eigentlich überflüssig, denn das gleich könnten zwei Sichten leisten:
CREATE VIEW dbo.Personal_Reich AS SELECT Vorname, Verdienst FROM dbo.Personal WHERE Verdienst >= 2500.0; GO CREATE VIEW dbo.Personal_Arm AS SELECT Vorname, Verdienst FROM dbo.Personal WHERE Verdienst < 2500.0; GO
dann gibt es auch kein Problem, wenn sich die Verdienst mal ändern.
Deswegen nur der Vollständigkeit halber eine Variante, die auf MERGE setzt, und Probleme mit mehreren Zeilen bzw. Veränderungen vermeidet:
CREATE TABLE dbo.Personal ( Vorname varchar(20) NOT NULL, Verdienst decimal(10, 2) NOT NULL); CREATE TABLE dbo.Arm( Vorname varchar(20), Verdienst decimal(10, 2)); CREATE TABLE dbo.Reich( Vorname varchar(20), Verdienst decimal(10, 2)); GO CREATE TRIGGER dbo.TR_Personal_Insert ON dbo.Personal AFTER INSERT, UPDATE AS SET NOCOUNT ON; MERGE dbo.Reich AS target USING (SELECT Vorname, Verdienst FROM inserted) AS source(Vorname, Verdienst) ON target.Vorname = source.Vorname -- War vorhanden, jedoch zu wenig WHEN MATCHED AND source.Verdienst < 2500.0 THEN DELETE WHEN MATCHED AND source.Verdienst >= 2500.0 THEN UPDATE SET Verdienst = source.Verdienst WHEN NOT MATCHED AND source.Verdienst >= 2500.0 THEN INSERT (Vorname, Verdienst) VALUES (source.Vorname, source.Verdienst); MERGE dbo.Arm AS target USING (SELECT Vorname, Verdienst FROM inserted) AS source(Vorname, Verdienst) ON target.Vorname = source.Vorname -- War vorhanden, jedoch zu wenig WHEN MATCHED AND source.Verdienst >= 2500.0 THEN DELETE WHEN MATCHED AND source.Verdienst < 2500.0 THEN UPDATE SET Verdienst = source.Verdienst WHEN NOT MATCHED AND source.Verdienst < 2500.0 THEN INSERT (Vorname, Verdienst) VALUES (source.Vorname, source.Verdienst); GO INSERT INTO Personal (Vorname, Verdienst) VALUES ('Alfred', 1000), ('Bernhard', 2500), ('Cäsar', 2000), ('Detlef', 2499.99), ('Egon', 3000); SELECT 'Arm:', * FROM Arm; SELECT 'Reich:', * FROM Reich; UPDATE Personal SET Verdienst = CASE WHEN Verdienst > 2500.0 THEN Verdienst - 100.0 ELSE Verdienst + 100.0 END; SELECT 'Nun Arm:', * FROM Arm; SELECT 'Nun Reich:', * FROM Reich; GO
Den DELETE Trigger habe ich mal weggelassen, der sollte kein Kunststück sein ;)
Sinnvoller wäre im übrigen eine ID, denn Namen können sich ändern.
Gruß Elmar
- Als Antwort vorgeschlagen Christoph Muthmann Dienstag, 17. Juni 2014 06:50
- Als Antwort markiert Ionut DumaModerator Donnerstag, 3. Juli 2014 13:23
Alle Antworten
-
Hallo Arek,
grundsätzlich funktioniert es, es sind aber die typischen Basic-Fehler enthalten.
1. Objekt Kürzel von Triggern ist TR, nicht einfach nur T =>
if (OBJECT_ID ('t_reich_arm', 'TR')) is not null
2. Ein Trigger feuert je Transaktion, nicht je Datensatz, Dein Trigger geht aber davon aus, das es nur einen Datensatz gibt. Es könnte sein, das 2 Datensätze mit einmal Verdienst < 2500 und einmal mit > 2500 eingefügt wird; dann macht Dein Trigger irgendwas, nur nicht gerade das gewünschte.
Leg mal eine neue Testdatenbank an und probiere dort mal folgendes Skript aus:
CREATE TABLE dbo.personal (vorname varchar(30), verdienst int); CREATE TABLE dbo.reich (vorname varchar(30), verdienst int); CREATE TABLE dbo.arm (vorname varchar(30), verdienst int); GO create trigger t_reich_arm on dbo.personal after insert as Declare @geld int set @geld = (select verdienst from inserted) IF @geld >= 2500 insert into reich (vorname, verdienst) select I.vorname, I.verdienst from inserted I else insert into arm (vorname, verdienst) select I.vorname, I.verdienst from inserted I GO INSERT INTO dbo.personal (vorname, verdienst) VALUES ('Olaf', 1234); GO SELECT * FROM dbo.personal; SELECT * FROM dbo.arm; SELECT * FROM dbo.reich; GO -- Mulit Insert INSERT INTO dbo.personal (vorname, verdienst) VALUES ('Peter', 2345), ('Maria', 3333); GO SELECT * FROM dbo.personal; SELECT * FROM dbo.arm; SELECT * FROM dbo.reich;
Übrigens, ist in Deiner Tabelle "Verdienst" ein Integer Wert, wie im Trigger, oder doch eher ein Dezimal/Money Typ?
Olaf Helper
[ Blog] [ Xing] [ MVP]- Als Antwort vorgeschlagen Christoph Muthmann Dienstag, 17. Juni 2014 06:50
- Als Antwort markiert Ionut DumaModerator Donnerstag, 3. Juli 2014 13:23
-
Hallo Arek,
neben der von Olaf gegebenen Antwort:
Ein Trigger ist eigentlich überflüssig, denn das gleich könnten zwei Sichten leisten:
CREATE VIEW dbo.Personal_Reich AS SELECT Vorname, Verdienst FROM dbo.Personal WHERE Verdienst >= 2500.0; GO CREATE VIEW dbo.Personal_Arm AS SELECT Vorname, Verdienst FROM dbo.Personal WHERE Verdienst < 2500.0; GO
dann gibt es auch kein Problem, wenn sich die Verdienst mal ändern.
Deswegen nur der Vollständigkeit halber eine Variante, die auf MERGE setzt, und Probleme mit mehreren Zeilen bzw. Veränderungen vermeidet:
CREATE TABLE dbo.Personal ( Vorname varchar(20) NOT NULL, Verdienst decimal(10, 2) NOT NULL); CREATE TABLE dbo.Arm( Vorname varchar(20), Verdienst decimal(10, 2)); CREATE TABLE dbo.Reich( Vorname varchar(20), Verdienst decimal(10, 2)); GO CREATE TRIGGER dbo.TR_Personal_Insert ON dbo.Personal AFTER INSERT, UPDATE AS SET NOCOUNT ON; MERGE dbo.Reich AS target USING (SELECT Vorname, Verdienst FROM inserted) AS source(Vorname, Verdienst) ON target.Vorname = source.Vorname -- War vorhanden, jedoch zu wenig WHEN MATCHED AND source.Verdienst < 2500.0 THEN DELETE WHEN MATCHED AND source.Verdienst >= 2500.0 THEN UPDATE SET Verdienst = source.Verdienst WHEN NOT MATCHED AND source.Verdienst >= 2500.0 THEN INSERT (Vorname, Verdienst) VALUES (source.Vorname, source.Verdienst); MERGE dbo.Arm AS target USING (SELECT Vorname, Verdienst FROM inserted) AS source(Vorname, Verdienst) ON target.Vorname = source.Vorname -- War vorhanden, jedoch zu wenig WHEN MATCHED AND source.Verdienst >= 2500.0 THEN DELETE WHEN MATCHED AND source.Verdienst < 2500.0 THEN UPDATE SET Verdienst = source.Verdienst WHEN NOT MATCHED AND source.Verdienst < 2500.0 THEN INSERT (Vorname, Verdienst) VALUES (source.Vorname, source.Verdienst); GO INSERT INTO Personal (Vorname, Verdienst) VALUES ('Alfred', 1000), ('Bernhard', 2500), ('Cäsar', 2000), ('Detlef', 2499.99), ('Egon', 3000); SELECT 'Arm:', * FROM Arm; SELECT 'Reich:', * FROM Reich; UPDATE Personal SET Verdienst = CASE WHEN Verdienst > 2500.0 THEN Verdienst - 100.0 ELSE Verdienst + 100.0 END; SELECT 'Nun Arm:', * FROM Arm; SELECT 'Nun Reich:', * FROM Reich; GO
Den DELETE Trigger habe ich mal weggelassen, der sollte kein Kunststück sein ;)
Sinnvoller wäre im übrigen eine ID, denn Namen können sich ändern.
Gruß Elmar
- Als Antwort vorgeschlagen Christoph Muthmann Dienstag, 17. Juni 2014 06:50
- Als Antwort markiert Ionut DumaModerator Donnerstag, 3. Juli 2014 13:23