2010-05-12 13 views
9

dado una tabla que tiene tres columnasINSERT INTO que la columna no identidad ID de clave copia filas y auto-incrementos

  1. ID (clave principal, no-autoincremental)
  2. GroupID
  3. SomeValue

Estoy tratando de escribir una sola instrucción SQL INSERT INTO que hará una copia de cada fila que tenga un GroupID en un nuevo GroupID.

Ejemplo tabla que comienza:

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

meta después de ejecutar un INSERT sencilla INTO:

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

pensé que podría hacer algo como:

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

Esto provoca una Violación PrimaryKey ya que terminará reutilizando el mismo valor Max (ID) +1 varias veces como parece.

¿Es mi único recurso a un grupo de instrucciones INSERT en una instrucción WHILE de T-SQL que tiene un valor de Contador incrementado?

Tampoco tengo la opción de convertir la ID en una columna de identidad de incremento automático, ya que no tendría código fuente de ruptura.

+0

es mejor para mover subconsulta (especialmente si se trata de uno de cálculo de tiempo) para unirse, es más performante. si en cualquier caso, otras respuestas son lentas, puede usar el mío –

+0

@Michael: 'SQL Server' es lo suficientemente inteligente como para calcular la expresión de esa manera una sola vez. – Quassnoi

+0

@Quassnoi: en cuanto a rendimiento, siempre me siento incómodo con las subconsultas en la proyección de datos. No es ciencia de cohetes mover la subconsulta en la sección UNIR de ninguna manera. De todas formas, haré un perfil en SQL Server más tarde –

Respuesta

10

En lugar de + 1, agregue el número de fila. También he arreglado el error en su cláusula WHERE (debe ser GroupID =, no 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 
) 
+0

¡Funcionó! ¡Gracias por la rápida ayuda! – AmoebaMan17

1
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 
+0

Esto también me da el error: 'La función de clasificación" ROW_NUMBER "debe tener una cláusula ORDER BY. –

1

Utilice esta:

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 
+0

En SQL Server 2008 recibo algunos errores al intentar ejecutar este comando. –

+0

Encontré la primera respuesta más fácil de entender para mi conocimiento simple de SQL. Sin embargo, parece que puedo hacer el mismo trabajo usando CROSS JOIN, lo probaré también. – AmoebaMan17

+0

Pude hacer que esto funcionara también al agregar la cláusula ORDER BY en la instrucción OVER() , p. SELECT (ROW_NUMBER() OVER (ORDER BY GroupID) + X.MaxID) – AmoebaMan17

Cuestiones relacionadas