INSERT SELECT: Mapping zwischen alten und neuen IDs



  • Hi,

    Beispiel: ich hab eine Tabelle "tabelle" mit den Spalten "ID" (int) und "Value" (nvarchar(max)). ID hat auto increment aktiviert. Und eine zweite Tabelle "wo_anders" mit den gleichen Spalten.

    Wenn ich jetzt sowas mache:

    INSERT INTO tabelle
    	(
    		id
    		, value
    	)
    
    	SELECT
    		id
    		, value
    	FROM
    		wo_anders
    

    und ich brauche das Mapping zwischen der alten ID (die aus wo_anders) und der neuen (die gerade in "tabelle" eingefügt wurde). Wie krieg ich das gebacken? Mein Ansatz:

    DECLARE @copyValues TABLE
    (
    	id INT
    	, value NVARCHAR(MAX)
    	, rownum INT
    );
    
    INSERT INTO @copyValues
    	(
    		id
    		, value
    		, rownum
    	)
    
    	SELECT
    		id
    		, value
    		, ROW_NUMBER() OVER(ORDER BY ID)
    	FROM
    		wo_anders
    	ORDER BY
    		id
    
    DECLARE @newIDs TABLE
    (
    	id INT
    )
    
    INSERT INTO
    	tabelle
    	(
    		value
    	)
    
    	OUTPUT INSERTED.id INTO @newIDs
    
    	SELECT
    		value
    	FROM
    		@copyValues
    	ORDER BY
    		id
    
    DECLARE @mapping TABLE
    (
    	id INT
    	, rownum INT
    )
    
    INSERT INTO
    	@mapping
    	(
    		id
    		, rownum
    	)
    
    	SELECT
    		id
    		, ROW_NUMBER() OVER(ORDER BY id)
    	FROM
    		@newIDs
    
    SELECT
    	c.id AS oldID
    	, m.id AS newID
    FROM
    	@copyValues c
    	INNER JOIN @mapping m ON c.rownum = m.rownum
    

    Das funktioniert auch, aber es is relativ viel Code für relativ wenig Ergebnis. Geht das nicht einfacher? Wichtig ist dabei, dass es ein INSERT SELECT ist, weil es viele Datensätze sein können und drüber loopen zu lang dauern würde.



  • Mit Identity spart man sich sogar noch ein paar Zeilen:

    DECLARE @copyValues TABLE
    (
    	id INT
    	, value NVARCHAR(MAX)
    	, rownum INT
    );
    
    INSERT INTO @copyValues
    	(
    		id
    		, value
    		, rownum
    	)
    
    	SELECT
    		id
    		, value
    		, ROW_NUMBER() OVER(ORDER BY ID)
    	FROM
    		wo_anders
    	ORDER BY
    		id
    
    DECLARE @newIDs TABLE
    (
    	id INT
    	, rownum INT IDENTITY(1, 1)
    )
    
    INSERT INTO
    	tabelle
    	(
    		value
    	)
    
    	OUTPUT INSERTED.id INTO @newIDs
    
    	SELECT
    		value
    	FROM
    		@copyValues
    	ORDER BY
    		id
    
    SELECT
    	c.id AS oldID
    	, n.id AS newID
    FROM
    	@copyValues c
    	INNER JOIN @newIDs n ON c.rownum = n.rownum
    


  • Hat denn wirklich keiner eine Idee?


Log in to reply