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

I just want to copy one row to insert into the same table (i.e., I want to duplicate an existing row in the table) but I want to do this without having to list all the columns after the "select", because this table has too many columns.

But when I do this, I get the error:

Duplicate entry 'xxx' for key 1

I can handle this by creating another table with the same columns as a temporary container for the record I want to copy:

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;

Is there a simpler way to solve this?

TRiG
  • 10,148
  • 7
  • 57
  • 107
lina
  • 1,931
  • 2
  • 12
  • 4
  • 1
    I just have a comment about the hard-coded values for the key. I would do something like `max(oldtable.id) + oldtable_temp.key` this way I make sure the ids increment and are unique. – guy mograbi Oct 03 '13 at 14:24
  • Possible duplicate of [Duplicate / Copy records in the same MySQL table](http://stackoverflow.com/questions/729489/duplicate-copy-records-in-the-same-mysql-table) – Organic Advocate Nov 23 '16 at 17:23
  • @OrganicAdvocate this has more answers and more views than that question – Drew Nov 23 '16 at 17:28
  • Yes, instead of `update oldtable_tem set key=2;` use `update oldtable_tem set key=NULL;` and then simply `insert into oldtable select * from oldtable_tem;` – Timofey Bugaevsky May 04 '21 at 19:32

26 Answers26

215

I used Leonard Challis's technique with a few changes:

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;

As a temp table, there should never be more than one record, so you don't have to worry about the primary key. Setting it to null allows MySQL to choose the value itself, so there's no risk of creating a duplicate.

If you want to be super-sure you're only getting one row to insert, you could add LIMIT 1 to the end of the INSERT INTO line.

Note that I also appended the primary key value (1 in this case) to my temporary table name.

Grim...
  • 16,518
  • 7
  • 45
  • 61
  • 3
    This solution is correct (in contrast to some other ones that got up votes) in that it allows MySQL to choose the primary key value. – Jan Hettich Feb 01 '13 at 20:46
  • 1
    This approach preserves blob and geospatial data as well. Thanks Grim! – Strixy Sep 04 '13 at 20:26
  • 11
    How can a primary key be null? – Imran Shafqat Dec 04 '13 at 07:42
  • 5
    If it's null, it get automatically assigned the next AI number when it's inserted. – Grim... Dec 11 '13 at 11:08
  • 2
    If the table's schema does not allow for NULL in the primary key, set it to 0 instead of NULL. – Yzmir Ramirez Sep 22 '14 at 20:19
  • My problem was a little different -- I needed to copy a batch of rows to rows with a new primary key. The temporary table was very helpful, and saved a lot of work. I inserted the desired rows into a temporary table, changed the primary keys and inserted that info back into the original table. Much less trouble than doing it one column at a time. – Betty Mock Dec 12 '14 at 03:39
  • I used this technique and got a DB error Column 'id' cannot be null UPDATE tmptable_1 SET id = NULL, seems that it may be more complicated that it first seems – Keith Ivison Dec 17 '16 at 14:47
  • 4
    IMRAN - you may well ask. I thought perhaps the id field of the temporary table wasn't made a PK automatically (I'm pretty sure SQL Server doesn't do so in these circumstances) but it is. I needed to do ALTER TABLE tmptable_1 MODIFY `primarykey` INT NULL; after the first line to make the solution work – DJDave Feb 14 '17 at 08:43
  • 1
    If safe update mode is enabled and you can't add `id = NULL`, use `SET SQL_SAFE_UPDATES = 0;` before the update statement to disable it then `SET SQL_SAFE_UPDATES = 1;` directly after to re-enable it. – EternalHour Nov 01 '17 at 08:39
  • this method need the permission to call "create", right? ah! – Sunny Chow Mar 21 '19 at 09:14
64

Update 07/07/2014 - The answer based on my answer, by Grim..., is a better solution as it improves on my solution below, so I'd suggest using that.

You can do this without listing all the columns with the following syntax:

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;

You may decide to change the primary key in another way.

LeonardChallis
  • 7,759
  • 6
  • 45
  • 76
  • 18
    This is basically the same solution as the OP had already provided for their own problem, albeit with _actual_ temp tables, and slightly cleaner create pattern. I think the OP asked for a _better approach_ to what they were already using, not a clean up of their existing syntax. Don't really understand all the upvotes for this. – Sepster Oct 03 '12 at 13:18
  • Thank you. Its going well with dynamic function – Sonal Khunt Feb 19 '13 at 05:53
  • Is it necessary to delete the tmptable once this process has finished? – SSH This May 30 '13 at 01:10
  • "By default all the temporary tables are deleted by MySQL when your database connection gets terminated. Still you want to delete them in between then you do so by issuing DROP TABLE command." [More here](http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm) – LeonardChallis May 30 '13 at 07:32
  • Given you created the `tmptable`, you don't need to add the `WHERE primarykey = 2` statement for the last line too. (I.e., just `INSERT INTO table SELECT * FROM tmptable`.) – Marcus Dec 16 '13 at 21:02
  • I don't know if the text on the tutorialspoint website has changed or what, but clicking on @LeonardChallis' [More here](http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm) link above I see deletion instructions with very different meaning due to the inclusion of the word IF: "By default, all the temporary tables are deleted by MySQL when your database connection gets terminated. Still IF [emphasis added] you want to delete them in between, then you do so by issuing DROP TABLE command." This says to me it's NOT necessary to manually drop the temporary table (in most circumstances). – pjd Mar 11 '15 at 15:34
  • @Sepster the upvoters are likely visitors to the article that tried to solve a slightly different problem than the one that OP had stated. This answer is clean and provides a general idea of how to approach copying rows in general. – AstroSharp Jul 15 '20 at 23:59
49

I'm assuming you want the new record to have a new primarykey? If primarykey is AUTO_INCREMENT then just do this:

INSERT INTO table (col1, col2, col3, ...)
SELECT col1, col2, col3, ... FROM table
  WHERE primarykey = 1

...where col1, col2, col3, ... is all of the columns in the table except for primarykey.

If it's not an AUTO_INCREMENT column and you want to be able to choose the new value for primarykey it's similar:

INSERT INTO table (primarykey, col2, col3, ...)
SELECT 567, col2, col3, ... FROM table
  WHERE primarykey = 1

...where 567 is the new value for primarykey.

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • 50
    How come this is upvoted 7 times when it ignores the question? *... but i don't want list all the columns after the "select",cause this table has too many columns ...* – LeonardChallis May 02 '12 at 09:49
  • 8
    -1 as this is precisely what the OP wants to avoid. Read the question, or at least offer an answer like "this is the only possible way". – devios1 Jul 24 '12 at 17:51
  • 5
    Because sometimes the question itself is wrong. :) Duplicating rows without altering the content increases redundancy. Changing the database structure to minimize redundancy should be recommended, if it is possible. – Torben Sep 20 '13 at 13:43
  • 6
    Just because it's not right under normal practices doesn't make it wrong. There are plenty of times when standard best practices don't apply. Example: the database represents documents and a user needs to preserve a copy of a document before making changes. – ima747 Nov 26 '13 at 12:58
  • 1
    The question is not wrong at all. What if you have stored some complex structure that took time to configure and the user then wants to make a copy of it because she wants to tweak a few things here and there to make it current, all the while preserving the old one for historical purposes? – s.m. Jun 04 '14 at 09:46
  • 11
    Because you might land on this page not wanting exactly the same as the OP – jx12345 May 18 '17 at 10:01
17

You almost had it with the your first query you just need to specify the columns, that way you can exclude your primary key in the insert which will enact the auto-increment you likely have on the table to automatically create a new primary key for the entry.

For example change this:

insert into table select * from table where primarykey=1

To this:

INSERT INTO table (col1, col2, col3) 
SELECT col1, col2, col3 
FROM table 
WHERE primarykey = 1

Just don't include the primarykey column in either the column list for the INSERT or for the SELECT portions of the query.

Braeden Black
  • 443
  • 4
  • 6
  • 1
    is there a way to pull most of the columns through the select statement but update one of them manually in the insert command? such as `insert into table ("val1", col2, col3) select col2, col3 from table where primarykey = 1` or something similar? – fIwJlxSzApHEZIl Oct 25 '18 at 22:45
  • 1
    Found it! Copy values from one row but add one of your own values into the insert statement: https://stackoverflow.com/questions/23971078/copy-one-row-from-a-table-to-another-and-insert-value-of-one-column-in-same-quer – fIwJlxSzApHEZIl Oct 25 '18 at 22:46
  • 1
    Sorry was just notified of your questions, glad you found it, that is indeed the way. – Braeden Black Oct 26 '18 at 23:23
9

You could also try dumping the table, finding the insert command and editing it:

mysqldump -umyuser -p mydatabase --skip-extended-insert mytable > outfile.sql

The --skip-extended-insert gives you one insert command per row. You may then find the row in your favourite text editor, extract the command and alter the primary key to "default".

  • 2
    +1 from me as this is a good "outside the box" approach that may actually be helpful outside of run-time, in some circumstances. But primarily it's the first answer that actually addresses the OP's question and doesn't just syntactically tweak the solution already provided by the OP. – Sepster Oct 03 '12 at 13:22
7

This can be achieved with some creativity:

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;

This will result in the new row getting an auto incremented id instead of the id from the selected row.

curmil
  • 1,077
  • 13
  • 9
6

This procedure assumes that:

  • you don't have _duplicate_temp_table
  • your primary key is int
  • you have access to create table

Of course this is not perfect, but in certain (probably most) cases it will work.

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;
  • 1
    +1 Haven't confirmed this `works` but the approach is sound, and is of value because it is unique here and does actually address the OP's question. – Sepster Oct 03 '12 at 13:25
6

If your table's primary key field is an auto increment field, then you can use query with columns. For example, your table named test_tbl has 3 fields as id, name, age. id is a primary key field and auto increment, so you can use the following query to duplicate the row:

INSERT INTO `test_tbl` (`name`,`age`) SELECT `name`,`age` FROM `test_tbl`;

This query results in duplicating every row.


If your table's primary key field is not an auto increment field, then you can use the following method:

INSERT INTO `test_tbl` (`id`,`name`,`age`)
  SELECT 20,`name`,`age` FROM `test_tbl` WHERE id = 19;

The result of this query is a duplicate row of id=19 inserted as id=20.

Félix Saparelli
  • 8,424
  • 6
  • 52
  • 67
user2595171
  • 85
  • 1
  • 1
  • That is the best answer there is, the case is pretty straightforward: INSERT INTO `tableName` (`fieldName1`, `fieldName2`, `fieldName3`) SELECT `fieldName1`, `fieldName2`, `fieldName3` FROM `tableName` WHERE 1 (to copy all of them at once) – jakubplus Jun 15 '16 at 09:53
  • Seconded - this answer is succinct and in the spirit of actually "Copying" a row. – user37309 Sep 21 '19 at 04:26
5

I used Grim's technique with a little change: If someone looking for this query is because can't do a simple query due to primary key problem:

INSERT INTO table SELECT * FROM table WHERE primakey=1;

With my MySql install 5.6.26, key isn't nullable and produce an error:

#1048 - Column 'primakey' cannot be null 

So after create temporary table I change the primary key to a be nullable.

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;
Luca Camillo
  • 796
  • 9
  • 9
4

clone row with update fields and auto increment value

CREATE TEMPORARY TABLE `temp` SELECT * FROM `testing` WHERE id = 14;

UPDATE `temp` SET id = (SELECT id FROM testing ORDER by id DESC LIMIT 1
 )+1, user_id = 252 ,policy_no = "mysdddd12" where id = 14;

INSERT INTO `testing` SELECT * FROM `temp`;

DROP TEMPORARY TABLE IF EXISTS `temp`;
Muhammed Neswine
  • 2,028
  • 1
  • 20
  • 20
  • @Torben Please check the tick on the left of the question (mark it as accepted) so that everyone will know it worked for you. – HosseyNJF Jun 01 '20 at 20:08
4

I used in my Koha database to insert duplicate items with the 'C' prefix in barcode column:

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

Some of the following was gleaned off of this site. This is what I did to duplicate a record in a table with any number of fields:

This also assumes you have an AI field at the beginning of the table

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
}
richardwhitney
  • 506
  • 1
  • 6
  • 21
3

I might be late in this, but I have a similar solution which has worked for me.

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

This way I don't need to create a temporary table and etc. As the row is copied in the same table the Max(PK)+1 function can be used easily.

I came looking for the solution of this question (had forgotten the syntax) and I ended up making my own query. Funny how things work out some times.

Regards

echo_salik
  • 842
  • 1
  • 18
  • 35
3

If the Primary Key is Auto Increment, just specify each field except the primary key.

INSERT INTO table(field1,field2,field3) SELECT (field1,field2,field3) FROM table WHERE primarykey=1

Fedy Venom
  • 399
  • 4
  • 11
3

I updated @LeonardChallis's solution as it didn't work for me as none of the others. I removed the WHERE clauses and SET primaryKey = 0 in the temp table so MySQL auto-increments itself the primaryKey

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

This is of course to duplicate all the rows in the table.

D4V1D
  • 5,805
  • 3
  • 30
  • 65
2

I would use below,

insert into ORDER_ITEM select * from ORDER_ITEM where ITEM_NUMBER =123;
Ishan Liyanage
  • 2,237
  • 1
  • 26
  • 25
1

I just had to do this and this was my manual solution:

  1. In phpmyadmin, check the row you wish to copy
  2. At the bottom under query result operations click 'Export'
  3. On the next page check 'Save as file' then click 'Go'
  4. Open the exported file with a text editor, find the value of the primary field and change it to something unique.
  5. Back in phpmyadmin click on the 'Import' tab, locate the file to import .sql file under browse, click 'Go' and the duplicate row should be inserted.

If you don't know what the PRIMARY field is, look back at your phpmyadmin page, click on the 'Structure' tab and at the bottom of the page under 'Indexes' it will show you which 'Field' has a 'Keyname' value 'PRIMARY'.

Kind of a long way around, but if you don't want to deal with markup and just need to duplicate a single row there you go.

user27068
  • 179
  • 2
  • 10
  • Nice, answers the op in an out of the box kind of way. Doesn't work for all cases, obviously, such as blobs and geospatial data, but pretty easy to pull off and does work for those odd ball changes. – Strixy Sep 04 '13 at 19:32
1

This solution showed above works perfect also for selected rows. For example I am creating demonstration rows for my nice2work project, and this works perfect.

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

Sorry for the necropost but this is what I turned up with google and since I found this helpful but problematic I wanted to contribute an important modification for anyone else who digs this up.

First off, I'm using SQL Server, not MySQL, but I think it should work similarly. I used Leonard Challis' solution because it was simplest and met the need, however there's a problem with this - if you simply take the PK and increment it by 1 then what happens if you've added other records since the row in question was added. I decided it was best to just let the system handle the autoincrementing of the PK, so I did the following:

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

I believe this would work similarly in MySQL, but I can't test this, sorry

maxx233
  • 108
  • 8
0

I know it's an old question, but here is another solution:

This duplicates a row in the main table, assuming the primary key is auto-increment, and creates copies of linked-tables data with the new main table id.

Other options for getting column names:
-SHOW COLUMNS FROM tablename; (Column name: Field)
-DESCRIBE tablename (Column name: Field)
-SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' (Column name: column_name)

//First, copy main_table row
$ColumnHdr='';
$Query="SHOW COLUMNS FROM `main_table`;";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
while($Row=mysql_fetch_array($Result))
{
    if($Row['Field']=='MainTableID')     //skip main table id in column list
        continue;
    $ColumnHdr.=",`" . $Row['Field'] . "`";
}
$Query="INSERT INTO `main_table` (" . substr($ColumnHdr,1) . ")
        (SELECT " . substr($ColumnHdr,1) . " FROM `main_table`
            WHERE `MainTableID`=" . $OldMainTableID . ");";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
$NewMainTableID=mysql_insert_id($link);

//Change the name (assumes a 30 char field)
$Query="UPDATE `main_table` SET `Title`=CONCAT(SUBSTRING(`Title`,1,25),' Copy') WHERE `MainTableID`=" . $NewMainTableID . ";";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);

//now copy in the linked tables
$TableArr=array("main_table_link1","main_table_link2","main_table_link3");
foreach($TableArr as $TableArrK=>$TableArrV)
{
    $ColumnHdr='';
    $Query="SHOW COLUMNS FROM `" . $TableArrV . "`;";
    $Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
    while($Row=mysql_fetch_array($Result))
    {
        if($Row['Field']=='MainTableID')     //skip main table id in column list, re-added in query
            continue;
        if($Row['Field']=='dbID')    //skip auto-increment,primary key in linked table
            continue;
        $ColumnHdr.=",`" . $Row['Field'] . "`";
    }

    $Query="INSERT INTO `" . $TableArrV . "` (`MainTableID`," . substr($ColumnHdr,1) . ")
            (SELECT " . $NewMainTableID . "," . substr($ColumnHdr,1) . " FROM `" . $TableArrV . "`
             WHERE `MainTableID`=" . $OldMainTableID . ");";
    $Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
}
Paul
  • 311
  • 4
  • 8
0

max233 was certainly on the right track, at least for the autoincrement case. However, do not do the ALTER TABLE. Simply set the auto-increment field in the temporary table to NULL. This will present an error, but the following INSERT of all fields in the temporary table will happen and the NULL auto field will obtain a unique value.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
0

Just wanted to post my piece of PHP code, because I think the way I collect the columns is a bit cleaner in code than the previous examples. Also this shows how you could easily alter an field, in this case adding a string. But you could also replace a foreign key field with the newly added record, in case you want to copy some child records as well.

  // Read columns, unset the PK (always the first field in my case)
  $stmt = $conn->prepare('SHOW COLUMNS FROM template');
  $stmt->execute();

  $columns = $stmt->fetchAll();
  $columns = array_map(function ($element) { return $element['Field']; }, $columns);

  unset($columns[0]);

  // Insert record in the database. Add string COPY to the name field.
  $sql = "INSERT INTO `template` (".implode(",", $columns).")";
  if ($key = array_search('name', $columns))
      $columns[$key] = "CONCAT(name, ' COPY')";
  $sql .= " SELECT ".implode(",", $columns)." FROM `template` WHERE `id` = ".$id;

  $stmt = $conn->prepare($sql);
  $stmt->execute();
rolandow
  • 1,049
  • 1
  • 15
  • 28
0

Create a table

    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 a row

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

Clone row insert above

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;

Test

SELECT * FROM `sample_table`;
Abdullah
  • 968
  • 12
  • 17
  • Note: If you are getting error ( #1048 ) use '' instead of NULL – Abdullah Oct 18 '15 at 13:06
  • Is it just me or is this **exactly** what the OP **didn't** want? (I.e. manually adding every column to the query.) – Byson Jan 07 '16 at 13:40
  • You are right, I just read OP's "I JUST want to copy one row to insert into the same table" sentence, maybe, anyway this is still useful for "Duplicate entry 'xxx' for key ???" error ^^ – Abdullah Feb 04 '16 at 17:19
0

Here's an answer I found online at this site Describes how to do the above1 You can find the answer at the bottom of the page. Basically, what you do is copy the row to be copied to a temporary table held in memory. You then change the Primary Key number using update. You then re-insert it into the target table. You then drop the table.

This is the code for it:

CREATE TEMPORARY TABLE rescueteam ENGINE=MEMORY SELECT * FROMfitnessreport4 WHERE rID=1;# 1 row affected. UPDATE rescueteam SET rID=Null WHERE rID=1;# 1 row affected.INSERT INTO fitnessreport4 SELECT * FROM rescueteam;# 1 row affected. DROP TABLE rescueteam# MySQL returned an empty result set (i.e. zero
rows).

I created the temporary table rescueteam. I copied the row from my original table fitnessreport4. I then set the primary key for the row in the temporary table to null so that I can copy it back to the original table without getting a Duplicate Key error. I tried this code yesterday evening and it worked.

0

This is an additional solution to the answer by "Grim..." There have been some comments on it having a primary key as null. Some comments about it not working. And some comments on solutions. None of the solutions worked for us. We have MariaDB with the InnoDB table.

We could not set the primary key to allow null. Using 0 instead of NULL led to duplicate value error for the primary key. SET SQL_SAFE_UPDATES = 0; Did not work either.

The solution from "Grim..." did work IF we changed our PRIMARY KEY to UNIQUE instead

Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73
Simon
  • 66
  • 5
0

Drawing from answers above, and elsewhere on SO, I came to this as my final code for cloning one record:

CREATE TEMPORARY TABLE temptable SELECT * FROM things WHERE Thing_ID = 10000345;
UPDATE temptable SET Thing_ID = 0;
INSERT INTO things SELECT * FROM temptable;
DROP TEMPORARY TABLE IF EXISTS temptable;

Setting the value of the PRIMARY key, the Thing_ID, to be = 0 is shorter than altering the temptable to allow NULL and then setting the PRIMARY key to NULL - and, for me, it works in MySQL.

Geoff Kendall
  • 1,307
  • 12
  • 13