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

Kil*_*fer 118 sql t-sql sql-server sql-server-2005

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

insert into MyTable
    select * from MyTable where uniqueId = @Id;
Run Code Online (Sandbox Code Playgroud)

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

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

Aar*_*ieb 179

试试这个:


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

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

  • 太棒了 像魅力一样工作。一旦你写出来,它是如此明显。谢谢!! (2认同)
  • 如果您有几列,这将起作用。如果你有 20 或 30 列,你仍然可以使用这种方法,但它会令人生畏。此外,每次添加列并希望复制该数据时,都需要将该列添加到此脚本中。最好是使用 sys 表动态生成插入。 (2认同)

Jon*_*nas 88

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

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

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;
Run Code Online (Sandbox Code Playgroud)

"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;
Run Code Online (Sandbox Code Playgroud)

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

  • +1表示不必列出所有列 (8认同)
  • 对于`TempTable`,使用`#TempTable`不是更好,所以它是一个真正的临时表吗? (8认同)
  • 我使用以下格式`使用MyDatabase; SELECT*INTO #TempTable FROM [TABLE] WHERE [indexfield] =:id; ALTER TABLE #TempTable DROP COLUMN [indexfield]; INSERT INTO [TABLE] SELECT*FROM #TempTable; DROP TABLE #TempTable;`这样我就知道它会在没有任何延迟的情况下被清理干净,不会将间歇文件写入光盘. (3认同)
  • 如果您不想对您的标识列名称进行硬编码,也可以使用`$ identity` (2认同)

Mat*_*nze 12

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


小智 10

指定除ID字段之外的所有字段.

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


小智 7

我有同样的问题,我想要一个脚本来处理一个表,该表具有由其他开发人员定期添加的列。不仅如此,我还支持我们数据库的许多不同版本,因为客户可能不会全部使用当前版本。

我采用了 Jonas 的解决方案并稍微修改了它。这允许我制作该行的副本,然后在将其添加回原始源表之前更改主键。这对于处理列中不允许 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;
Run Code Online (Sandbox Code Playgroud)

完成删除临时表后。

DROP TABLE #TempRow;
Run Code Online (Sandbox Code Playgroud)


Jey*_*ara 6

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

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

我的做法是,

  1. 查询 Sys.Columns 以获取表的完整列列表,并包括要在 where 子句中跳过的列的名称。
  2. 将其转换为 CSV 作为列名。
  3. 构建选择...基于此插入到脚本中。


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)

Run Code Online (Sandbox Code Playgroud)