Trong MySQL, tôi có thể sao chép một hàng để chèn vào cùng một bảng không?


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

Tôi chỉ muốn sao chép một hàng để chèn vào cùng một bảng (nghĩa là tôi muốn sao chép một hàng hiện có trong bảng) nhưng tôi muốn làm điều này mà không phải liệt kê tất cả các cột sau "chọn", vì bảng này có quá nhiều cột.

Nhưng khi tôi làm điều này, tôi nhận được lỗi:

Mục trùng lặp 'xxx' cho khóa 1

Tôi có thể xử lý việc này bằng cách tạo một bảng khác có cùng cột với vùng chứa tạm thời cho bản ghi tôi muốn sao chép:

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;

Có cách nào đơn giản hơn để giải quyết điều này?


Tôi chỉ có một nhận xét về các giá trị được mã hóa cứng cho khóa. Tôi sẽ làm một cái gì đó như thế max(oldtable.id) + oldtable_temp.keynày để đảm bảo rằng id tăng và là duy nhất.
anh chàng mograbi


@OrganicAdvocate này có nhiều câu trả lời và quan điểm hơn câu hỏi đó
Drew

Câu trả lời:


189

Tôi đã sử dụng kỹ thuật của Leonard Challis với một vài thay đổi:

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;

Là một bảng tạm thời, không bao giờ nên có nhiều hơn một bản ghi, vì vậy bạn không phải lo lắng về khóa chính. Đặt nó thành null cho phép MySQL tự chọn giá trị, do đó không có rủi ro tạo bản sao.

Nếu bạn muốn siêu chắc chắn, bạn chỉ nhận được một hàng để chèn, bạn có thể thêm GIỚI HẠN 1 vào cuối dòng INSERT INTO.

Lưu ý rằng tôi cũng đã thêm giá trị khóa chính (1 trong trường hợp này) vào tên bảng tạm thời của mình.


3
Giải pháp này là chính xác (ngược lại với một số giải pháp khác đã nhận được phiếu bầu) ở chỗ nó cho phép MySQL chọn giá trị khóa chính.
Jan Hettich

1
Mặc dù sẽ không hoạt động chính xác như là do tên bảng tạm thời không nhất quán ( tmptable_1so với tmptable)
Kieran Tully

9
Làm thế nào một khóa chính có thể là null?
Imran Shafqat

5
Nếu nó là null, nó sẽ tự động được gán số AI tiếp theo khi nó được chèn.
Grim ...

2
IMRAN - bạn cũng có thể yêu cầu. Tôi nghĩ có lẽ trường id của bảng tạm thời không tự động tạo PK (tôi khá chắc chắn rằng SQL Server không làm như vậy trong những trường hợp này) nhưng thực tế là vậy. Tôi cần phải thực hiện ALTER TABLE tmptable_1 MODIFY primarykeyINT NULL; sau dòng đầu tiên để giải pháp hoạt động
DJDave

61

Cập nhật 07/07/2014 - Câu trả lời dựa trên câu trả lời của tôi, bởi Grim ... , là một giải pháp tốt hơn vì nó cải thiện giải pháp của tôi dưới đây, vì vậy tôi khuyên bạn nên sử dụng nó.

Bạn có thể làm điều này mà không liệt kê tất cả các cột với cú pháp sau:

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;

Bạn có thể quyết định thay đổi khóa chính theo cách khác.


16
Về cơ bản, đây là giải pháp tương tự như OP đã cung cấp cho vấn đề của riêng họ, mặc dù với các bảng tạm thời thực tế và mô hình tạo sạch hơn một chút. Tôi nghĩ rằng OP đã yêu cầu một cách tiếp cận tốt hơn với những gì họ đã sử dụng, chứ không phải làm sạch cú pháp hiện có của họ. Đừng thực sự hiểu tất cả các upvote cho điều này.
Sepster

Cảm ơn bạn. Nó hoạt động tốt với chức năng động
Sonal Khunt

Có cần phải xóa tmptable sau khi quá trình này kết thúc?
SSH này vào

"Theo mặc định, tất cả các bảng tạm thời bị xóa bởi MySQL khi kết nối cơ sở dữ liệu của bạn bị chấm dứt. Bạn vẫn muốn xóa chúng ở giữa thì bạn làm như vậy bằng cách ban hành lệnh DROP TABLE." Thêm tại đây
LeonardChallis

Do bạn đã tạo tmptable, bạn không cần thêm WHERE primarykey = 2câu lệnh cho dòng cuối cùng. (Tức là, chỉ INSERT INTO table SELECT * FROM tmptable.)
Marcus

42

Tôi giả sử bạn muốn bản ghi mới có bản mới primarykey? Nếu primarykeyAUTO_INCREMENTthì chỉ cần làm điều này:

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

... Đâu col1, col2, col3, ...là tất cả các cột trong bảng ngoại trừ primarykey .

Nếu đó không phải là một AUTO_INCREMENTcột và bạn muốn có thể chọn giá trị mới cho primarykeynó tương tự:

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

... Đâu 567là giá trị mới cho primarykey.


41
Làm thế nào mà điều này được nâng cấp 7 lần khi nó bỏ qua câu hỏi? ... nhưng tôi không muốn liệt kê tất cả các cột sau "chọn", vì bảng này có quá nhiều cột ...
LeonardChallis

7
-1 vì đây chính xác là những gì OP muốn tránh. Đọc câu hỏi, hoặc ít nhất là đưa ra một câu trả lời như "đây là cách khả thi duy nhất".
devios1

5
Bởi vì đôi khi chính câu hỏi là sai. :) Sao chép hàng mà không thay đổi nội dung làm tăng sự dư thừa. Nên thay đổi cấu trúc cơ sở dữ liệu để giảm thiểu dư thừa, nếu có thể.
Torben

5
Chỉ vì nó không đúng theo thông lệ thông thường không làm cho nó sai. Có rất nhiều lần khi các thực hành tốt nhất tiêu chuẩn không được áp dụng. Ví dụ: cơ sở dữ liệu thể hiện các tài liệu và người dùng cần lưu giữ một bản sao của tài liệu trước khi thực hiện các thay đổi.
ima747

6
Bởi vì bạn có thể hạ cánh trên trang này không muốn chính xác như OP
jx12345

13

Bạn gần như đã có nó với truy vấn đầu tiên của mình, bạn chỉ cần chỉ định các cột, theo cách đó bạn có thể loại trừ khóa chính của mình trong phần chèn sẽ thực hiện tăng tự động mà bạn có thể có trên bảng để tự động tạo khóa chính mới cho nhập cảnh.

Ví dụ thay đổi điều này:

insert into table select * from table where primarykey=1

Về điều này:

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

Chỉ không bao gồm cột khóa chính trong danh sách cột cho INSERT hoặc cho các phần CHỌN của truy vấn.


1
Có cách nào để kéo hầu hết các cột thông qua câu lệnh select nhưng cập nhật một trong số chúng theo cách thủ công trong lệnh insert không? chẳng hạn như insert into table ("val1", col2, col3) select col2, col3 from table where primarykey = 1hoặc một cái gì đó tương tự?
anon58192932

1
Tìm thấy rồi! Sao chép các giá trị từ một hàng nhưng thêm một trong các giá trị của riêng bạn vào câu lệnh chèn: stackoverflow.com/questions/23971078/
Kẻ

1
Xin lỗi chỉ được thông báo về câu hỏi của bạn, rất vui vì bạn đã tìm thấy nó, đó thực sự là cách.
Braeden Đen

9

Bạn cũng có thể thử kết xuất bảng, tìm lệnh chèn và chỉnh sửa nó:

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

Cung --skip-extended-insertcấp cho bạn một lệnh chèn mỗi hàng. Sau đó, bạn có thể tìm thấy hàng trong trình soạn thảo văn bản yêu thích của mình, trích xuất lệnh và thay đổi khóa chính thành "mặc định".


2
+1 từ tôi vì đây là một cách tiếp cận "bên ngoài hộp" tốt có thể thực sự hữu ích ngoài thời gian chạy, trong một số trường hợp. Nhưng chủ yếu đó là câu trả lời đầu tiên thực sự giải quyết câu hỏi của OP và không chỉ chỉnh sửa một cách tổng hợp giải pháp đã được OP cung cấp.
Sepster

6

Thủ tục này giả định rằng:

  • bạn không có _d repeatate_temp_table
  • khóa chính của bạn là int
  • bạn có quyền truy cập để tạo bảng

Tất nhiên điều này không hoàn hảo, nhưng trong một số trường hợp nhất định (có thể là hầu hết) nó sẽ hoạt động.

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 Không xác nhận điều này worksnhưng cách tiếp cận là đúng đắn và có giá trị vì nó là duy nhất ở đây và thực sự giải quyết câu hỏi của OP.
Sepster

5

Điều này có thể đạt được với một số sáng tạo:

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;

Điều này sẽ dẫn đến hàng mới nhận được id tăng tự động thay vì id từ hàng đã chọn.


Đây phải là câu trả lời được chấp nhận!
Felipe Desiderati

5

Nếu trường khóa chính của bảng của bạn là trường tăng tự động, thì bạn có thể sử dụng truy vấn với các cột. Ví dụ: bảng của bạn có tên test_tblcó 3 trường là id, name, age. idlà trường khóa chính và tự động tăng, vì vậy bạn có thể sử dụng truy vấn sau để nhân đôi hàng:

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

Truy vấn này dẫn đến việc nhân đôi mỗi hàng.


Nếu trường khóa chính của bảng của bạn không phải là trường tăng tự động, thì bạn có thể sử dụng phương pháp sau:

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

Kết quả của truy vấn này là một hàng trùng lặp id=19được chèn là id=20.


Đó là câu trả lời tốt nhất hiện nay, trường hợp khá đơn giản: INSERT INTO tableName( fieldName1, fieldName2, fieldName3) SELECT fieldName1, fieldName2, fieldName3TỪ tableNameĐÂU 1 (sao chép tất cả trong số họ cùng một lúc)
jakubplus

Thứ hai - câu trả lời này ngắn gọn và trên tinh thần thực sự "Sao chép" một hàng.
dùng37309

4

hàng clone với các trường cập nhật và giá trị tăng tự động

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 Vui lòng kiểm tra đánh dấu bên trái của câu hỏi (đánh dấu là chấp nhận) để mọi người sẽ biết nó hoạt động cho bạn.
HosseyNJF

3

Một số điều sau đây đã được lượm lặt khỏi trang web này. Đây là những gì tôi đã làm để sao chép một bản ghi trong bảng với bất kỳ số lượng trường nào:

Điều này cũng giả sử bạn có trường AI ở đầu bảng

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
}

2

Tôi có thể bị trễ trong việc này, nhưng tôi có một giải pháp tương tự đã có hiệu quả với tôi.

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

Bằng cách này, tôi không cần tạo một bảng tạm thời, v.v. Vì hàng được sao chép trong cùng một bảng, Max(PK)+1chức năng có thể được sử dụng dễ dàng.

Tôi đã tìm kiếm giải pháp của câu hỏi này (đã quên cú pháp) và cuối cùng tôi đã thực hiện truy vấn của riêng mình. Hài hước làm thế nào mọi thứ làm việc ra một số lần.

Trân trọng


2

Nếu Khóa chính là Tự động tăng, chỉ cần chỉ định từng trường ngoại trừ khóa chính.

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


2

Tôi đã cập nhật giải pháp của @ LeonardChallis vì nó không hiệu quả với tôi như những người khác. Tôi đã loại bỏ các WHEREmệnh đề và SET primaryKey = 0trong bảng tạm thời để MySQL tự động tăng chính nó

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

Điều này là tất nhiên để sao chép tất cả các hàng trong bảng.


2

Tôi đã sử dụng kỹ thuật của Grim với một chút thay đổi: Nếu ai đó tìm kiếm truy vấn này là do không thể thực hiện một truy vấn đơn giản do sự cố khóa chính:

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

Với cài đặt MySql của tôi 5.6.26, khóa không thể rỗng và gây ra lỗi:

#1048 - Column 'primakey' cannot be null 

Vì vậy, sau khi tạo bảng tạm thời, tôi thay đổi khóa chính thành 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;

cách khác, trong các phiên bản mới của mariadb / mysql, khóa chính có thể được đặt thành 0, cho phép tăng tự động hoạt động khi được chèn.
Shelbypereira

2

Tôi sẽ sử dụng dưới đây,

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

1
Điều này không hoạt động nếu ITEM_NUMBER là khóa chính của bạn, có khả năng trong tình huống này.
Billy Pilgrim

2

Tôi đã sử dụng trong cơ sở dữ liệu Koha của mình để chèn các mục trùng lặp với tiền tố 'C' trong cột mã vạch :

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

1

Tôi chỉ phải làm điều này và đây là giải pháp thủ công của tôi:

  1. Trong phpmyadmin , kiểm tra hàng bạn muốn sao chép
  2. Ở dưới cùng bên dưới hoạt động kết quả truy vấn, nhấp vào 'Xuất'
  3. Trên trang tiếp theo , chọn 'Lưu dưới dạng tệp', sau đó nhấp vào 'Đi'
  4. Mở tệp đã xuất bằng trình soạn thảo văn bản, tìm giá trị của trường chính và thay đổi tệp thành một cái gì đó duy nhất.
  5. Quay lại phpmyadmin, nhấp vào tab 'Nhập' , xác định vị trí tệp để nhập tệp .sql trong trình duyệt , nhấp vào 'Đi' và hàng trùng lặp sẽ được chèn.

Nếu bạn không biết trường CHÍNH là gì, hãy nhìn lại trang phpmyadmin của bạn , nhấp vào tab 'Cấu trúc' và ở cuối trang dưới 'Chỉ mục', nó sẽ cho bạn biết 'Trường''Tên khóa' giá trị 'CHÍNH HÃNG' .

Một chặng đường dài, nhưng nếu bạn không muốn đối phó với đánh dấu và chỉ cần sao chép một hàng ở đó bạn đi.


Tốt đẹp, trả lời các op trong một loại ra khỏi hộp. Rõ ràng, nó không hoạt động cho tất cả các trường hợp, chẳng hạn như các đốm màu và dữ liệu không gian địa lý, nhưng khá dễ dàng để thực hiện và không hoạt động cho những thay đổi bóng lẻ đó.
Strixy

1

Giải pháp này cho thấy ở trên hoạt động hoàn hảo cũng cho các hàng được chọn. Ví dụ: tôi đang tạo các hàng trình diễn cho dự án Nice2work của mình và điều này hoạt động hoàn hảo.

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

Xin lỗi vì sự cần thiết nhưng đây là những gì tôi đã bật lên với google và vì tôi thấy điều này hữu ích nhưng có vấn đề, tôi muốn đóng góp một sửa đổi quan trọng cho bất kỳ ai khác khai thác nó.

Trước hết, tôi đang sử dụng SQL Server, không phải MySQL, nhưng tôi nghĩ nó sẽ hoạt động tương tự. Tôi đã sử dụng giải pháp của Leonard Challis vì nó đơn giản nhất và đáp ứng nhu cầu, tuy nhiên có vấn đề với điều này - nếu bạn chỉ cần lấy PK và tăng thêm 1 thì điều gì xảy ra nếu bạn thêm các bản ghi khác kể từ khi hàng được đề cập được thêm vào . Tôi quyết định tốt nhất là chỉ để hệ thống xử lý việc tự động tăng tốc của PK, vì vậy tôi đã làm như sau:

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

Tôi tin rằng điều này sẽ hoạt động tương tự trong MySQL, nhưng tôi không thể kiểm tra điều này, xin lỗi


1
hoàn toàn bakwaas trả lời
AsadYarKhan

0

Tôi biết đó là một câu hỏi cũ, nhưng đây là một giải pháp khác:

Điều này sao chép một hàng trong bảng chính, giả sử khóa chính là tự động tăng và tạo các bản sao của dữ liệu bảng được liên kết với id bảng chính mới.

Các tùy chọn khác để nhận tên cột:
-SHOW COLUMNS TỪ tablename; (Tên cột: Trường)
-DESCRIBE tablename (Tên cột: Trường)
-SELECT cột_name TỪ information_schema.columns WHERE table_name = 'tablename' (Tên cột: cột_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 chắc chắn đã đi đúng hướng, ít nhất là cho trường hợp tự động tăng tốc. Tuy nhiên, không làm BẢNG THAY ĐỔI. Chỉ cần đặt trường tăng tự động trong bảng tạm thời thành NULL. Điều này sẽ xuất hiện một lỗi, nhưng INSERT sau của tất cả các trường trong bảng tạm thời sẽ xảy ra và trường tự động NULL sẽ thu được một giá trị duy nhất.


0

Tạo một bảng

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

Chèn một hàng

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

Clone hàng chèn ở trên

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;

Kiểm tra

SELECT * FROM `sample_table`;

Lưu ý: Nếu bạn gặp lỗi (# 1048), hãy sử dụng '' thay vì NULL
Abdullah Aydın

Đây chỉ là tôi hay đây chính xác là những gì OP không muốn? (Tức là thêm thủ công từng cột vào truy vấn.)
Byson

Bạn nói đúng, tôi chỉ đọc câu "TÔI CHỈ muốn sao chép một hàng để chèn vào cùng một bảng" của OP, có lẽ, dù sao thì điều này vẫn hữu ích cho "Sao chép mục 'xxx' cho khóa ???" lỗi ^^
Abdullah Aydın

0

Đây là một câu trả lời tôi tìm thấy trực tuyến tại trang web này Mô tả cách thực hiện ở trên 1 Bạn có thể tìm thấy câu trả lời ở cuối trang. Về cơ bản, những gì bạn làm là sao chép hàng sẽ được sao chép vào một bảng tạm thời được giữ trong bộ nhớ. Sau đó, bạn thay đổi số Khóa chính bằng cách cập nhật. Sau đó, bạn chèn lại nó vào bảng đích. Sau đó bạn thả bàn.

Đây là mã cho nó:

TẠO rescueteamĐỘNG CƠ BẢNG TẠM THỜI = CHỌN BỘ NHỚ * TỪ fitnessreport4WHERE rID = 1; # 1 hàng bị ảnh hưởng. CẬP NHẬT rescueteamTHIẾT LẬP rID = Null WHERE rID = 1; # 1 hàng bị ảnh hưởng.INSERT INTO fitnessreport4CHỌN * TỪ rescueteam; # 1 hàng bị ảnh hưởng. BẢNG DROP rescueteam# MySQL trả về một tập kết quả trống (tức là
hàng không ).

Tôi đã tạo ra bảng cứu hộ tạm thời. Tôi đã sao chép hàng từ bảng gốc của tôi Fitnessreport4. Sau đó, tôi đặt khóa chính cho hàng trong bảng tạm thời thành null để tôi có thể sao chép nó trở lại bảng gốc mà không gặp lỗi Khóa trùng lặp. Tôi đã thử mã này tối hôm qua và nó đã hoạt động.


0

Đây là một giải pháp bổ sung cho câu trả lời của "Grim ..." Đã có một số ý kiến ​​về việc nó có khóa chính là null. Một số ý kiến ​​về nó không hoạt động. Và một số ý kiến ​​về giải pháp. Không có giải pháp nào làm việc cho chúng tôi. Chúng tôi có MariaDB với bảng InnoDB.

Chúng tôi không thể đặt khóa chính để cho phép null. Sử dụng 0 thay vì NULL dẫn đến lỗi giá trị trùng lặp cho khóa chính. SET SQL_SAFE_UPDATES = 0;Cũng không hoạt động.

Giải pháp từ "Grim ..." đã có hiệu quả NẾU chúng tôi đã thay đổi KHÓA CHÍNH của chúng tôi thành ĐỘC ĐÁO


-1

Chỉ muốn đăng đoạn mã PHP của tôi, bởi vì tôi nghĩ rằng cách tôi thu thập các cột trong mã sạch hơn một chút so với các ví dụ trước. Ngoài ra, điều này cho thấy cách bạn có thể dễ dàng thay đổi một trường, trong trường hợp này thêm một chuỗi. Nhưng bạn cũng có thể thay thế một trường khóa ngoại bằng bản ghi mới được thêm vào, trong trường hợp bạn muốn sao chép một số bản ghi con.

  // 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

Đối với một giải pháp rất đơn giản, bạn có thể sử dụng PHPMyAdmin để xuất hàng dưới dạng tệp CSV sau đó chỉ cần nhập tệp CSV đã sửa đổi. Chỉnh sửa cột ID / khóa chính để hiển thị không có giá trị trước khi bạn nhập nó.

SELECT * FROM table where primarykey=1

Sau đó ở dưới cùng của trang:

nhập mô tả hình ảnh ở đây

Trường hợp nói "Xuất" chỉ đơn giản là xuất, sau đó chỉnh sửa tệp csv để xóa giá trị khóa chính, vì vậy nó trống và sau đó chỉ cần nhập nó vào cơ sở dữ liệu, một khóa chính mới sẽ được chỉ định khi nhập.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.