¿Cómo se copia un registro en una tabla SQL pero se intercambia el id único de la nueva fila?


Esta pregunta se acerca a lo que necesito, pero mi escenario es ligeramente diferente. La tabla de origen y la tabla de destino son las mismas y la clave principal es un uniqueidentifier (guid). Cuando intento esto:

insert into MyTable
    select * from MyTable where uniqueId = @Id;

Obviamente obtengo una violación de restricción de clave primaria, ya que estoy intentando copiar sobre la clave primaria. En realidad, no quiero copiar sobre la clave primaria en absoluto. Más bien, quiero crear uno nuevo. Además, me gustaría copiar selectivamente sobre ciertos campos, y dejar los otros nulos. Para hacer las cosas más complejas, necesito tomar la clave principal del registro original e insertarla en otro campo en la copia (campo PreviousId).

Estoy seguro de que hay una solución fácil para esto, simplemente no sé lo suficiente TSQL para saber lo que es.

Author: Community, 2008-09-29

10 answers

Prueba esto:


insert into MyTable(field1, field2, id_backup)
    select field1, field2, uniqueId from MyTable where uniqueId = @Id;

Cualquier campo no especificado debe recibir su valor por defecto (que suele ser NULL cuando no está definido).

 162
Author: AaronSieb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 20:54:06

De acuerdo, sé que es un problema antiguo, pero de todos modos publico mi respuesta.

Me gusta esta solución. Solo tengo que especificar la(s) columna (s) de identidad.

SELECT * INTO TempTable FROM MyTable_T WHERE id = 1;
ALTER TABLE TempTable DROP COLUMN id;
INSERT INTO MyTable_T SELECT * FROM TempTable;
DROP TABLE TempTable;

La columna "id"es la columna de identidad y esa es la única columna que tengo que especificar. Es mejor que al revés de todos modos. :-)

Uso SQL Server. Puede usar " CREATE TABLE" y "UPDATE TABLE" en las filas 1 y 2. Hmm, vi que realmente no le di la respuesta que él quería. Quería copiar el id a otra columna también. Pero esta solución es buena para hacer una copia con un nuevo auto-id.

Edito mi solución con los idéas de Michael Dibbets.

use MyDatabase; 
SELECT * INTO #TempTable FROM [MyTable] WHERE [IndexField] = :id;
ALTER TABLE #TempTable DROP COLUMN [IndexField]; 
INSERT INTO [MyTable] SELECT * FROM #TempTable; 
DROP TABLE #TempTable;

Puede soltar más de una columna separándolas con un ",". El: id debe reemplazarse por el id de la fila que desea copiar. MyDatabase, MyTable e IndexField deben ser reemplazados por sus nombres (por supuesto).

 69
Author: Jonas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-19 12:05:11

Especifique todos los campos excepto su campo ID.

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;
 9
Author: Scott Bevington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 17:37:25

Supongo que estás tratando de evitar escribir todos los nombres de las columnas. Si está utilizando SQL Management Studio, puede hacer clic con el botón derecho en la tabla y el Script como Insert.. luego puede jugar con esa salida para crear su consulta.

 9
Author: Matt Hinze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-21 19:49:10
insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id
 2
Author: Jeffrey L Whitledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 17:39:42

Si "key" es tu campo PK y es autonumerico.

insert into MyTable (field1, field2, field3, parentkey)
select field1, field2, null, key from MyTable where uniqueId = @Id

Generará un nuevo registro, copiando el campo 1 y el campo 2 del registro original

 1
Author: Eduardo Campañó,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 17:42:34

Puedes hacer así:

INSERT INTO DENI/FRIEN01P 
SELECT 
   RCRDID+112,
   PROFESION,
   NAME,
   SURNAME,
   AGE, 
   RCRDTYP, 
   RCRDLCU, 
   RCRDLCT, 
   RCRDLCD 
FROM 
   FRIEN01P      

Allí, en lugar de 112, debe poner un número del id máximo en la tabla DENI / FRIEN01P.

 0
Author: Denis Kutlubaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-18 16:54:25

Mi tabla tiene 100 campos, y necesitaba una consulta para funcionar. Ahora puedo cambiar cualquier número de campos con alguna lógica condicional básica y no preocuparme por su posición ordinal.

  1. Reemplace el siguiente nombre de la tabla por su nombre de la tabla

    SQLcolums = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = 'TABLE-NAME')"
    
    Set GetColumns = Conn.Execute(SQLcolums)
    Do WHILE not GetColumns.eof
    
    colName = GetColumns("COLUMN_NAME")
    
  2. Reemplace el nombre del campo de identidad original con su nombre de campo PK

    IF colName = "ORIGINAL-IDENTITY-FIELD-NAME" THEN ' ASSUMING THAT YOUR PRIMARY KEY IS THE FIRST FIELD DONT WORRY ABOUT COMMAS AND SPACES
        columnListSOURCE = colName 
        columnListTARGET = "[PreviousId field name]"
    ELSE
        columnListSOURCE = columnListSOURCE & colName
        columnListTARGET = columnListTARGET & colName
    END IF
    
    GetColumns.movenext
    
    loop
    
    GetColumns.close    
    
  3. Vuelva a reemplazar los nombres de las tablas (tanto el nombre de la tabla de destino como el nombre de la tabla de origen); edite su where condiciones

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)
    
 0
Author: Rit Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-20 18:33:19

Tengo el mismo problema en el que quiero que un solo script funcione con una tabla que tenga columnas agregadas periódicamente por otros desarrolladores. No solo eso, sino que estoy apoyando muchas versiones diferentes de nuestra base de datos, ya que es posible que todos los clientes no estén al día con la versión actual.

Tomé la solución de Jonas y la modifiqué ligeramente. Esto me permite hacer una copia de la fila y luego cambiar la clave primaria antes de volver a agregarla a la tabla fuente original. Esto también es muy útil para trabajar con tablas que no permiten valores NULOS en columnas y no desea tener que especificar el nombre de cada columna en el RECUADRO.

Este código copia la fila de ' ABC 'a'XYZ'

SELECT * INTO #TempRow FROM SourceTable WHERE KeyColumn = 'ABC';
UPDATE #TempRow SET KeyColumn = 'XYZ';
INSERT INTO SourceTable SELECT * FROM #TempRow;
DELETE #TempRow;

Una vez que haya terminado la caída de la tabla temporal.

DROP TABLE #TempRow;
 0
Author: TonyT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-05 00:02:29

Sé que mi respuesta llega tarde a la fiesta. Pero la forma en que resolví es un poco diferente a todas las respuestas.

Tuve una situación, necesito clonar una fila en una tabla excepto algunas columnas. Esos pocos tendrán nuevos valores. Este proceso debería ser compatible automáticamente con futuros cambios en la tabla. Esto implica, clonar el registro sin especificar ningún nombre de columna.

Mi enfoque es,

  1. Consulta Sys.Columnas para obtener la lista completa de columnas de la tabla e incluir los nombres de columnas para saltar en la cláusula where.
  2. Convertir eso en CSV como nombres de columna.
  3. Build Select... Insertar en el script basado en esto.


declare @columnsToCopyValues varchar(max), @query varchar(max)
SET @columnsToCopyValues = ''

--Get all the columns execpt Identity columns and Other columns to be excluded. Say IndentityColumn, Column1, Column2 Select @columnsToCopyValues = @columnsToCopyValues + [name] + ', ' from sys.columns c where c.object_id = OBJECT_ID('YourTableName') and name not in ('IndentityColumn','Column1','Column2') Select @columnsToCopyValues = SUBSTRING(@columnsToCopyValues, 0, LEN(@columnsToCopyValues)) print @columnsToCopyValues

Select @query = CONCAT('insert into YourTableName (',@columnsToCopyValues,', Column1, Column2) select ', @columnsToCopyValues, ',''Value1'',''Value2'',', ' from YourTableName where IndentityColumn =''' , @searchVariable,'''')

Print @query exec (@query)

 0
Author: Jeyara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-18 04:55:26