Sequenzielle SQL-Einfügungen, wenn sie von CROSS APPLY ausgelöst werden

8

Dieser Prozess hat mehrere Schritte, die sich in verschiedenen Tabellen einer Datenbank widerspiegeln:

Produktion - & gt; UPDATE für die Inventory-Tabelle mit etwas wie

%Vor%

Das obige füttert eine Protokolltabelle mit einem TRIGGER wie folgt:

%Vor%

Und schließlich sollte jedes Update INSERT eine Zeile in eine Finanztabelle aufnehmen, die ich oben zu TRIGGER hinzugefügt habe:

%Vor%

Das Problem ist mit dieser Zeile:

%Vor%

soll den letzten Kontostand berechnen. Da aber CROSS APPLY alle INSERTS als Stapel behandelt, wird die Berechnung aus dem gleichen letzten Datensatz ausgeführt, und ich erhalte einen falschen Saldo. Beispiel:

%Vor%

Was wäre der Weg, um das zu lösen? Ein Trigger für die Tabelle FINS anstatt für die Saldenberechnung?

    
greener 19.02.2014, 22:01
quelle

6 Antworten

2

Die vorhandene Logik in Ihrer Abfrage verstehen

UPDATE -Anweisung wird trigger nur einmal für einen Satz oder einen Stapel auslösen, die Join-Bedingungen erfüllen. Die eingefügte Anweisung enthält alle Datensätze, die aktualisiert werden. Dies liegt an der BATCH-Verarbeitung, nicht wegen CROSS APPLY , sondern wegen UPDATE .

In dieser Abfrage von Ihnen

%Vor%

Für jede CORP von einer Äußeren Abfrage wird die gleiche BAL zurückgegeben.

%Vor%

Das heißt, Ihre innere Abfrage wird jedes Mal durch 1000 ersetzt (Wert, den Sie in Ihrem Beispiel verwendet haben) CORP = 'XYZ'

%Vor%

Jetzt enthält Ihre eingefügte Anweisung alle Datensätze, die eingefügt werden. Also werden die Kosten jedes Eintrags um 1000 subtrahiert. Daher erhalten Sie ein unerwartetes Ergebnis.

Lösungsvorschlag

Nach meinem Verständnis wollen Sie eine kumulative Häufigkeit Art der Sache berechnen. Oder letzte laufende Summe

Datenvorbereitung für Problemstellung. Benutzte meine Dummy-Daten, um dir eine Idee zu geben.

%Vor%

Alternative Logik zum Abziehen der Kosten vom letzten laufenden Kontostand.

%Vor%

Ausgabe

%Vor%

Sie müssen Ihre Spalten ein wenig twittern, um diese Funktionalität in Ihren Auslöser zu bekommen.

    
Shantanu Gupta 26.02.2014, 20:03
quelle
0

Ich denke, Sie können einen Trigger auf den Flossen versuchen.

Sie können IDENT_CURRENT ('Table') verwenden, um den letzten Primärschlüssel aus der Tabelle zu übernehmen und eine Auswahl zu treffen.

Ich denke, es ist besser als "Top 1 auswählen".

Um den letzten Bilanzwert zu erhalten, setzen Sie eine Variable last_bal = wählen Sie bal aus FINS, wobei primary_key = Ident_Current ("FINS")

ist     
Icaroo 26.02.2014 12:04
quelle
0

gut

first sql ist ein Spiel, in dem es mit Gruppen oder besser gesagt mit "set" funktioniert, also musst du immer darüber nachdenken.

Wenn Sie mit einem einfachen Gegenstand arbeiten, ist es richtig, es ist vielleicht besser, sich an

zu wenden %Vor%     
Carlos Cocom 26.02.2014 16:54
quelle
0

Ich gebe Ihnen keine genaue Abfrage. Vergessen Sie einen Moment den Auslöser. Weil Sie Ihre Abfrage nicht testen können. Ich schlage vor, Output-Klausel zu verwenden. Dies wird Ihnen helfen, die richtige Abfrage zu erstellen und zu testen. Diese Abfrage läuft in Ordnung, (wenn Sie Merge verwenden können, dann ist das am besten).

%Vor%

Sie haben jetzt einen Wert in die Tabellenvariable @t

eingefügt %Vor%

Überprüfen Sie diese Abfrage bis hierhin. Denken Sie an die Optimierung oder triggern Sie später. Ich denke, dass ich guten Vorschlag gab. Und ich denke Subtraktion ist kein Problem. Ich sage, alles in Ausgangsklausel zu setzen und die Frage zu analysieren und sie zu prüfen.

Sie können CTE auch innerhalb des Triggers verwenden, aber wie testen Sie es?

%Vor%     
KumarHarsh 27.02.2014 09:49
quelle
0

So etwas ist nicht vollständig.

%Vor%     
Icaroo 27.02.2014 19:11
quelle
0

Wenn Sie, ähnlich wie bei @ Shantanus Methode, eine Sequenz mit inserted verknüpfen könnten, könnte die virtuelle Tabelle, die dem Trigger zugeordnet ist, dies tun, indem Sie alle Kosten, die vor dem aktuellen Datensatz liegen, subtrahieren.

Dies könnte durch Hinzufügen einer Zeilenversion zu STOR erreicht werden, die automatisch mit jedem Löschen aktualisiert wird.

Dann statt:

((SELECT TOP 1 BAL FROM FINS WHERE COMPANY = CORP ORDER BY TS DESC)- COST) from inserted ...

Machen Sie die Zeilenversion RV, und:

%Vor%

Sollte tun, was Sie wollen. Du könntest dies mit einem Zeitstempel machen, der mehr auffindbar ist als CURRENT_TIMESTAMP, der, glaube ich, nur auf Sekunden reduziert wird, aber das erfordert, dass du ihn in der UPDATE-Anweisung aktualisierst. Die Zeilenversion kann Probleme mit Ihren STOR-INSERT-Anweisungen verursachen.

    
albe 27.02.2014 22:26
quelle

Tags und Links