如何在SQL表中复制记录但是换出新行的唯一ID?

时间:2008-09-29 17:35:05

标签: sql sql-server sql-server-2005 tsql

This question接近我的需要,但我的情况略有不同。源表和目标表是相同的,主键是uniqueidentifier(guid)。当我尝试这个时:

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

我显然遇到了主键约束违规,因为我试图复制主键。实际上,我根本不想复制主键。相反,我想创建一个新的。另外,我想有选择地复制某些字段,并将其他字段留空。为了使事情变得更复杂,我需要获取原始记录的主键,并将其插入副本中的另一个字段(PreviousId字段)。

我确信有一个简单的解决方案,我只是不知道足够的TSQL知道它是什么。

11 个答案:

答案 0 :(得分:171)

试试这个:


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

未指定的任何字段都应该接收其默认值(未定义时通常为NULL)。

答案 1 :(得分:79)

好的,我知道这是一个老问题,但无论如何我都会发布我的答案。

我喜欢这个解决方案。我只需要指定标识列。

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;

“id” - 列是标识列,这是我必须指定的唯一列。无论如何,它比其他方式更好。 : - )

我使用SQL Server。您可能希望在第1行和第2行使用“CREATE TABLE”和“UPDATE TABLE”。 嗯,我看到我没有给出他想要的答案。他也希望将id复制到另一列。但是这个解决方案很适合制作一个带有新auto-id的副本。

我用Michael Dibbets的idéas编辑我的解决方案。

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;

您可以通过用“,”分隔多个列来删除它们。 :id应替换为要复制的行的id。 MyDatabase,MyTable和IndexField应该替换为您的名字(当然)。

答案 2 :(得分:11)

我猜你在试图避免写出所有的列名。如果您正在使用SQL Management Studio,您可以轻松地右键单击表格和脚本为插入...然后您可以使用该输出来创建查询。

答案 3 :(得分:10)

指定除ID字段以外的所有字段。

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;

答案 4 :(得分:3)

我遇到了同样的问题,我希望单个脚本能够处理其他开发人员定期添加列的表。不仅如此,我支持我们数据库的许多不同版本,因为客户可能不会都与当前版本保持同步。

我接受了乔纳斯的解决方案并略微修改了它。这允许我复制该行,然后在将其添加回原始源表之前更改主键。这对于使用不允许列中的NULL值的表非常方便,并且您不希望必须在INSERT中指定每个列名。

此代码复制' ABC'到' XYZ'

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

完成删除临时表后。

DROP TABLE #TempRow;

答案 5 :(得分:2)

insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id

答案 6 :(得分:1)

如果“key”是您的PK字段并且它是自动数字。

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

它将生成一条新记录,从原始记录中复制field1和field2

答案 7 :(得分:1)

我的表有100个字段,我需要一个查询才能正常工作。现在我可以用一些基本的条件逻辑切换出任意数量的字段,而不用担心它的序数位置。

  1. 将以下表名替换为您的表名

    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. 用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. 再次替换表名(目标表名和源表名);修改您的where条件

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)
    

答案 8 :(得分:1)

我知道我的答案迟到了。但我解决的方式与所有答案有点不同。

我有一种情况,我需要在表中克隆除少数列之外的行。少数人会有新的价值观。此过程应自动支持将来对表的更改。这意味着,克隆记录而不指定任何列名。

我的方法是,

  1. 查询Sys.Columns以获取表的完整列列表并包含名称 在where子句中跳过的列。
  2. 将其转换为CSV作为列名称。
  3. 构建选择...基于此插入脚本。
  4. 
    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)

答案 9 :(得分:0)

你可以这样做:

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

而不是112,你应该在表DENI / FRIEN01P中放入一些最大id。

答案 10 :(得分:0)

这是我使用ASP Classic进行的操作,无法完全与上面的答案一起使用,我希望能够将系统中的产品复制到新的product_id并需要它才能工作即使我们在表格中添加了更多列。

Cn.Execute("CREATE TEMPORARY TABLE temprow AS SELECT * FROM product WHERE product_id = '12345'")
Cn.Execute("UPDATE temprow SET product_id = '34567'")
Cn.Execute("INSERT INTO product SELECT * FROM temprow")
Cn.Execute("DELETE temprow")
Cn.Execute("DROP TABLE temprow")