Trigger After Insert Problem

KitKat

Neuer Benutzer
Beiträge
3
Hallo Zusammen,
bis vor ein paar Wochen hatte ich mit SQL so rein gar nichts zu tun.
Jetzt hab ich mich da ein bisschen rein gearbeitet aber letztlich wie so oft komme ich alleine nicht weiter.
Ich habe einen SQLServer2008R2.
Dieser Hostet eine Datenbank für ein Antivirenssystem,
Das Schema, alle Prozeduren usw. unterliegen der Herstellerlizenz.

Das Ziel ist ein Risikoevent an unser Tickesystem zu senden.
das Ticketsystem kann über eine Schnittstelle mit einem XML gefüttert werden, dass zwingend UTF-8 Benötigt.
MSSQL kann aber nur UTF-16.
Ich habe eine Query erstellt, die alle relevanten Daten enthält. Ein Kollege hat hierzu ein passenden PowershellScript geliefert.
Das PS wird per SQL-Agent-Job und cmdexec angesprochen.
Wird er Job manuell ausgeführt wird ein Ticket erstellt.
Ich wollte einen Trigger erstellen. (Der Hersteller macht hier keine Probleme)

Ich hab mir die Schemareferenz besorgt und Tabellen identifiziert, die für den Trigger in Frage kommen.
Sobald ich jedoch einen Trigger auf egal welche Tabelle setze kommen in der Tabelle keinerlei Daten mehr an.
Nicht einmal wenn ich den Trigger disable und er einfach nur da ist.
Da ich dieses Problem nicht lösen kann habe ich einen Job erstellt, der einfach nur Daten aus einer DB in eine andere DB kopiert und das im 45 Sekunden Takt.
Das wird nicht sonderlich Performant werden aber darüber soll ich mir keine Gedanken machen


Code:
Use xxxxx
Begin

INSERT INTO Test.dbo.TAB_XXX_TEST
SELECT  TOP(1)
   V_AL.idx
,  V.VIRUSNAME
,  VC.COMPUTER_NAME
,  V_al.Description
,  G.NAME as 'Client-Group'
,  D.Name as 'AV-Domain'
,  VC.IP_ADDR1_TEXT
,  V_AL.Filepath
,  V_AL.Source
,  AA.ACTUALACTION
,  V_AL.Alertdatetime
,  V_AL.Alertinserttime
,  V_AL.ALERTENDDATETIME

From    dbo.V_ALERTS as V_AL
        inner Join dbo.V_VIRUS as V on V_AL.VIRUSNAME_IDX = V.VIRUSNAME_IDX
        inner join dbo.ACTUALACTION as AA on V_AL.ACTUALACTION_IDX = AA.ACTUALACTION_IDX
        inner join  dbo.V_SEM_COMPUTER as VC on V_AL.COMPUTER_IDX = Computer_ID
        inner join dbo.V_GROUPS as G on V_AL.CLIENTGROUP_IDX = G.ID
        inner Join dbo.V_DOMAINS as D on G.DOMAIN_ID = D.ID
      
Where V_AL.IDX not in (SELECT idx FROM Test.dbo.TAB_ITSM_TEST)

Group by
           D.Name
        ,  V_AL.Alertdatetime
        ,  V_AL.Filepath
        ,  V_AL.Description
        ,  V_AL.ALERTENDDATETIME
        ,  V_AL.Alertinserttime
        ,  AA.ACTUALACTION
        ,  VC.COMPUTER_NAME
        ,  G.NAME
        ,  V_AL.Source
        ,  VC.IP_ADDR1_TEXT
        ,  V_AL.ALERT_IDX, al.idx
        ,  V.VIRUSNAME
      
order by ALERTDATETIME desc
end

Gleichzeitig wird geprüft ob eine IDX bereits vorhanden ist.
"Where Al.IDX not in (SELECT idx FROM Test.dbo.TAB_ITSM_TEST)"
Wenn nicht, soll der Datensatz kopiert werden.
Erstaunlicherweise funktioniert das völlig Problemlos.


Jetzt möchte ich, auf dieser Tabelle den Trigger setzten.
Der Trigger soll nach Insert einen Job ausführen.
Egal was ich bisher geschrieben habe, immer wenn der CopyJob läuft (auf dem Testssystem alle 45 Sekunden)
startet auch der Job der das PowerShellscript ausführt.
Jedes mal, egal ob ein Datensatz eingefügt wurde oder nicht.
Das bedeutet, ich generiere Tickets alle 45 Sekunden egal ob das Event bereits vorhanden ist oder nicht.
(das ist für mich schon ein echter Fortschritt ;))

Ich bin mir sicher das Problem sitzt VOR der Datenbank.
Ich dachte es wäre ganz einfach sowas wie:

Code:
USE [Test]
GO
/****** Object:  Trigger [dbo].[TR_ITSM_TEST]    Script Date: 04/29/2016 20:28:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:        <Author,,Name>
-- Create date: <Create Date,,>
-- Description:    <Description,,>
-- =============================================
ALTER TRIGGER [dbo].[TR_ITSM_TEST]
   ON  [dbo].[TAB_ITSM_TEST]
After insert
AS
BEGIN

  exec msdb.dbo.sp_start_job 'ITSM-Ticket_Job'

-- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here
END

Kann mir bitte jemand helfen, damit der Trigger nur dann den Job startet, wenn auch WIRKLICH ein Insert in den Table passiert ist?
 
Werbung:
Also zunächst mal finde ich das mit dem Trigger auf der UrsprungsDB komisch, läuft das System wirklich nicht wenn hier ein deaktivierter AFTER INSERT Trigger auf einer Tabelle liegt? Ich kann mir nicht vorstellen das der Hersteller hier "Maßnahmen zur Erkennung" eingebaut hat. Eventuell lohnt es sich, hier einfach nochmal nachzufragen.

Wenn du sowieso alle 45 Sekunden die Tabelle kopierst, wieso fragst du dann nicht alle 45 Sekunden nur die relevante Information in der DB ab und generierst direkt deine Meldung an dein Zielsystem? Ersetze dazu einfach deinen Copy Job mit dem Prozeduraufruf oder einem SQL Script das du regelmäßig aufrufst.

Dein gezeigter Trigger feuert tatsächlich immer, wenn die Tabelle angesprochen wird, auch wenn eigentlich keine Datensätze geschrieben werden weil dein Ausgangsselect keine Ergebnis-Zeilen liefert. Dieses Verhalten nervt mich auch momentan an einer Stelle. Du könntest folgendes probieren:
Code:
ALTER TRIGGER [dbo].[TR_ITSM_TEST]
ON  [dbo].[TAB_ITSM_TEST]
AFTER INSERT
AS
IF ( SELECT count(*) FROM INSERTED ) > 0
BEGIN
 
Hallo Ukulele,

erstmal vielen Dank für deine Antwort.
Ich hab das dann mal versucht, das Ergebnis ist leider identisch. Alle 45 Sekunden erstellt der Job ein Ticket.
Ich hab jetzt nochmal versucht einen Trigger auf eine der Basistabellen zu setzten. Da passiert dann aber überhaupt gar nichts mehr.
Ich erhalte nicht einmal mehr Notification Mails.
Dann hab ich versucht einen Instead Of Trigger auf einen View zu legen.

Das Blockiert zumindest nicht die Weiterverarbeitung. Es wird aber weder der Datensatz kopiert, noch startet der Job.

Also zunächst mal finde ich das mit dem Trigger auf der UrsprungsDB komisch, läuft das System wirklich nicht wenn hier ein deaktivierter AFTER INSERT Trigger auf einer Tabelle liegt? Ich kann mir nicht vorstellen das der Hersteller hier "Maßnahmen zur Erkennung" eingebaut hat. Eventuell lohnt es sich, hier einfach nochmal nachzufragen.

Das Gespräch mit meinem Techniker des Herstellers war in etwa so, dass ich vom Risk-Logfile im 30 Sekundentakt ein Dump erstellen kann. Daraus soll ich mich dann die relevanten Daten ziehen und weiter verarbeiten.
Das bringt mich aber auch nicht weiter. :-(

Wenn du sowieso alle 45 Sekunden die Tabelle kopierst, wieso fragst du dann nicht alle 45 Sekunden nur die relevante Information in der DB ab und generierst direkt deine Meldung an dein Zielsystem? Ersetze dazu einfach deinen Copy Job mit dem Prozeduraufruf oder einem SQL Script das du regelmäßig aufrufst.

Ich hab das noch nicht in betracht gezogen, weil ich mich damit noch nicht beschäftigt habe.
Ich hab also einfach noch nie eine Stored Procedure geschrieben....geschweige denn dass ich wüsste wie man die Aufruft...:confused:


Danke für die vielen Hinweise und Gedankenanregungen. Ich werde dann wohl erst nochmal meine Abende mit Lesen verbringen :)

Viele Grüße

KitKat
 
Es müsste nichtmal eine SP sein oder irgendein Code der in der DB liegt. Du könntest ein SQL Script auf dem Dateisystem ablegen und mit einem Windows Task über die Komandozeile aufrufen. Hier mal eine Beispiel-Bat-Datei:
Code:
"C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\SQLCMD.EXE" -S "SERVER\SQLEXPRESS" -U "Benutzer" -P "Passwort" -i "D:\Scripte\copy.sql"
Das PW für den User liegt allerdings im Klartext in der Bat-Datei. Den Inhalt von copy.sql kannst du dann frei gestalten. Die kann z.B. per Select nur relevante Daten abfragen und per INSERT in eine andere DB schreiben, je nach Anforderung.
 
Werbung:
Hallo Ukulele,

noch einmal vielen Dank.
Ich habe ehrlich gesagt nicht gewusst wie ich diese Woche noch weiter machen soll.
Manchmal hilft es einfach schon ein paar andere Ansätze auszuprobieren um auf neue Gedanken zu kommen.
Und das hast du geschafft :)

Ich hab heute aus meinem Copy Job eine SP erstellt.
Diese läuft nun als Job auf der Herstellerdatenbank und scheint auch nicht zu stören.

Mein Job der dann das Ticket erstellen soll wollte aber erstmal weiterhin nicht so wie ich.
Ich weiß gar nicht warum ich es gemacht habe, aber irgendwann hab ich aus dem Trigger den zu vorgeschlagen hast:

Code:
ALTER TRIGGER [dbo].[TR_ITSM_TEST]
ON [dbo].[TAB_ITSM_TEST]
AFTER INSERT
AS
IF ( SELECT count(*) FROM INSERTED ) > 0
BEGIN

einfach das hier gemacht:

Code:
ALTER TRIGGER [dbo].[Start_ITSM]
   ON  [dbo].[TAB_ITSM_TEST]
   AFTER INSERT, UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   IF ( SELECT count(1) FROM INSERTED ) > 0
exec msdb.dbo.sp_Start_job 'ITSM-Ticket_Job'
   
END

Und schon funktioniert alles so wie es soll.

Nochmal vielen Dank du warst mir eine große Hilfe :) :) :)

Viele Grüße
KitKat
 
Zurück
Oben