none
Probleme mit Triggern mit Update-Kommandos RRS feed

  • Frage

  • Hallo Experten,

    derzeit verwende ich in einem unserer SSIS-Projekte eine "OLE DB Destination" mit dem Data Access Mode "Table or view", um Daten aus einem Excel Sheet in eine DB-Tabelle einzupflegen. Dies funktioniert auch einwandfrei.

    Hinter der Tabelle steht ein InsteadOf-Trigger. Dieser nimmt hier- und dort ein paar Updates an der Trigger-Tabelle vor.

    Mein Problem ist hierbei, dass nicht alle Updates sauber durchlaufen, wenn der Trigger durch einen Insert über das SSIS-Projekt gefeuert wird. Irgendwas scheint die Updates zu blockieren. Möglicherweise hat jemand von Euch eine Idee, was der Grund sein könnte? Ich wäre jedenfalls dankbar für jede Hilfe.

    Gruss

    Maurice



    • Bearbeitet Moe1980 Mittwoch, 10. April 2013 15:52
    Mittwoch, 10. April 2013 15:51

Antworten

  •  Wenn ich einzelne Inserts vornehme, z.B.

    Da ist schon mal das grundlegende Problem; der Trigger wird per Transaktion gefeuert und nicht je einzelnem Datensatz. Das wiederum bedeutet, das die virtuelle Tabelle "inserted" 1 - n Datensätze enthalten kann; in Deinem Trigger-Code gehst Du fest davon aus, das immer nur ein Datensatz vorhanden ist.

    Du musst Deinen Trigger so umschreiben, das es eben 1-n Datensätze behandeln kann.


    Olaf Helper

    Blog Xing

    • Als Antwort markiert Moe1980 Mittwoch, 10. April 2013 16:41
    Mittwoch, 10. April 2013 16:15
  • Kann man den SSIS vielleicht so konfigurieren, dass er in diesem Fall keine Transaktionen verwendet?

    In relationalen Datenbanken werden immer Transaktionen verwendet, auch wenn man sie nicht explizit startet; anders könnte man auch nicht ACID sicher stellen.

    In SSIS kannst Du das Verhalten in Datenziel (Destination) steuern mit:


    Olaf Helper

    Blog Xing

    • Als Antwort markiert Moe1980 Mittwoch, 10. April 2013 16:41
    Mittwoch, 10. April 2013 16:34

Alle Antworten

  • Hallo Maurice,

    ohne den Triggercode zu sehen, ist das wohl eher ein Fall für die Glaskugel.

    Oftmals werden Trigger falsch programmiert, nämlich unter der Annahme, es gäbe nur einen Datensatz in inserted, bzw. deleted. Wenn man dann die Daten aus diesen Tabellen mit den Daten der Originaltabelle verbindet, fehlen dann einige Datensätze, falls bei einem DML Befehl mehrere Datensätze eingefügt/aktualisiert/gelöscht werden.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Mittwoch, 10. April 2013 15:57
    Moderator
  • Hallo Maurice,

    nur anhand der verbalen Beschreibung wird hier niemand das Problem nachvollziehen können.

    Ein paar mehr Details, wie Tabellen Design, Trigger Code (Snipplet) und Details zum SSIS Package sind da schon nötig.


    Olaf Helper

    Blog Xing


    Mittwoch, 10. April 2013 15:59
  • Ich verwende derzeit SSIS 2008 für die Entwicklung unserer Projekte. Es gibt eine History-Tabelle, die bei neuen Einträgen aktualisiert werden soll. Falls ein Eintrag bereits existiert, wird zuerst geprüft, ob ein neuer Eintrag erstellt oder ob zuerst vorhandene Datensätze aktualisiert werden sollen.
    Mittwoch, 10. April 2013 16:13
  •  Wenn ich einzelne Inserts vornehme, z.B.

    Da ist schon mal das grundlegende Problem; der Trigger wird per Transaktion gefeuert und nicht je einzelnem Datensatz. Das wiederum bedeutet, das die virtuelle Tabelle "inserted" 1 - n Datensätze enthalten kann; in Deinem Trigger-Code gehst Du fest davon aus, das immer nur ein Datensatz vorhanden ist.

    Du musst Deinen Trigger so umschreiben, das es eben 1-n Datensätze behandeln kann.


    Olaf Helper

    Blog Xing

    • Als Antwort markiert Moe1980 Mittwoch, 10. April 2013 16:41
    Mittwoch, 10. April 2013 16:15
  • Seltsamerweise tritt das Problem auch dann auf, wenn ich immer nur einen einzigen Datensatz behandle. Da dürfte doch eigentlich auch eine Transaktion nicht viel ausmachen. Was SSIS daraus macht, ist aus meiner Sicht noch etwas schwammig.

    Hier noch mal kurz mein Vorgehen:

    1. SSIS-Projekt wird gestartet. In der Excel-Datei ist nur ein Eintrag vorhanden. Der Eintrag wird vorgenommen. Der Trigger muss hier noch kein Update vornehmen.

    2. Der Task ist durchgelaufen und wird mit der nächsten Datei mit einem ähnlichen Eintrag gestartet. Hierbei muss der Trigger noch immer kein Update vornehmen.

    3. Wieder ist der Task durch. Er wird mit einer dritten Datei mit ebenfalls dem Datensatz in abgewandelter Form neu gestartet. Nun sollte der Update der Vorgänger-Datensätze erfolgen. Nur einer der beiden Datensätze wird allerdings aktualisiert.

    Wenn ich das ganze manuell mache:

    1. Manuell wird Datensatz1 aus Datei 1 per Insert-Statement in die Historisierungstabelle eingetragen

    2. Manuell wird Datensatz2 aus Datei 2 per Insert-Statement in die Historisierungstabelle eingetragen

    3. Manuell wird Datensatz3 aus Datei 3 per Insert-Statement in die Historisierungstabelle eingetragen

    Nachdem die Eintragungen erfolgt sind, ist das Update abgeschlossen.

    Kann man den SSIS vielleicht so konfigurieren, dass er in diesem Fall keine Transaktionen verwendet?

    • Bearbeitet Moe1980 Mittwoch, 10. April 2013 16:24
    Mittwoch, 10. April 2013 16:18
  • Hallo Maurice,

    erst mal vielen Dank für Eure schnellen Antworten. Mein Trigger funktioniert an sich. Wenn ich einzelne Inserts vornehme, z.B.

    dann funktioniert das auch alles. Allerdings wird beim Updaten immer der Fehler begangen, dass nur einer der Datensätze aktualisiert wird, anstatt alle, die den Kriterien entsprechen.

    Es geht hier also wirklich nur um das Update-Kommando, welches über den SSIS scheinbar nur eben einen Datensatz aktualisiert.

    Das ist eben genau das, was ich meinte. SSIS kann dafür nichts, "Schuld" hat IMHO die falsche Programmierung deines Triggers. Du darfst nicht erwarten, dass nur ein Datensatz kommt. Das kann man auch selbst ausprobieren, indem man bspw.:

    INSERT <Tabelle>( <Spalte> ) VALUES ( 'Wert1' ), ( 'Wert2' )
    

    ausführt.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Mittwoch, 10. April 2013 16:20
    Moderator
  • Hättest Du einen Tipp für mich, was ich da machen könnte? Wie sollte aus Deiner Sicht die Abarbeitung in diesem Fall erfolgen?

    Es handelt sich doch um drei verschiedene Transaktionen, wenn ich dreimal das gleiche SSIS-Projekt starte. Somit ist das für mich keine Transaktion mit mehreren Insert-Befehlen.

    • Bearbeitet Moe1980 Mittwoch, 10. April 2013 16:33
    Mittwoch, 10. April 2013 16:28
  • Kann man den SSIS vielleicht so konfigurieren, dass er in diesem Fall keine Transaktionen verwendet?

    In relationalen Datenbanken werden immer Transaktionen verwendet, auch wenn man sie nicht explizit startet; anders könnte man auch nicht ACID sicher stellen.

    In SSIS kannst Du das Verhalten in Datenziel (Destination) steuern mit:


    Olaf Helper

    Blog Xing

    • Als Antwort markiert Moe1980 Mittwoch, 10. April 2013 16:41
    Mittwoch, 10. April 2013 16:34
  • Danke für den Hinweis. Leider verfügt unser SSIS 2008 nur über solche Optionen, wenn wir fast load verwenden. Beim data access mode "Table or View" haben wir diese Möglichkeit nicht.
    Mittwoch, 10. April 2013 16:37
  • Okay, nun funktioniert es. Den data access mode habe ich nun auf "Table or View - fast load" umgestellt, wobei ich den Haken bei "Table lock" entfernt und "Rows per batch" auf 1 gestellt habe. Nun funktioniert es wie gewünscht. Wahrscheinlich liegt es eher an einem Table lock, als an der Transaktion. Jedenfalls get es nun. Vielen Dank für Eure schnelle Hilfe!! 
    • Bearbeitet Moe1980 Mittwoch, 10. April 2013 16:45
    Mittwoch, 10. April 2013 16:44
  • und "Rows per batch" auf 1 gestellt habe. Nun funktioniert es wie gewünscht.

    Hallo Maurice,

    das sollte Dich aber bitte nicht daran "hindern", Deinen Trigger zu korrigieren, damit er unter allen Umständen funktioniert.

    Eine einfache Modifikation wäre, ohne den restlichen Code anpassen zu müssen, die Datensätze aus "inserted" per Cursor abzuarbeiten; dabei werden die Daten auch in Variablen geladen. Du müsstest also nur eine Schleife um den Code bilden, der Rest kann so unverändert bleiben.


    Olaf Helper

    Blog Xing

    Mittwoch, 10. April 2013 16:55