2016-04-12 10 views
2

Ich versuche einige Einfüge-Skripts (Vermeidung von Duplikaten) Batch und ich habe einige Tabellen, die keinen Primärschlüssel (ich weiß ... Ich habe sie nicht erstellt und ich kann sie nicht ändern). Im Wesentlichen habe ich die benötigten Zeilen gepackt, in eine temporäre Tabelle ([TempTable]) gestellt und einige Werte aktualisiert.SQL Insert unterschiedliche Datensätze

Jetzt muss ich DISTINCT TOP Werte von [TempTable] in [OriginalTable] in Batches wieder einfügen. Um dies zu tun, stelle ich mir vor, ich würde eine Spalte in der temporären Tabelle benötigen (die ich erstellt habe ... nennen wir es [ValuesInserted]), die angibt, welche Spalten gerade eingefügt wurden.

Ich würde eine INSERT Anweisung zu setzen DISTINCT Werte in die ursprüngliche Tabelle, mit TOP zu Batch es.

Dann würde ich die temporäre Tabelle UPDATE ValuesInserted auf 1 für die Datensätze, die gerade eingefügt wurden. Dies ist, wo ich bin stecken:

UPDATE /*TOP (1000) - Doesn't work*/ [TempTable] 
SET [ValuesInserted] = 1 
??? 

Dann würde ich die Datensätze aus der temporären Tabelle löschen, so dass meine nächste INSERT Anweisung (TOP verwenden) wird der vorherige Satz von Datensätzen nicht erfassen.

DELETE 
FROM [TempTable] 
WHERE [ValuesInserted] = 1 

Das Hauptproblem ist, dass ich habe gerade einen UPDATE läuft nur auf den TOP (1000) Reihen, erfasst nicht alle Datensätze, die Duplikate in [TempTable] haben. Ich kann auch keine INNER JOIN für alle Spalten auf zwei Kopien von [TempTable] ausführen, da dies auf vielen verschiedenen Tabellen mit dynamischem SQL ausgeführt wird. Grundsätzlich muss das Skript generisch sein (nicht für jede Tabelle spezifisch), aber es sollte angenommen werden, dass es keinen Primärschlüssel gibt.

Die folgende allgemeine Probe fängt die Idee:

Val1 Val2 ValuesInserted 
1  1  0 
1  2  0 
1  3  0 
1  4  0 
1  5  0 
1  6  0 
1  7  0 
1  8  0 
1  9  0 
1  1  0    <--Duplicate 
2  1  0 
2  2  0 
2  3  0 
2  4  0 
2  5  0 
2  6  0 
2  7  0 
2  8  0 
2  9  0 
2  1  0    <--Duplicate 
3  1  0 
3  2  0 
3  3  0 
3  4  0 
3  5  0 
3  6  0 
3  7  0 
3  8  0 
3  9  0 
3  1  0    <--Duplicate 
1  2  0    <--Duplicate 
1  3  0    <--Duplicate 

eine UPDATE TOP (5) auf dieser oben Datensatz Dadurch wird nur die ersten 5 Datensätze aktualisieren:

Val1 Val2 ValuesInserted 
1  1  1    <--Updated 
1  2  1    <--Updated 
1  3  1    <--Updated 
1  4  1    <--Updated 
1  5  1    <--Updated 
1  6  0 
1  7  0 
1  8  0 
1  9  0 
1  1  0    <--Duplicate 
2  1  0 
2  2  0 
2  3  0 
2  4  0 
2  5  0 
2  6  0 
2  7  0 
2  8  0 
2  9  0 
2  1  0    <--Duplicate 
3  1  0 
3  2  0 
3  3  0 
3  4  0 
3  5  0 
3  6  0 
3  7  0 
3  8  0 
3  9  0 
3  1  0    <--Duplicate 
1  2  0    <--Duplicate 
1  3  0    <--Duplicate 

ich alle Datensätze zu aktualisieren, die passen die oberen 5 Einträge wie folgt:

Val1 Val2 ValuesInserted 
1  1  1    <--Updated 
1  2  1    <--Updated 
1  3  1    <--Updated 
1  4  1    <--Updated 
1  5  1    <--Updated 
1  6  0 
1  7  0 
1  8  0 
1  9  0 
1  1  1    <--Updated 
2  1  0 
2  2  0 
2  3  0 
2  4  0 
2  5  0 
2  6  0 
2  7  0 
2  8  0 
2  9  0 
2  1  0    <--Duplicate 
3  1  0 
3  2  0 
3  3  0 
3  4  0 
3  5  0 
3  6  0 
3  7  0 
3  8  0 
3  9  0 
3  1  0    <--Duplicate 
1  2  1    <--Updated 
1  3  1    <--Updated 

Wenn Sie Ihre machen können Idee Arbeit an diesem Beispiel, ich kann es auf meinen speziellen Fall anwenden.

Bin ich damit völlig falsch, oder fehlt mir etwas? Ich bin auf der Suche nach einer Lösung, die Ressourcen hog nicht, weil das Skript ist stapelweise und läuft auf sehr großen Datenbanken auf High-Impact-Servern.

Das nächste Thema, das ich zu diesem Thema finden konnte war: Using Distinct in SQL Update. Die angegebenen Antworten funktionieren jedoch nicht, wenn TOP verwendet wird.

EDIT: Dies war offensichtlich zu Beginn nicht klar. Die erste Sache, die ich mache, ist, Reihen von [OriginalTable] zu ergreifen und sie in [TempTable] zu setzen. Diese Zeilen sind zunächst eindeutig. Ich führe jedoch eine Aktualisierung durch, die einige der Werte ändert und Daten wie das obige Beispiel ergibt.Von dort, muss ich DISTINCT Reihen ergreifen und sie wieder in [OriginalTable] einfügen.

+0

Das größte Problem, das Sie hier haben, ist man oben verwenden aber du hast keine Bestellung von. Ohne eine Bestellung haben Sie keine Möglichkeit festzustellen, welche Zeilen ausgewählt werden. https://blogs.msdn.microsoft.com/conor_cunningham_msft/2008/08/27/no-seatbelt-expecting-order-without-order-by/ –

+0

Dies ist überhaupt nicht verknüpft mit [Tag: Batch-Datei]. .. – aschipfl

Antwort

2

Es sieht so aus, als würden Sie wirklich alles tun, um dies so kompliziert wie möglich zu machen. Ich würde nur die Duplikate von der temporären Tabelle an erster Stelle entfernen. Oder nie INSERT sie dort, was noch besser ist. Oder erstellen Sie eine tatsächliche ETL-Lösung, vielleicht mit SSIS.

Diese Dinge gesagt, was Sie suchen für die OUTPUT Klausel ist, der zu jeder INSERT, UPDATE hinzugefügt werden können, oder DELETE Aussage:

DECLARE @inserted_ids TABLE (val1, val2) 

INSERT INTO dbo.OriginalTable (val1, val2) 
OUTPUT INSERTED.val1, INSERTED.val2 INTO @inserted_ids 
SELECT DISTINCT TOP 1000 val1, val2 
FROM dbo.TempTable 

DELETE TT 
FROM @inserte_ids II 
INNER JOIN dbo.TempTable TT ON 
    TT.val1 = II.val1 AND 
    TT.val2 = II.val2 
+0

Wenn ich Datensätze in '[TempTable]' einfügen, sind sie alle eindeutig. Wie ich schon sagte: "Im Grunde habe ich die benötigten Zeilen gepackt, in eine temporäre Tabelle ([TempTable]) gestellt und einige Werte darin aktualisiert." Es ist dieses Update, das doppelte Datensätze erstellt. Ich versuche, Duplikate aus der temporären Tabelle zu entfernen, aber ich muss es in Batches tun, weil die tatsächlichen Tabellen, die ich mache, massiv sind. –

+0

Wenn sie alle eindeutig sind, ist es nicht nötig, SELECT DISTINCT auszuwählen. Ihre Beispieldaten zeigen auch doppelte Werte. –

+0

Ich habe eine SSIS-Lösung in Betracht gezogen, aber das Skript, das ich hier schreibe, ist Teil eines viel größeren Transaktions-Batch-Skripts. Ich stimme zu, es ist insgesamt nicht der beste Ansatz, aber mit dem muss ich arbeiten. Diese Lösung muss auch generisch sein. Wie ich bereits erwähnt habe: "Grundsätzlich muss das Skript generisch sein (nicht spezifisch für eine Tabelle) ...". Das Erwähnen bestimmter Spalten wie val1 und val2 macht es spezifisch für eine Tabelle. –