Wie behebt man dieses Problem mit gespeicherten Prozeduren?

sql sqlbulkcopy sql-server

Frage

Ich habe 2 Tische. Die folgenden sind nur eine abgespeckte Version dieser Tabellen.

TableA
Id <pk> incrementing
Name varchar(50)

TableB
TableAId <pk> non incrementing
Name varchar(50)

Jetzt haben diese Tabellen eine Beziehung zueinander.

Szenario

Benutzer 1 kommt zu meiner Site und führt einige Aktionen durch (in diesem Fall fügt er Zeilen zu Tabelle A hinzu). Also verwende ich eine SqlBulkCopy alle diese Daten in Tabelle A.

Allerdings muss ich die Daten auch zu Tabelle B hinzufügen, aber ich kenne die neu erstellten IDs aus Tabelle A nicht, da SQLBulkCopy diese nicht zurückgibt.

Ich denke also an eine gespeicherte Prozedur, die alle IDs findet, die nicht in Tabelle B vorhanden sind, und fügt sie dann ein.

INSERT INTO TableB (TableAId , Name)
SELECT Id,Name FROM TableA as tableA
WHERE not exists( ...)

Dies bringt jedoch ein Problem mit sich. Ein Benutzer kann jederzeit etwas aus TableB löschen. Wenn also ein Benutzer eine Zeile löscht und dann ein anderer Benutzer vorbeikommt oder sogar derselbe Benutzer kommt und etwas an Tabelle A vornimmt, bringt meine gespeicherte Prozedur die gelöschte Zeile in Tabelle B zurück. Da es immer noch in Tabelle A, aber nicht in Tabelle B existiert, erfüllt es die Bedingung für die gespeicherte Prozedur.

Gibt es also eine bessere Möglichkeit, mit zwei Tabellen zu arbeiten, die aktualisiert werden müssen, wenn Bulk-Insert verwendet wird?

Akzeptierte Antwort

SQLBulkCopy verkompliziert das, daher würde ich eine Staging-Tabelle und eine OUTPUT-Klausel in Erwägung ziehen

Beispiel, in einer Mischung aus Client-Pseudocode und SQL

create SQLConnection

Create #temptable
Bulkcopy to #temptable

Call proc on same SQLConnection

proc:
   INSERT tableA (..)
   OUTPUT INSERTED.key, .. INTO TableB
   SELECT .. FROM #temptable

close connection

Anmerkungen:

  • Versuchbar wird lokal zur Verbindung und isoliert sein

  • Die Schreibvorgänge nach A und B werden atomar sein
  • Überlappende oder spätere Schreibvorgänge interessieren nicht, was später mit A und B passiert
  • den letzten Punkt betonend, werden A und B immer nur aus der Reihe von Zeilen in #temptable bevölkert

Alternative:

Fügen Sie A und B eine weitere Spalte namens sessionid hinzu und verwenden Sie diese, um Zeilenstapel zu identifizieren.


Beliebte Antwort

Als eine alternative Lösung könnten Sie Datenbank-Trigger verwenden , um die zweite Tabelle zu aktualisieren.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum