SQL MERGE-Befehl . INSERT aller Datenzeilen verhindern, beschränkbar auf nur geänderte?
Hallo,
ich habe mir die Funktion MERGE die Tage angeschaut, die mir bislang neu war.
Der Syntax stammt von @4400667902
Ich habe nun festgestellt, dass wenn ich in der Tabelle EINEN Datensatz ändere, er mir ALLE Datensätze in die Zieltabelle kopiert, was bei 85.000 Zeilen dann Zeit frisst.
Werden anschließend einzelne Zeilen gelöscht/geändert/neu hinzugefügt, geht dies natürlich flux.
ABER, kann ich denn diesem MERGE-Befehl auch mitgeben, dass er NICHT alle Datenzeilen erst mal kopiert, sondern nur die sich ändern in der Tabelle?
Ich möchte den MERGE anstelle INSERT/UPDATE in einem Trigger verwenden.
ich habe mir die Funktion MERGE die Tage angeschaut, die mir bislang neu war.
Der Syntax stammt von @4400667902
MERGE datev_eodb_mandanten_backup AS t
USING datev_eodb_mandanten AS s
ON t.MDTGUID = s.MDTGUID
AND t.MDTID = s.MDTID
WHEN MATCHED
AND ( isnull(t.MDTVON,''1900-01-01 00:00:00.000'') != isnull(s.MDTVON,''1900-01-01 00:00:00.000'')
OR isnull(t.MDTBIS,''1900-01-01 00:00:00.000'') != isnull(s.MDTBIS,''1900-01-01 00:00:00.000'')
OR isnull(t.MDTSTATUS,0) != isnull(s.MDTSTATUS,0)
OR isnull(t.MDTNR,0) != isnull(s.MDTNR,0)
OR isnull(t.MDTNAME,'''') != isnull(s.MDTNAME,'''')
OR isnull(t.MDTTYP,'''') != isnull(s.MDTTYP,'''')
OR isnull(t.MDTPLZ,'''') != isnull(s.MDTPLZ,'''')
OR isnull(t.MDTORT,'''') != isnull(s.MDTORT,'''')
OR isnull(t.MDTSTR,'''') != isnull(s.MDTSTR,'''')
OR isnull(t.MDTGID,0) != isnull(s.MDTGID,0)
OR isnull(t.MDTGNAME,'''') != isnull(s.MDTGNAME,'''')
OR isnull(t.DOHR,'''') != isnull(s.DOHR,'''') )
THEN
UPDATE
SET t.MDTVON = s.MDTVON,
t.MDTBIS = s.MDTBIS,
t.MDTSTATUS = s.MDTSTATUS,
t.MDTNR = s.MDTNR,
t.MDTNAME = s.MDTNAME,
t.MDTTYP = s.MDTTYP,
t.MDTPLZ = s.MDTPLZ,
t.MDTORT = s.MDTORT,
t.MDTSTR = s.MDTSTR,
t.MDTGID = s.MDTGID,
t.MDTGNAME = s.MDTGNAME,
t.DOHR = s.DOHR
WHEN NOT MATCHED BY TARGET
THEN
INSERT(MDTGUID,MDTID,MDTVON,MDTBIS,MDTSTATUS,MDTNR,MDTNAME,MDTTYP,MDTPLZ,MDTORT,MDTSTR,MDTGID,MDTGNAME,DOHR)
VALUES(s.MDTGUID,s.MDTID,s.MDTVON,s.MDTBIS,s.MDTSTATUS,s.MDTNR,s.MDTNAME,s.MDTTYP,s.MDTPLZ,s.MDTORT,s.MDTSTR,s.MDTGID,s.MDTGNAME,s.DOHR)
WHEN NOT MATCHED BY SOURCE
THEN
DELETE;
Ich habe nun festgestellt, dass wenn ich in der Tabelle EINEN Datensatz ändere, er mir ALLE Datensätze in die Zieltabelle kopiert, was bei 85.000 Zeilen dann Zeit frisst.
Werden anschließend einzelne Zeilen gelöscht/geändert/neu hinzugefügt, geht dies natürlich flux.
ABER, kann ich denn diesem MERGE-Befehl auch mitgeben, dass er NICHT alle Datenzeilen erst mal kopiert, sondern nur die sich ändern in der Tabelle?
Ich möchte den MERGE anstelle INSERT/UPDATE in einem Trigger verwenden.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 396263
Url: https://administrator.de/forum/sql-merge-befehl-insert-aller-datenzeilen-verhindern-beschraenkbar-auf-nur-geaenderte-396263.html
Ausgedruckt am: 23.12.2024 um 05:12 Uhr
5 Kommentare
Neuester Kommentar
Hallo chgs2011,
Du vergleichst zwei komplette Tabellen, da werden dann eben auch die Daten der kompletten Tabelle eingetragen. Grundsätzlich kannst Du die Daten bei USING auch einschränken bzw. dir irgendwelche Abfragen zusammenschustern, z.B.:
Oder wenn es sowieso der Trigger auf datev_eodb_mandanten ist, dann gleich nur inserted verwenden.
Dann mußt Du aber achtgeben mit dem "when not matched by source", da werden dann nämlich alle Datensätze, die Du beim USING nicht mitgenommen hast, gelöscht, weil sie ja in dieser eingeschränkten Abfrage nicht existieren. Deswegen dürfte ein "when not matched by source" sowieso ziemlich sinnlos sein, wenn man SOURCE einschränkt.
Alternativ könntest Du auch beim "when not matched by target" noch die Zusatzbedingung dranhängen "and exists (select 1 from inserted where ID = s.ID)", dann werden nur die eingefügten Datensätze auch in datev_eodb_mandanten_backup eingefügt. Aber bei "matched" und "when not matched by source" hättest Du immer noch die komplette Überprüfung, was da wahrscheinlich auch nicht so ideal ist.
Ich würde beim USING einschränken und das "when not matched by source" rausnehmen.
Gruß, Mad Max
Du vergleichst zwei komplette Tabellen, da werden dann eben auch die Daten der kompletten Tabelle eingetragen. Grundsätzlich kannst Du die Daten bei USING auch einschränken bzw. dir irgendwelche Abfragen zusammenschustern, z.B.:
MERGE datev_eodb_mandanten_backup AS t
USING (select d.* from datev_eodb_mandanten d join inserted i on i.ID = d.ID) AS s
...
Dann mußt Du aber achtgeben mit dem "when not matched by source", da werden dann nämlich alle Datensätze, die Du beim USING nicht mitgenommen hast, gelöscht, weil sie ja in dieser eingeschränkten Abfrage nicht existieren. Deswegen dürfte ein "when not matched by source" sowieso ziemlich sinnlos sein, wenn man SOURCE einschränkt.
Alternativ könntest Du auch beim "when not matched by target" noch die Zusatzbedingung dranhängen "and exists (select 1 from inserted where ID = s.ID)", dann werden nur die eingefügten Datensätze auch in datev_eodb_mandanten_backup eingefügt. Aber bei "matched" und "when not matched by source" hättest Du immer noch die komplette Überprüfung, was da wahrscheinlich auch nicht so ideal ist.
Ich würde beim USING einschränken und das "when not matched by source" rausnehmen.
Gruß, Mad Max
Da du das ganze aus einem Trigger heraus ausführst würde ich einfach nur Inserted als Quelltabelle heranziehen und alles aus Inserted mit der Zieltabelle mergen. Das würde nur die Datensätze betreffen, die geändert wurden. Du dürftest nur mit MERGE nichts löschen in der Zieltabelle, denn das würde ja jedesmal alles löschen was nicht in Inserted steht.