在MySQL中,我能否复制一行并将其插入到同一张表中?

193
insert into table select * from table where primarykey=1

我想复制表中的一行数据并将其插入到同一张表里(即,我想要复制该表中的一个现有行),但我不想在“select”之后列出所有列,因为这个表有太多的列。

但是,当我尝试这样做时,我收到了以下错误:

重复条目'xxx',键为1

我可以通过创建另一个与原表具有相同列的临时容器来复制所需记录以避开这个问题:

create table oldtable_temp like oldtable;
insert into oldtable_temp select * from oldtable where key=1;
update oldtable_tem set key=2;
insert into oldtable select * from oldtable where key=2;

有没有更简单的方法来解决这个问题?


1
我只是对于硬编码的键值有些评论。我会采用类似于max(oldtable.id) + oldtable_temp.key的方式,这样我可以确保id递增且唯一。 - guy mograbi
可能是 在同一张 MySQL 表中复制记录 的重复问题。 - Organic Advocate
@OrganicAdvocate,这个问题有更多的答案和更多的浏览量,比那个问题要多。 - Drew
是的,不要使用update oldtable_tem set key=2;,而是使用update oldtable_tem set key=NULL;,然后简单地使用insert into oldtable select * from oldtable_tem; - Timofey Bugaevsky
26个回答

4

我在我的Koha数据库中使用'C'前缀在条形码列中插入了重复的物品:

INSERT INTO items (`biblionumber`, `biblioitemnumber`, `barcode`, `dateaccessioned` ) SELECT `biblionumber`, `biblioitemnumber`,  CONCAT('C',`barcode`), `dateaccessioned` FROM `items` WHERE barcode='14832';

3

以下部分内容摘自该网站。以下是我在具有任意数量字段的表中复制记录所做的操作:

这也假设您在表的开头有一个AI字段。

function duplicateRow( $id = 1 ){
dbLink();//my db connection
$qColumnNames = mysql_query("SHOW COLUMNS FROM table") or die("mysql error");
$numColumns = mysql_num_rows($qColumnNames);

for ($x = 0;$x < $numColumns;$x++){
$colname[] = mysql_fetch_row($qColumnNames);
}

$sql = "SELECT * FROM table WHERE tableId = '$id'";
$row = mysql_fetch_row(mysql_query($sql));
$sql = "INSERT INTO table SET ";
for($i=1;$i<count($colname)-4;$i++){//i set to 1 to preclude the id field
//we set count($colname)-4 to avoid the last 4 fields (good for our implementation)
$sql .= "`".$colname[$i][0]."`  =  '".$row[$i]. "', ";
}
$sql .= " CreateTime = NOW()";// we need the new record to have a new timestamp
mysql_query($sql);
$sql = "SELECT MAX(tableId) FROM table";
$res = mysql_query($sql);
$row = mysql_fetch_row($res);
return $row[0];//gives the new ID from auto incrementing
}

3

我更新了@LeonardChallis的解决方案,因为它对我和其他人都不起作用。我移除了临时表中的WHERE子句和 SET primaryKey = 0,这样MySQL就可以自动递增primaryKey。

CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable;
UPDATE tmptable SET primaryKey = 0;
INSERT INTO myTable SELECT * FROM tmptable;

当然,这是为了复制表格中所有的行。

3
如果主键是自动递增的,只需指定除主键之外的每个字段。 INSERT INTO 表名(字段1,字段2,字段3) SELECT (字段1,字段2,字段3) FROM 表名 WHERE 主键=1

3

也许我来得有点晚,但我有一个类似的解决方案,对我很有效。

 INSERT INTO `orders` SELECT MAX(`order_id`)+1,`container_id`, `order_date`, `receive_date`, `timestamp` FROM `orders` WHERE `order_id` = 1

这样我就不需要创建临时表等。由于行是在同一张表中复制的,所以可以轻松使用Max(PK)+1函数。
我来寻找这个问题的解决方案(忘记了语法),最后自己编写了查询。有时候事情的发展很有趣。
问候

2
我会使用以下代码:
insert into ORDER_ITEM select * from ORDER_ITEM where ITEM_NUMBER =123;

1
如果ITEM_NUMBER是您的主键(在这种情况下很可能),则此方法无效。 - Billy Pilgrim

1

我刚刚做了这件事,以下是我的手动解决方案:

  1. phpmyadmin中,勾选您想要复制的行
  2. 在查询结果操作下方,点击'导出'
  3. 在下一页上,勾选'保存为文件',然后点击'Go'
  4. 使用文本编辑器打开导出的文件,找到主键字段的值,并将其更改为唯一的值。
  5. 回到phpmyadmin,点击'导入'选项卡,在浏览下找到要导入的.sql文件,然后点击'Go',重复的行应该被插入。

如果您不知道PRIMARY字段是什么,请返回您的phpmyadmin页面,点击'结构'选项卡,在页面底部的'索引'下,它将向您显示哪个'字段'具有'Keyname''PRIMARY'

这可能是一个比较麻烦的方法,但如果您不想处理标记,只需要复制单个行,那么这就是您需要的方法。


很好,以一种独特的方式回答了问题。显然并不适用于所有情况,比如二进制大对象和地理空间数据,但是非常容易实现,并且对于那些奇怪的变化确实有效。 - Strixy

1
这个上面展示的解决方案也适用于选定的行。例如,我正在为我的nice2work项目创建演示行,这个方法非常完美。
CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable WHERE id=500;
UPDATE tmptable SET id = 0;
UPDATE some fields I need to change
INSERT INTO myTable SELECT * FROM tmptable;
DROP TABLE tmptable;

//  You can use this same also directly into your code like (PHP Style)
$sql = "CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable WHERE id=500;
UPDATE tmptable SET id = 0;
UPDATE some fields I need to change
INSERT INTO myTable SELECT * FROM tmptable;DROP TABLE tmptable;";

0
创建一个表格。
    CREATE TABLE `sample_table` (
       `sample_id` INT(10) unsigned NOT NULL AUTO_INCREMENT,
       `sample_name` VARCHAR(255) NOT NULL,
       `sample_col_1` TINYINT(1) NOT NULL,
       `sample_col_2` TINYINT(2) NOT NULL,

      PRIMARY KEY (`sample_id`),
      UNIQUE KEY `sample_id` (`sample_id`)

    ) ENGINE='InnoDB' DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

插入一行

INSERT INTO `sample_table`
   VALUES(NULL, 'sample name', 1, 2);

复制行并在上方插入

INSERT INTO `sample_table`
   SELECT 
    NULL AS `sample_id`, -- new AUTO_INCREMENT PRIMARY KEY from MySQL
    'new dummy entry' AS `sample_name`,  -- new UNIQUE KEY from you
    `sample_col_1`, -- col from old row
    `sample_col_2` -- col from old row
   FROM `sample_table`
   WHERE `sample_id` = 1;

测试

SELECT * FROM `sample_table`;

注意:如果出现错误(#1048),请使用“”而不是NULL - Abdullah
是不是只有我觉得这恰恰是 OP 不想要的?(也就是手动将每个列添加到查询中。) - Byson
你说得对,我刚刚读到 OP 的“我只想复制一行并插入到相同的表格中”的句子,无论如何,这仍然对“Duplicate entry 'xxx' for key ???”错误非常有用 ^^ - Abdullah

0

抱歉打扰了,但这是我在谷歌上找到的结果,因为我发现这很有帮助但也有问题,所以我想为任何其他人提供一个重要的修改。

首先,我使用的是SQL Server,而不是MySQL,但我认为它应该类似。我使用Leonard Challis的解决方案,因为它最简单并且满足需求,但是存在一个问题-如果您只是取PK并将其增加1,那么如果自添加该行后添加了其他记录会发生什么。我决定最好让系统处理PK的自动递增,因此我执行了以下操作:

SELECT * INTO #tmpTable FROM Table WHERE primarykey = 1
--Optionally you can modify one or more fields here like this: 
--UPDATE #tmpTable SET somefield = newData
ALTER TABLE #tmpTable DROP COLUMN TicketUpdateID
INSERT INTO Tickets SELECT * FROM #tmpTable
DROP TABLE #tmpTable

我相信在MySQL中也可以类似地工作,但是我无法进行测试,很抱歉


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接