views:

45

answers:

1

Using MS SQL 2005,

Table 1

ID |  T1Value  | T2ID  |  GroupID
----------------------------------
1  |     a     |  10   |     1
2  |     b     |  11   |     1
3  |     c     |  12   |     1
4  |     a     |  22   |     2

Table 2

ID  |  T2Value
----------------
10  |     H
11  |     J
12  |     K
22  |     H

I want to clone the data for GroupID == 1 into a new GroupID so that I result with the following:

Table 1

ID |  T1Value  | T2ID  |  GroupID
----------------------------------
1  |     a     |  10   |     1
2  |     b     |  11   |     1
3  |     c     |  12   |     1
4  |     a     |  22   |     2
5  |     a     |  23   |     3
6  |     b     |  24   |     3
7  |     c     |  25   |     3

Table 2

ID  |  T2Value
----------------
10  |     H
11  |     J
12  |     K
22  |     H
23  |     H
24  |     J
25  |     K

I've found some SQL clone patterns that allow me to clone data in the same table well... but as I start to deal with cloning data in two tables at the same time and then linking up the new rows correctly... that's just not something I feel like I have a good grasp of.

I thought I could do some self-joins to deal with this, but I am worried in the cases where the non-key fields have the same data in multiple rows.

A: 

Is my only option to use a cursor to keep track of the ID mapping? Here is some pseudo-code I wrote... not tested yet. I was hoping for something more concise. Is this my only option?

DECLARE @NewT2Key INT
DECLARE @OldT2Key INT
DECLARE @T2Value  VARCHAR(50)
DECLARE @T2KeyNewOld TABLE (OldT2Key INT, NewT2Key INT)

DECLARE @NewGroupID INT
DECLARE @OldGroupID INT

SET @NewGroupID = 3
SET @OldGroupID = 1

--
-- STEP 1: CLONE THE TABLE2 DATA AND KEEP MAPPING OF OLD-to-NEW IDs
--
DECLARE curT2Keys
CURSOR FAST_FORWARD LOCAL FOR
    SELECT t2.ID,
        t2.T2Value
    FROM dbo.Table2 t2
        JOIN dbo.Table1 t1
        ON  t2.ID    = t1.T2ID
    WHERE t1.GroupID = @OldGroupID
    ORDER BY t1.ID

OPEN curT2Keys
FETCH NEXT FROM curT2Keys INTO @OldT2Key, @T2Value

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @NewT2Key = (SELECT MAX(ID)+1 FROM dbo.Table2)

    INSERT INTO dbo.Table2(ID, T2Value)
    VALUES(@NewT2Key, @T2Value)

    INSERT INTO @T2KeyNewOld(OldT2Key, NewT2Key)
    VALUES(@OldT2Key, @NewT2Key)

    FETCH NEXT FROM curT2Keys INTO @OldT2Key, @T2Value
END
CLOSE curT2Keys
DEALLOCATE curT2Keys

--
-- STEP 2: CLONE THE TABLE1 DATA AND UPDATE IDs WITH NEW MAPPING
--

      INSERT INTO dbo.Table1([ID], [T1Value], [T2ID], [GroupID])
      (SELECT
            (SELECT MAX(ID) FROM dbo.Table1) + ROW_NUMBER() OVER (ORDER BY GroupID),
            t1.[T1Value],
            t2.[NewT2Key],
            @NewGroupID
       FROM dbo.Table1 t1 
           JOIN @T2KeyNewOld t2
           ON t1.T2ID = t2.OldT2Key
       WHERE t1.GroupID = @OldGroupID
      )
AmoebaMan17
I just tested the code above, and it appeared to work for me. I always feel like when I opt to use WHILE loops in my TSQL, I'm thinking like a programmer and not like a DBA. I'm at least able to do table JOINS in STEP 2. I just wish I knew how to create a Temporary Table for my mappings without having to do use the Cursor.
AmoebaMan17