ใน MySQL ฉันสามารถคัดลอกหนึ่งแถวเพื่อแทรกลงในตารางเดียวกันได้หรือไม่


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

ฉันต้องการคัดลอกหนึ่งแถวเพื่อแทรกลงในตารางเดียวกัน (เช่นฉันต้องการทำซ้ำแถวที่มีอยู่ในตาราง) แต่ฉันต้องการทำสิ่งนี้โดยไม่ต้องแสดงรายการคอลัมน์ทั้งหมดหลัง "เลือก" เนื่องจากตารางนี้มี คอลัมน์มากเกินไป

แต่เมื่อฉันทำสิ่งนี้ฉันได้รับข้อผิดพลาด:

รายการที่ซ้ำกัน '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;

มีวิธีที่ง่ายกว่าในการแก้ปัญหานี้หรือไม่?


ฉันเพิ่งมีความคิดเห็นเกี่ยวกับค่าฮาร์ดโค้ดสำหรับคีย์ ฉันจะทำอะไรแบบmax(oldtable.id) + oldtable_temp.keyนี้เพื่อให้แน่ใจว่ารหัสเพิ่มขึ้นและไม่ซ้ำกัน
guy mograbi


@OrganicAdvocate มีคำตอบเพิ่มเติมและจำนวนการดูมากกว่าคำถามนั้น
Drew

คำตอบ:


189

ฉันใช้เทคนิคของ 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;

ในฐานะที่เป็นตารางชั่วคราวไม่ควรมีมากกว่าหนึ่งระเบียนดังนั้นคุณไม่ต้องกังวลเกี่ยวกับคีย์หลัก การตั้งค่าให้เป็นโมฆะทำให้ MySQL สามารถเลือกค่าได้เองดังนั้นจึงไม่มีความเสี่ยงในการสร้างซ้ำ

หากคุณต้องการมั่นใจอย่างยิ่งว่าคุณจะได้รับเพียงหนึ่งแถวเพื่อแทรกคุณสามารถเพิ่ม LIMIT 1 ต่อท้ายบรรทัด INSERT INTO

โปรดทราบว่าฉันยังผนวกค่าคีย์หลัก (1 ในกรณีนี้) ต่อท้ายชื่อตารางชั่วคราวของฉัน


3
วิธีนี้ถูกต้อง (ตรงกันข้ามกับคนอื่น ๆ ที่ได้คะแนนโหวต) ซึ่งทำให้ MySQL สามารถเลือกค่าคีย์หลัก
Jan Hettich

1
แม้ว่าจะไม่ทำงานอย่างแน่นอนเนื่องจากชื่อตารางชั่วคราวที่ไม่สอดคล้องกัน ( tmptable_1vs. tmptable)
Kieran Tully

9
คีย์หลักจะเป็นโมฆะได้อย่างไร
Imran Shafqat

5
หากเป็นโมฆะจะได้รับหมายเลข AI ถัดไปโดยอัตโนมัติเมื่อใส่เข้าไป
กลัว ...

3
IMRAN - คุณอาจถาม ฉันคิดว่าบางทีฟิลด์ id ของตารางชั่วคราวไม่ได้ทำ PK โดยอัตโนมัติ (ฉันค่อนข้างแน่ใจว่า SQL Server ไม่ได้ทำในสถานการณ์เหล่านี้) แต่ก็เป็นเช่นนั้น ฉันต้องแก้ไข ALTER TABLE tmptable_1 MODIFY primarykeyINT NULL; หลังจากบรรทัดแรกเพื่อให้การแก้ปัญหาทำงาน
DJDave

61

อัปเดตเมื่อวันที่ 07/07/2014 - คำตอบที่อิงตามคำตอบของฉันโดย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;

คุณอาจตัดสินใจเปลี่ยนคีย์หลักด้วยวิธีอื่น


16
นี่เป็นวิธีแก้ปัญหาเดียวกับที่ OP ได้เตรียมไว้สำหรับปัญหาของตัวเองแม้ว่าจะมีตารางอุณหภูมิจริงและสร้างรูปแบบที่สะอาดขึ้นเล็กน้อย ฉันคิดว่า OP ขอวิธีที่ดีกว่าสำหรับสิ่งที่พวกเขาใช้อยู่แล้วไม่ใช่การล้างไวยากรณ์ที่มีอยู่ของพวกเขา ไม่เข้าใจ upvotes ทั้งหมดสำหรับเรื่องนี้
Sepster

ขอบคุณ. เป็นไปได้ด้วยฟังก์ชั่นไดนามิก
Sonal Khunt

จำเป็นต้องลบ tmptable เมื่อกระบวนการนี้เสร็จสิ้นหรือไม่
SSH นี้

"โดยค่าเริ่มต้นตารางชั่วคราวทั้งหมดจะถูกลบโดย MySQL เมื่อการเชื่อมต่อฐานข้อมูลของคุณถูกยกเลิก แต่คุณยังต้องการลบในระหว่างนั้นโดยการออกคำสั่ง DROP TABLE" เพิ่มเติมได้ที่นี่
LeonardChallis

เมื่อคุณสร้างtmptableคุณไม่จำเป็นต้องเพิ่มWHERE primarykey = 2คำสั่งสำหรับบรรทัดสุดท้ายด้วย (เช่นเพิ่งINSERT INTO table SELECT * FROM tmptable)
Marcus

42

ฉันสมมติว่าคุณต้องการให้บันทึกใหม่มีใหม่primarykeyหรือไม่ ถ้าprimarykeyเป็นAUTO_INCREMENTเช่นนั้นเพียงแค่ทำสิ่งนี้:

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

... ที่col1, col2, col3, ...มีทั้งหมดของคอลัมน์ในตารางยกเว้น primarykey

หากไม่ใช่AUTO_INCREMENTคอลัมน์และคุณต้องการเลือกค่าใหม่ให้primarykeyคล้ายกัน:

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

... ที่เป็นค่าใหม่สำหรับ567primarykey


41
ทำไมสิ่งนี้ถึงถูกโหวตขึ้น 7 ครั้งเมื่อมันไม่สนใจคำถาม ... แต่ฉันไม่ต้องการรายการทั้งหมดคอลัมน์หลังจากที่ "เลือก" สาเหตุตารางนี้มีคอลัมน์มากเกินไป ...
LeonardChallis

7
-1 เนื่องจากนี่เป็นสิ่งที่ OP ต้องการหลีกเลี่ยง อ่านคำถามหรืออย่างน้อยเสนอคำตอบเช่น "นี่เป็นวิธีเดียวที่เป็นไปได้"
devios1

5
เพราะบางครั้งคำถามตัวเองผิด :) การทำสำเนาแถวโดยไม่แก้ไขเนื้อหาจะเพิ่มความซ้ำซ้อน แนะนำให้เปลี่ยนโครงสร้างฐานข้อมูลเพื่อลดความซ้ำซ้อนหากเป็นไปได้
Torben

5
เพียงเพราะมันไม่ถูกต้องภายใต้การปฏิบัติปกติไม่ได้ทำให้ผิด มีหลายครั้งที่การปฏิบัติที่ดีที่สุดมาตรฐานไม่ได้นำไปใช้ ตัวอย่าง: ฐานข้อมูลแทนเอกสารและผู้ใช้จำเป็นต้องเก็บรักษาสำเนาของเอกสารไว้ก่อนทำการเปลี่ยนแปลง
ima747

6
เพราะคุณอาจลงจอดบนหน้านี้ไม่ต้องการเหมือนกับ OP
jx12345

13

คุณเกือบจะได้รับมันด้วยแบบสอบถามแรกของคุณคุณเพียงแค่ต้องระบุคอลัมน์วิธีที่คุณสามารถยกเว้นคีย์หลักของคุณในการแทรกซึ่งจะประกาศการเพิ่มอัตโนมัติที่คุณน่าจะมีในตารางเพื่อสร้างคีย์หลักใหม่โดยอัตโนมัติ การเข้า

ตัวอย่างเช่นเปลี่ยนสิ่งนี้:

insert into table select * from table where primarykey=1

สำหรับสิ่งนี้:

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

ไม่ต้องรวมคอลัมน์คีย์หลักในรายการคอลัมน์สำหรับ INSERT หรือส่วน SELECT ของแบบสอบถาม


1
มีวิธีดึงคอลัมน์ส่วนใหญ่ผ่านคำสั่ง select แต่อัพเดตหนึ่งคอลัมน์ด้วยตนเองในคำสั่งแทรกหรือไม่ เช่นinsert into table ("val1", col2, col3) select col2, col3 from table where primarykey = 1หรืออะไรที่คล้ายกัน?
anon58192932

1
พบมัน! คัดลอกค่าจากหนึ่งแถว แต่เพิ่มค่าของคุณเองลงในคำสั่งแทรก: stackoverflow.com/questions/23971078/…
anon58192932

1
ขออภัยได้รับแจ้งจากคำถามของคุณดีใจที่คุณพบนั่นเป็นวิธีที่แน่นอน
Braeden Black

9

คุณสามารถลองทิ้งตารางค้นหาคำสั่งแทรกและแก้ไข:

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

--skip-extended-insertช่วยให้คุณมีคำสั่งแทรกหนึ่งต่อแถว จากนั้นคุณสามารถค้นหาแถวในเท็กซ์เอดิเตอร์ที่คุณชื่นชอบแตกคำสั่งและเปลี่ยนคีย์หลักเป็น "default"


2
+1 จากฉันเนื่องจากนี่เป็นวิธีการ "นอกกรอบ" ที่ดีซึ่งอาจมีประโยชน์นอกเวลาทำงานในบางกรณี แต่ส่วนใหญ่มันเป็นคำตอบแรกที่ตอบคำถามของ OP และไม่เพียงแค่ปรับแก้ปัญหาที่มีอยู่ใน OP แล้ว
Sepster

6

ขั้นตอนนี้จะถือว่า:

  • คุณไม่มี _duplicate_temp_table
  • คีย์หลักของคุณคือ int
  • คุณสามารถเข้าถึงเพื่อสร้างตาราง

แน่นอนว่ามันไม่สมบูรณ์แบบ แต่ในบางกรณี (อาจมากที่สุด) มันจะทำงานได้

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 ยังไม่ได้รับการยืนยันworksแต่วิธีการฟังดูดีและมีคุณค่าเพราะมันไม่เหมือนกันที่นี่และตอบคำถามของ OP ได้จริง
Sepster

5

สามารถทำได้ด้วยความคิดสร้างสรรค์:

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;

ซึ่งจะส่งผลให้แถวใหม่ได้รับรหัสที่เพิ่มขึ้นอัตโนมัติแทนที่จะเป็นรหัสจากแถวที่เลือก


นี่ควรเป็นคำตอบที่ยอมรับได้!
Felipe Desiderati

5

ถ้าเขตข้อมูลคีย์หลักของตารางของคุณเป็นเขตข้อมูลเพิ่มอัตโนมัติคุณสามารถใช้แบบสอบถามกับคอลัมน์ได้ ตัวอย่างเช่นตารางของคุณชื่อtest_tblมี 3 ฟิลด์id, name, ageดังนี้ idเป็นเขตข้อมูลคีย์หลักและเพิ่มขึ้นอัตโนมัติดังนั้นคุณสามารถใช้แบบสอบถามต่อไปนี้เพื่อทำซ้ำแถว:

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

แบบสอบถามนี้ส่งผลให้เกิดการทำซ้ำทุกแถว


หากฟิลด์คีย์หลักของตารางของคุณไม่ใช่ฟิลด์การเพิ่มอัตโนมัติคุณสามารถใช้วิธีการต่อไปนี้:

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

ผลของแบบสอบถามนี้คือแถวซ้ำแทรกเป็นid=19id=20


นั่นคือคำตอบที่ดีที่สุดที่มีในกรณีที่ตรงไปตรงสวย: แทรกtableName( fieldName1, fieldName2, fieldName3) SELECT fieldName1, fieldName2, fieldName3จากtableNameWHERE 1 (การคัดลอกทั้งหมดของพวกเขาในครั้งเดียว)
jakubplus

Seconded - คำตอบนี้สั้นกระชับและในความจริงแล้ว "คัดลอก" แถว
37309

4

แถวโคลนที่มีฟิลด์อัปเดตและค่าการเพิ่มอัตโนมัติ

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`;

@Torben โปรดตรวจสอบเห็บทางด้านซ้ายของคำถาม (ทำเครื่องหมายเป็นที่ยอมรับ) เพื่อให้ทุกคนรู้ว่ามันได้ผลสำหรับคุณ
HosseyNJF

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

ฉันใช้เทคนิคของ Grim กับการเปลี่ยนแปลงเล็กน้อย: หากใครบางคนกำลังมองหาข้อความค้นหานี้ก็เพราะไม่สามารถทำแบบสอบถามง่ายๆได้เนื่องจากปัญหาคีย์หลัก:

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

ด้วย MySql ของฉันติดตั้ง 5.6.26 กุญแจไม่สามารถลบล้างได้และทำให้เกิดข้อผิดพลาด:

#1048 - Column 'primakey' cannot be null 

ดังนั้นหลังจากสร้างตารางชั่วคราวฉันเปลี่ยนคีย์หลักให้เป็นโมฆะ

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;

หรือในเวอร์ชั่นใหม่ของ mariadb / mysql primaryKey สามารถตั้งค่าเป็น 0 ซึ่งช่วยให้การเพิ่มอัตโนมัติทำงานเมื่อแทรก
shelbypereira

2

ฉันอาจจะมาสายนี้ แต่ฉันมีวิธีแก้ปัญหาแบบเดียวกันซึ่งใช้ได้กับฉัน

 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 table(field1,field2,field3) SELECT (field1,field2,field3) FROM table WHERE primarykey=1


2

ฉันอัปเดตวิธีแก้ปัญหาของ @ LeonardChallis เนื่องจากไม่ได้ผลสำหรับฉันเนื่องจากไม่มีวิธีการอื่น ฉันลบส่วนWHEREคำสั่งและSET primaryKey = 0ในตาราง temp เพื่อให้ MySQL เพิ่มค่าตัวหลักอัตโนมัติ

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

แน่นอนว่าจะเป็นการทำซ้ำแถวทั้งหมดในตาราง


2

ฉันจะใช้ด้านล่าง

insert into ORDER_ITEM select * from ORDER_ITEM where ITEM_NUMBER =123;

1
ไม่สามารถใช้งานได้หาก ITEM_NUMBER เป็นคีย์หลักของคุณซึ่งมีโอกาสเกิดขึ้นในสถานการณ์นี้
Billy Pilgrim

2

ฉันใช้ในฐานข้อมูล Kohaของฉันเพื่อแทรกรายการที่ซ้ำกันด้วยคำนำหน้า 'C' ในคอลัมน์บาร์โค้ด :

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

1

ฉันต้องทำสิ่งนี้และนี่เป็นวิธีแก้ปัญหาด้วยตนเองของฉัน:

  1. ในphpmyadminให้ตรวจสอบแถวที่คุณต้องการคัดลอก
  2. ที่ด้านล่างใต้การดำเนินการเกี่ยวกับผลการค้นหาให้คลิก'ส่งออก'
  3. ในหน้าถัดไปให้ทำเครื่องหมาย'บันทึกเป็นไฟล์'จากนั้นคลิก'ไป'
  4. เปิดไฟล์ที่ส่งออกด้วยโปรแกรมแก้ไขข้อความค้นหาค่าของฟิลด์หลักและเปลี่ยนเป็นสิ่งที่ไม่ซ้ำ
  5. ย้อนกลับไปในphpMyAdminคลิกที่'นำเข้า'แท็บค้นหาไฟล์ที่จะนำเข้าไฟล์ .sql ภายใต้การดูคลิก'ไป'และแถวที่ซ้ำกันควรแทรก

หากคุณไม่ทราบว่าหลักเขตคือมองย้อนกลับไปที่คุณphpMyAdminหน้าให้คลิกที่'โครงสร้าง'แท็บและที่ด้านล่างของหน้าภายใต้'ดัชนี'มันจะแสดงให้คุณเห็นว่า'ฟิลด์'มี'ชื่อคีย์'ค่า'หลัก'

ค่อนข้างไกล แต่ถ้าคุณไม่ต้องการจัดการกับมาร์กอัปและจำเป็นต้องทำซ้ำแถวเดียว


Nice ตอบ op ในรูปแบบของกล่อง ไม่สามารถใช้ได้กับทุกกรณีอย่างเห็นได้ชัดเช่นข้อมูล blobs และ geospatial แต่ค่อนข้างง่ายที่จะดึงออกและใช้งานได้กับการเปลี่ยนแปลงของลูกบอลคี่เหล่านั้น
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

ขออภัยที่ necropost แต่นี่คือสิ่งที่ฉันเปิดขึ้นด้วย google และเนื่องจากฉันพบว่ามีประโยชน์ แต่มีปัญหาฉันต้องการมีส่วนร่วมในการแก้ไขที่สำคัญสำหรับทุกคนที่ขุดขึ้นมานี้

ก่อนอื่นฉันใช้ 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 แต่ฉันไม่สามารถทดสอบได้ขออภัย


1
ตอบโดยสิ้นเชิง bakwaas
AsadYarKhan

0

ฉันรู้ว่ามันเป็นคำถามเก่า แต่นี่เป็นวิธีแก้ปัญหาอื่น:

สิ่งนี้ซ้ำแถวในตารางหลักสมมติว่าคีย์หลักคือการเพิ่มขึ้นอัตโนมัติและสร้างสำเนาของข้อมูลตารางที่เชื่อมโยงกับรหัสตารางหลักใหม่

ตัวเลือกอื่น ๆ สำหรับรับชื่อคอลัมน์:
-SHOW COLUMNS FROM tablename; (ชื่อคอลัมน์: ฟิลด์)
-DESCRIBE tablename (ชื่อคอลัมน์: ฟิลด์)
-SELECT column_name จาก data_schema.columns WHERE table_name = 'tablename' (ชื่อคอลัมน์: 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__);
}

0

max233 เป็นเส้นทางที่ถูกต้องอย่างน้อยในกรณีของการบันทึกภาพอัตโนมัติ อย่างไรก็ตามอย่าทำ ALTER TABLE เพียงตั้งค่าฟิลด์การเพิ่มอัตโนมัติในตารางชั่วคราวเป็น NULL สิ่งนี้จะแสดงข้อผิดพลาด แต่จะแทรก INSERT ต่อไปนี้ของเขตข้อมูลทั้งหมดในตารางชั่วคราวและฟิลด์ NULL auto จะได้รับค่าที่ไม่ซ้ำกัน


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 Aydın

มันเป็นเพียงฉันหรือนี้คือว่าสิ่งที่สหกรณ์ไม่ต้องการได้หรือไม่ (นั่นคือการเพิ่มทุกคอลัมน์ในแบบสอบถามด้วยตนเอง)
Byson

คุณพูดถูกฉันเพิ่งอ่านประโยค OP ของ "ฉันแค่ต้องการคัดลอกหนึ่งแถวเพื่อแทรกลงในตารางเดียวกัน" บางทีนี่อาจเป็นประโยชน์สำหรับ "รายการซ้ำ 'xxx' สำหรับคีย์ ??? ข้อผิดพลาด ^^
Abdullah Aydın

0

นี่คือคำตอบที่ฉันพบทางออนไลน์ที่ไซต์นี้อธิบายวิธีการด้านบน1 คุณสามารถหาคำตอบได้ที่ด้านล่างของหน้า โดยทั่วไปสิ่งที่คุณทำคือคัดลอกแถวที่จะคัดลอกไปยังตารางชั่วคราวที่เก็บไว้ในหน่วยความจำ จากนั้นคุณเปลี่ยนหมายเลขคีย์หลักโดยใช้การอัปเดต จากนั้นคุณแทรกเข้าไปในตารางเป้าหมายอีกครั้ง จากนั้นคุณวางโต๊ะ

นี่คือรหัสสำหรับมัน:

สร้างเครื่องมือตารางชั่วคราวrescueteam= เลือกหน่วยความจำ * จากที่fitnessreport4rID = 1; # 1 แถวได้รับผลกระทบ UPDATE rescueteamSET rID = NULL WHERE rID = 1; # 1 แถวที่ได้รับผลกระทบ INSERT INTO fitnessreport4SELECT * FROM rescueteam; # 1 แถวที่ได้รับผลกระทบ DROP Table rescueteam# MySQL ส่งคืนชุดผลลัพธ์ที่ว่างเปล่า (เช่นศูนย์
แถว)

ฉันสร้าง rescueteam ตารางชั่วคราว ฉันคัดลอกแถวจาก tablereport4 เดิมของฉัน จากนั้นฉันจะตั้งค่าคีย์หลักสำหรับแถวในตารางชั่วคราวเป็นโมฆะเพื่อให้ฉันสามารถคัดลอกกลับไปยังตารางดั้งเดิมโดยไม่ได้รับข้อผิดพลาดของคีย์ซ้ำ ฉันลองใช้รหัสนี้เมื่อเย็นวานและทำงานได้


0

นี่เป็นทางออกเพิ่มเติมสำหรับคำตอบโดย "น่ากลัว ... " มีความคิดเห็นบางส่วนเกี่ยวกับคำตอบที่มีคีย์หลักเป็นโมฆะ ความคิดเห็นบางอย่างเกี่ยวกับมันไม่ทำงาน และความคิดเห็นบางส่วนเกี่ยวกับการแก้ปัญหา ไม่มีวิธีแก้ปัญหาใดที่เหมาะกับเรา เรามี MariaDB พร้อมโต๊ะ InnoDB

เราไม่สามารถตั้งค่าคีย์หลักเพื่อให้เป็นโมฆะ การใช้ 0 แทน NULL ทำให้เกิดข้อผิดพลาดค่าซ้ำกันสำหรับคีย์หลัก SET SQL_SAFE_UPDATES = 0;ไม่ทำงานเช่นกัน

วิธีแก้ปัญหาจาก "น่ากลัว ... " ใช้งานได้ถ้าเราเปลี่ยนคีย์หลักเป็น UNIQUE แทน


-1

แค่ต้องการโพสต์โค้ด PHP ของฉันเพราะฉันคิดว่าวิธีที่ฉันรวบรวมคอลัมน์นั้นค่อนข้างสะอาดกว่าโค้ดก่อนหน้านี้ นอกจากนี้ยังแสดงวิธีที่คุณสามารถเปลี่ยนฟิลด์ได้อย่างง่ายดายในกรณีนี้การเพิ่มสตริง แต่คุณสามารถแทนที่เขตข้อมูลคีย์ต่างประเทศด้วยระเบียนที่เพิ่มใหม่ได้ในกรณีที่คุณต้องการคัดลอกระเบียนย่อยบางรายการเช่นกัน

  // 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();

-2

สำหรับวิธีแก้ปัญหาที่ง่ายมากคุณสามารถใช้ PHPMyAdmin เพื่อส่งออกแถวเป็นไฟล์ CSV จากนั้นเพียงนำเข้าไฟล์ CSV ที่แก้ไขแล้ว การแก้ไขคอลัมน์ ID / คีย์หลักเพื่อไม่แสดงค่าก่อนที่คุณจะนำเข้า

SELECT * FROM table where primarykey=1

จากนั้นที่ด้านล่างของหน้า:

ป้อนคำอธิบายรูปภาพที่นี่

ที่พูดว่า "ส่งออก" เพียงแค่ส่งออกจากนั้นแก้ไขไฟล์ csv เพื่อลบค่าคีย์หลักดังนั้นจึงว่างเปล่าและจากนั้นเพียงนำเข้าสู่ฐานข้อมูลจะมีการกำหนดคีย์หลักใหม่ให้กับการนำเข้า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.