Frage

Ich habe 2 Tabellen, eine aktive Tabelle und eine inaktive Tabelle. Ich möchte Bewegung Zeilen aus der aktiven in den inaktiven Tabelle. Mein erster Gedanke war

insert into inactive select * from active where ...
delete from active active where ...

Jedoch etwa 0,42 Sekunden später bemerkte ich diese / doppelte Zeilen fallen, wenn Updates ändern, was das where-Klausel auswählt.

In diesem Fall kann ich leicht verhindern, aber was soll ich tun, in Fällen, in denen ich nicht?

edit: Aus den Antworten Schaut es, wie es nicht leicht / triviale Weise, dies zu tun. Ich bin wirklich davon überrascht. Ich würde denken, dass es einige wesentliche Vorteile, es zu haben.

War es hilfreich?

Lösung

Status-Flags sind dein Freund.

UPDATE old_data SET move="MARKED";
INSERT INTO somewhere... SELECT where move="MARKED";
DELETE FROM old_data WHERE move="MARKED";

Wenn Sie dies tun mit Autocommit aus, wird es Schlösser überall ergreifen.

Sie können nach jedem Schritt COMMIT, wenn Sie ein wenig weniger Verriegelung tun wollen.

Andere Tipps

(In MS SQL mindestens) Sie Transaktionen und Sperrhinweise verwenden:

begin tran

insert into inactive
select * from active with (updlock)
where ...

delete from active
where ...

commit tran

Ohne Hinweis Verriegelung (UPDLOCK) Deadlocks auftreten kann, wenn jemand nicht verändert Datensätze gelöscht werden.

Ist Ihre Datenbank der OUTPUT-Klausel unterstützen? Dann könnte dies eine perfekte und leicht zu folgen Lösung für Sie, könnte es nicht?

http://msdn.microsoft.com/en-us/library /ms177564.aspx

delete active with (readpast)
output DELETED.*
into inactive
where ...

Wenn Sie die Zeilen pessimistisch sperren kann, das heißt, wie Sie sie lesen sie in die inaktive Tabelle zu kopieren, dann niemand kann sie unter Ihnen ändern aus.

Das Verfahren um die Zeilen zu sperren variiert je nach Datenbank-Marke, und Sie nicht angeben, dass in Ihrer Frage.

Deklarieren Sie eine lokale Tabelle var und setzt die Werte in dort, um sie in Ihre inaktive Tabelle einfügen, dann die Zeilen aus der aktiven Tabelle löschen, die in der lokalen Liste enthalten sind.

Die Transaktion Idee funktioniert genauso gut, obwohl auch.

Verwenden Sie entweder eine eindeutige ID Spalte wie

delete from active where rowid in (select rowid in inactive)

oder

delete from active as a 
where exists (select * 
              from inactive 
              where pkfld1=a.pkfld1 
              and pkfld2=a.pkfld2)

Auch vergessen Sie nicht, diesen Prozess in einer Transaktion zu wickeln.

Viel Glück.

Dies ist, wie ich meine, wo Klauseln erhalten:

DECLARE @MyTable TABLE
(
  TheKey int PRIMARY KEY
)
--
INSERT INTO @MyTable(TheKey)
SELECT TheKey FROM SourceTable WHERE rows I want
--
INSERT INTO Inactive(fieldlist)
SELECT fieldlist
FROM Active
WHERE TheKey IN (SELECT TheKey FROM @MyTable)
--
DELETE
FROM Active
WHERE TheKey IN (SELECT TheKey FROM @MyTable)

Wenn Sie als diese stärker benötigen, werden Sie auf Sperren suchen müssen (blockieren, Änderungen während der Transaktion).

Warum haben Sie zwei Tabellen, anstatt eine Spalte für „IsActive“?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top