Daten per SQL INSERT ohne Schlüsselspalte kopieren
Immer wieder steht man vor der Aufgabe, Datenmengen innerhalb einer Tabelle zu kopieren. Typisierte Datenzugriffsschichten, wie das Entity Framework, bieten zwar viel Komfort, lassen aber zukünftige DDL Updates außen vor. Ein Update des Datenmodells, speziell mit ergänzten oder gelöschten Spalten erzwingt dann automatisch ein Update der Anwendung, wenn die Kopierfunktion vollständige Kopien anlegen soll. Bei oft geänderten Tabellen wir das zu einem Problem. Zudem sind komplexere Kopieroperationen direkt auf dem Server mittels einer StoredProcedure meist wesentlich schneller.
Hier bietet sich natürlich die Lösung mit einem INSERT SQL an:
INSERT INTO MyTable SELECT mt.* FROM MyTable mt; |
Das Problem mit diesem Befehl sind aber IDENTITY Spalten, die nicht übergeben werden dürfen. Dies kann man natürlich durch Angabe der Spaltennamen umgehen. Damit landet man aber wieder am Anfang des Problems. Die Spaltennamen müssen fest definiert oder zuvor aufwändig ermittelt werden.
Eine andere Lösung lässt sich jedoch über temporäre Tabellen entwickeln. Man erstellt mit SELECT INTO eine temporäre Tabelle mit den benötigten Daten. Deren Identity-Spalte kann man problemlos verwerfen und danach funktioniert ein INSERT INTO ohne Problem:
CREATE PROCEDURE dbo.CopyTable @SourceId BIGINT AS SET NOCOUNT ON; IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable; SELECT mt.* INTO #MyTable FROM MyTable mt WHERE mt.Id = @SourceId; ALTER TABLE #MyTable DROP COLUMN Id; INSERT INTO MyTable SELECT mt.* FROM #MyTable mt; IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable; SET NOCOUNT OFF; GO |
Ein weiterer Vorteil ist das einfach Aktualisieren der neuen Datenmenge in der temporären Tabelle.