tags:

views:

93

answers:

3

Given a table that has three columns

  1. ID (Primary Key, not-autoincrementing)
  2. GroupID
  3. SomeValue

I am trying to write a single SQL INSERT INTO statement that will make a copy of every row that has one GroupID into a new GroupID.

Example beginning table:

ID | GroupID | SomeValue
------------------------
1  |    1    |    a
2  |    1    |    b

Goal after I run a simple INSERT INTO statement:

ID | GroupID | SomeValue
------------------------
1  |    1    |    a
2  |    1    |    b
3  |    2    |    a
4  |    2    |    b

I thought I could do something like:

INSERT INTO MyTable
(       [ID]
       ,[GroupID]
       ,[SomeValue]
)
(
SELECT (SELECT MAX(ID) + 1 FROM MyTable)
       ,@NewGroupID
       ,[SomeValue]
 FROM MyTable
 WHERE ID = @OriginalGroupID
)

This causes a PrimaryKey violation since it will end up reusing the same Max(ID)+1 value multiple times as it seems.

Is my only recourse to a bunch of INSERT statements in a T-SQL WHILE statement that has an incrementing Counter value?

I also don't have the option of turning the ID into an auto-incrementing Identity column since that would breaking code I don't have source for.

+1  A: 
WITH    q AS
        (
        SELECT  *,
                (
                SELECT  MAX(id)
                FROM    mytable
                ) + ROW_NUMBER() OVER () AS nid
        FROM    mytable
        WHERE   groupID = 1
        )
INSERT
INTO    mytable (id, groupid, somevalue)
SELECT  nid, 2, somevalue
FROM    q
Quassnoi
This also gives me the error: `The ranking function "ROW_NUMBER" must have an ORDER BY clause.`
Mark Byers
+1  A: 

Use this:

INSERT INTO MyTable
(       [ID]
       ,[GroupID]
       ,[SomeValue]
)    
 SELECT ROW_NUMBER() OVER() + X.MaxID 
       ,@NewGroupID
       ,[SomeValue]
 FROM MyTable
 CROSS JOIN (SELECT MAX(ID) AS MaxID FROM MyTable) X 
 WHERE GroupID = @OriginalGroupID
Michael Buen
In SQL Server 2008 I get a few errors when trying to run this command.
Mark Byers
I found the first answer easiest to understand for my simple SQL knowledge. However, it seems like I can get the same work done using a CROSS JOIN, I will try this out too.
AmoebaMan17
I was able to get this to work also by adding the ORDER BY clause in the OVER() statemente.g. SELECT (ROW_NUMBER() OVER(ORDER BY GroupID) + X.MaxID)
AmoebaMan17
Thanks for pointing out what's missing. Interesting, OVER() without parameter in Postgres is working. I will try in SQL Server later (I'm in OS X now) if parameter in OVER clause is optional.
Michael Buen
+1  A: 

Instead of + 1, add the row number. I also fixed the error in your WHERE clause (should be GroupID =, not ID =):

INSERT INTO MyTable
(       [ID]
       ,[GroupID]
       ,[SomeValue]
)
(
    SELECT
       (SELECT MAX(ID) FROM MyTable) + ROW_NUMBER() OVER (ORDER BY GroupId),
       @NewGroupID,
       [SomeValue]
    FROM MyTable
    WHERE GroupID = @OriginalGroupID
)
Mark Byers
It worked! Thanks for the quick help!
AmoebaMan17