lin*_*ina 149 mysql copy row duplicates
insert into table select * from table where primarykey=1
Run Code Online (Sandbox Code Playgroud)
我只想复制一行插入到同一个表中(即,我想复制表中的现有行)但我想这样做而不必列出"select"之后的所有列,因为这个表有列太多了.
但是当我这样做时,我得到错误:
密钥1的重复条目"xxx"
我可以通过创建另一个具有相同列的表作为我要复制的记录的临时容器来处理这个问题:
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;
Run Code Online (Sandbox Code Playgroud)
有没有更简单的方法来解决这个问题?
Gri*_*... 183
我使用Leonard Challis的技术进行了一些改动:
CREATE TEMPORARY TABLE tmptable_1 SELECT * FROM table WHERE primarykey = 1;
UPDATE tmptable_1 SET primarykey = NULL;
INSERT INTO table SELECT * FROM tmptable_1;
DROP TEMPORARY TABLE IF EXISTS tmptable_1;
Run Code Online (Sandbox Code Playgroud)
作为临时表,永远不应该有多个记录,因此您不必担心主键.将其设置为null允许MySQL自己选择值,因此不存在创建重复的风险.
如果你想要确定你只需要插入一行,你可以将LIMIT 1添加到INSERT INTO行的末尾.
请注意,我还将主键值(在本例中为1)附加到临时表名称.
Leo*_*lis 57
2014年7月7日更新 - 基于我的答案Grim ...的答案是一个更好的解决方案,因为它改进了我的解决方案,所以我建议使用它.
您可以使用以下语法在不列出所有列的情况下执行此操作:
CREATE TEMPORARY TABLE tmptable SELECT * FROM table WHERE primarykey = 1;
UPDATE tmptable SET primarykey = 2 WHERE primarykey = 1;
INSERT INTO table SELECT * FROM tmptable WHERE primarykey = 2;
Run Code Online (Sandbox Code Playgroud)
您可以决定以其他方式更改主键.
Jor*_*ing 37
我假设您希望新记录有新内容primarykey?如果primarykey是,AUTO_INCREMENT那么就这样做:
INSERT INTO table (col1, col2, col3, ...)
SELECT col1, col2, col3, ... FROM table
WHERE primarykey = 1
Run Code Online (Sandbox Code Playgroud)
... 除了col1, col2, col3, ...表之外, 表中的所有列都在哪里primarykey.
如果它不是一个AUTO_INCREMENT列,并且您希望能够为primarykey它选择相似的新值:
INSERT INTO table (primarykey, col2, col3, ...)
SELECT 567, col2, col3, ... FROM table
WHERE primarykey = 1
Run Code Online (Sandbox Code Playgroud)
... ... 567的新值primarykey.
小智 12
您几乎已经使用了第一个查询,只需要指定列,这样您就可以在插入中排除主键,这将生成您可能在表上自动增加的自动增量,以便为表创建新的主键.条目.
例如改变这个:
insert into table select * from table where primarykey=1
Run Code Online (Sandbox Code Playgroud)
对此:
INSERT INTO table (col1, col2, col3)
SELECT col1, col2, col3
FROM table
WHERE primarykey = 1
Run Code Online (Sandbox Code Playgroud)
只是不要在INSERT的列列表或查询的SELECT部分中包含primarykey列.
您也可以尝试转储表,找到insert命令并对其进行编辑:
mysqldump -umyuser -p mydatabase --skip-extended-insert mytable > outfile.sql
Run Code Online (Sandbox Code Playgroud)
该--skip-extended-insert给你每行一个INSERT命令.然后,您可以在您喜欢的文本编辑器中找到该行,解压缩命令并将主键更改为"default".
这可以通过一些创造力来实现:
SET @sql = CONCAT('INSERT INTO <table> SELECT null,
', (SELECT GROUP_CONCAT(COLUMN_NAME)
FROM information_schema.columns
WHERE table_schema = '<database>'
AND table_name = '<table>'
AND column_name NOT IN ('id')), '
from <table> WHERE id = <id>');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
Run Code Online (Sandbox Code Playgroud)
这将导致新行获得自动递增的 id,而不是来自所选行的 id。
此过程假定:
当然这并不完美,但在某些(可能是大多数)情况下它会起作用.
DELIMITER $$
CREATE PROCEDURE DUPLICATE_ROW(copytable VARCHAR(255), primarykey VARCHAR(255), copyid INT, out newid INT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @error=1;
SET @temptable = '_duplicate_temp_table';
SET @sql_text = CONCAT('CREATE TABLE ', @temptable, ' LIKE ', copytable);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('INSERT INTO ', @temptable, ' SELECT * FROM ', copytable, ' where ', primarykey,'=', copyid);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('SELECT max(', primarykey, ')+1 FROM ', copytable, ' INTO @newid');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('UPDATE ', @temptable, ' SET ', primarykey, '=@newid');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('INSERT INTO ', copytable, ' SELECT * FROM ', @temptable, '');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('DROP TABLE ', @temptable);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT @newid INTO newid;
END $$
DELIMITER ;
CALL DUPLICATE_ROW('table', 'primarykey', 1, @duplicate_id);
SELECT @duplicate_id;
Run Code Online (Sandbox Code Playgroud)
小智 5
如果表的主键字段是自动递增字段,则可以对列使用查询。例如,您名为的表test_tbl具有3个字段,如id, name, age。id是主键字段并自动递增,因此您可以使用以下查询复制该行:
INSERT INTO `test_tbl` (`name`,`age`) SELECT `name`,`age` FROM `test_tbl`;
Run Code Online (Sandbox Code Playgroud)
此查询导致复制每一行。
如果表的主键字段不是自动递增字段,则可以使用以下方法:
INSERT INTO `test_tbl` (`id`,`name`,`age`)
SELECT 20,`name`,`age` FROM `test_tbl` WHERE id = 19;
Run Code Online (Sandbox Code Playgroud)
该查询的结果是id=19插入了的重复行id=20。
我使用了 Grim 的技术,做了一点改变:如果有人寻找这个查询是因为由于主键问题而无法执行简单的查询:
INSERT INTO table SELECT * FROM table WHERE primakey=1;
Run Code Online (Sandbox Code Playgroud)
在我的 MySql 安装 5.6.26 中,密钥不可为空并产生错误:
#1048 - Column 'primakey' cannot be null
Run Code Online (Sandbox Code Playgroud)
因此,在创建临时表后,我将主键更改为可为空。
CREATE TEMPORARY TABLE tmptable_1 SELECT * FROM table WHERE primarykey = 1;
ALTER TABLE tmptable_1 MODIFY primarykey int(12) null;
UPDATE tmptable_1 SET primarykey = NULL;
INSERT INTO table SELECT * FROM tmptable_1;
DROP TEMPORARY TABLE IF EXISTS tmptable_1;
Run Code Online (Sandbox Code Playgroud)