Czy w MySQL mogę skopiować jeden wiersz i wstawić go do tej samej tabeli?

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

Chcę tylko skopiować jeden wiersz, aby wstawić go do tej samej tabeli (tj. Chcę zduplikować istniejący wiersz w tabeli), ale chcę to zrobić bez konieczności wyszczególniania wszystkich kolumn po opcji „wybierz”, ponieważ ta tabela ma za dużo kolumn.

Ale kiedy to robię, pojawia się błąd:

Powielony wpis „xxx” dla klucza 1

Mogę sobie z tym poradzić, tworząc inną tabelę z tymi samymi kolumnami, co tymczasowy kontener dla rekordu, który chcę skopiować:

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;

Czy istnieje prostszy sposób rozwiązania tego problemu?

lina
źródło
Mam tylko komentarz na temat zakodowanych wartości klucza. Zrobiłbym coś takiego w max(oldtable.id) + oldtable_temp.keyten sposób, aby upewnić się, że identyfikatory rosną i są unikalne.
facet mograbi
@OrganicAdvocate to ma więcej odpowiedzi i więcej wyświetleń niż to pytanie
Drew

Odpowiedzi:

189

Użyłem techniki Leonarda Challisa z kilkoma zmianami:

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;

Jako tabela tymczasowa nigdy nie powinno być więcej niż jeden rekord, więc nie musisz martwić się o klucz podstawowy. Ustawienie wartości null umożliwia MySQL wybranie samej wartości, więc nie ma ryzyka utworzenia duplikatu.

Jeśli chcesz mieć całkowitą pewność, że dostajesz tylko jeden wiersz do wstawienia, możesz dodać LIMIT 1 na końcu wiersza INSERT INTO.

Zauważ, że dołączyłem również wartość klucza podstawowego (w tym przypadku 1) do nazwy mojej tabeli tymczasowej.

Ponury...
źródło
3
To rozwiązanie jest poprawne (w przeciwieństwie do innych, które zdobyły głosy), ponieważ umożliwia MySQL wybranie wartości klucza podstawowego.
Jan Hettich
1
Chociaż nie będzie działać dokładnie tak, jak jest z powodu niespójnych tymczasowych nazw tabel (w tmptable_1porównaniu z tmptable)
Kieran Tully
9
Jak klucz podstawowy może być pusty?
Imran Shafqat
5
Jeśli jest pusty, po wstawieniu zostanie automatycznie przypisany następny numer AI.
Ponury ...
3
IMRAN - możesz zapytać. Pomyślałem, że być może pole id tabeli tymczasowej nie zostało automatycznie utworzone jako PK (jestem prawie pewien, że SQL Server nie robi tego w tych okolicznościach), ale tak jest. Musiałem zrobić ALTER TABLE tmptable_1 MODIFY primarykeyINT NULL; po pierwszej linii, aby rozwiązanie działało
DJDave
61

Aktualizacja 07/07/2014 - Odpowiedź oparta na mojej odpowiedzi, przez Grim ... , jest lepszym rozwiązaniem, ponieważ ulepsza moje rozwiązanie poniżej, więc proponuję jej użyć.

Możesz to zrobić bez wyświetlania wszystkich kolumn o następującej składni:

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;

Możesz zdecydować się na zmianę klucza podstawowego w inny sposób.

LeonardChallis
źródło
16
Jest to w zasadzie to samo rozwiązanie, które OP już przewidział dla własnego problemu, aczkolwiek z rzeczywistymi tabelami temp i nieco czystszym wzorcem tworzenia. Myślę, że OP poprosił o lepsze podejście do tego, czego już używali, a nie o uporządkowanie ich istniejącej składni. Naprawdę nie rozumiem wszystkich pozytywnych głosów za to.
Sepster
Dziękuję Ci.
Działa
Czy po zakończeniu tego procesu konieczne jest usunięcie tmptable?
SSH
„Domyślnie wszystkie tabele tymczasowe są usuwane przez MySQL po zerwaniu połączenia z bazą danych. Nadal chcesz je usunąć w międzyczasie, możesz to zrobić, wydając polecenie DROP TABLE”. Więcej tutaj
LeonardChallis
Biorąc pod uwagę, że utworzyłeś tmptable, nie musisz dodawać WHERE primarykey = 2instrukcji również do ostatniego wiersza. (To znaczy tylko INSERT INTO table SELECT * FROM tmptable.)
Marcus
42

Zakładam, że chcesz, aby nowa płyta miała nowy primarykey? Jeśli primarykeytak, AUTO_INCREMENTpo prostu zrób to:

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

... gdzie col1, col2, col3, ...są wszystkie kolumny w tabeli z wyjątkiem primarykey .

Jeśli to nie jest AUTO_INCREMENTkolumna i chcesz mieć możliwość wybrania nowej wartości, primarykeyponieważ jest podobna:

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

... gdzie 567jest nowa wartość dla primarykey.

Jordan Running
źródło
41
Jak to się dzieje, że jest to głosowane 7 razy, kiedy ignoruje pytanie? ... ale nie chcę wyświetlać wszystkich kolumn po „wybierz”, ponieważ ta tabela ma zbyt wiele kolumn ...
LeonardChallis
7
-1, ponieważ właśnie tego chce uniknąć PO. Przeczytaj pytanie lub przynajmniej odpowiedz w stylu „to jedyny możliwy sposób”.
devios1
5
Ponieważ czasami samo pytanie jest błędne. :) Duplikowanie wierszy bez zmiany zawartości zwiększa nadmiarowość. Jeśli to możliwe, zaleca się zmianę struktury bazy danych w celu zminimalizowania nadmiarowości.
Torben,
5
To, że nie jest to dobre w normalnych praktykach, nie oznacza, że ​​jest źle. W wielu przypadkach standardowe najlepsze praktyki nie mają zastosowania. Przykład: baza danych reprezentuje dokumenty, a użytkownik musi zachować kopię dokumentu przed wprowadzeniem zmian.
ima747
6
Ponieważ możesz wylądować na tej stronie, nie chcąc dokładnie tego samego, co OP
jx12345
13

Prawie miałeś to przy pierwszym zapytaniu, wystarczy określić kolumny, w ten sposób możesz wykluczyć klucz podstawowy we wkładce, co spowoduje automatyczne zwiększenie, które prawdopodobnie masz w tabeli, aby automatycznie utworzyć nowy klucz podstawowy dla wejście.

Na przykład zmień to:

insert into table select * from table where primarykey=1

Do tego:

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

Po prostu nie uwzględniaj kolumny klucza podstawowego ani na liście kolumn dla INSERT, ani dla części SELECT zapytania.

Braeden Black
źródło
1
czy istnieje sposób na przeciągnięcie większości kolumn za pomocą instrukcji select, ale zaktualizowanie jednej z nich ręcznie za pomocą polecenia wstawiania? takie jak insert into table ("val1", col2, col3) select col2, col3 from table where primarykey = 1lub coś podobnego?
anon58192932
1
Znalazłem to! Skopiuj wartości z jednego wiersza, ale dodaj jedną z własnych wartości do instrukcji insert: stackoverflow.com/questions/23971078/ ...
anon58192932
1
Przepraszamy, właśnie otrzymałem powiadomienie o twoich pytaniach, cieszę się, że je znalazłeś.
Braeden Black
9

Możesz także spróbować zrzucić tabelę, znaleźć polecenie wstawiania i edytować je:

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

--skip-extended-insertDaje jedno polecenie insert każdym wierszu. Możesz wtedy znaleźć wiersz w swoim ulubionym edytorze tekstu, wyodrębnić polecenie i zmienić klucz podstawowy na „domyślny”.

z powodzeniem
źródło
2
+1 ode mnie, ponieważ jest to dobre podejście „nieszablonowe”, które w niektórych okolicznościach może być przydatne poza czasem wykonywania. Ale przede wszystkim jest to pierwsza odpowiedź, która faktycznie odpowiada na pytanie OP i nie tylko modyfikuje składniowo rozwiązanie już dostarczone przez OP.
Sepster
6

Ta procedura zakłada, że:

  • nie masz _duplicate_temp_table
  • Twój klucz podstawowy to int
  • masz dostęp do tworzenia tabeli

Oczywiście nie jest to idealne rozwiązanie, ale w niektórych (prawdopodobnie większości) przypadków zadziała.

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;
Piotr Kaczmarek
źródło
1
+1 Nie potwierdziły tego, worksale podejście jest rozsądne i ma wartość, ponieważ jest tutaj wyjątkowe i faktycznie odpowiada na pytanie PO.
Sepster
5

Można to osiągnąć przy odrobinie kreatywności:

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;

Spowoduje to, że nowy wiersz otrzyma automatycznie zwiększany identyfikator zamiast identyfikatora z wybranego wiersza.

curmil
źródło
To powinna być akceptowana odpowiedź!
Felipe Desiderati
5

Jeśli pole klucza podstawowego tabeli jest polem automatycznie zwiększającym, możesz użyć zapytania z kolumnami. Na przykład tabela o nazwie test_tblma 3 pola jako id, name, age. idjest polem klucza podstawowego i automatycznym zwiększaniem, więc możesz użyć następującego zapytania, aby zduplikować wiersz:

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

To zapytanie powoduje zduplikowanie każdego wiersza.


Jeśli pole klucza podstawowego tabeli nie jest polem automatycznego zwiększania wartości, możesz użyć następującej metody:

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

Wynikiem tego zapytania jest zduplikowany wiersz id=19wstawiony jako id=20.

user2595171
źródło
Że jest najlepszą odpowiedzią jest, sprawa jest dość prosta: INSERT INTO tableName( fieldName1, fieldName2, fieldName3) SELECT fieldName1, fieldName2, fieldName3OD tableNameKTÓRYCH 1 (skopiować je wszystkie na raz)
jakubplus
Po drugie - ta odpowiedź jest zwięzła i w duchu „kopiowania” wiersza.
user37309
4

klonuj wiersz z polami aktualizacji i wartością automatycznego zwiększania

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`;
Shrinivas Mahindrakar
źródło
@Torben Zaznacz haczyk po lewej stronie pytania (zaznacz je jako zaakceptowane), aby wszyscy wiedzieli, że zadziałało.
HosseyNJF
3

Z tej witryny zebrano niektóre z poniższych informacji. Oto, co zrobiłem, aby zduplikować rekord w tabeli z dowolną liczbą pól:

Zakłada się również, że na początku tabeli znajduje się pole 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
}
richardwhitney
źródło
3

Użyłem techniki Grima z niewielką zmianą: Jeśli ktoś szuka tego zapytania, to dlatego, że nie może wykonać prostego zapytania z powodu problemu z kluczem podstawowym:

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

W mojej instalacji MySql 5.6.26 klucz nie dopuszcza wartości null i powoduje błąd:

#1048 - Column 'primakey' cannot be null 

Więc po utworzeniu tabeli tymczasowej zmieniam klucz podstawowy na dopuszczający wartość 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;
Luca Camillo
źródło
alternatywnie w nowych wersjach mariadb / mysql podstawowyKey może być ustawiony na 0, co pozwala na automatyczne zwiększanie wartości po wstawieniu.
shelbypereira
2

Mogę się z tym spóźnić, ale mam podobne rozwiązanie, które mi się sprawdziło.

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

W ten sposób nie muszę tworzyć tymczasowej tabeli itp. Ponieważ wiersz jest kopiowany w tej samej tabeli, Max(PK)+1funkcja może być łatwo używana.

Przyszedłem szukać rozwiązania tego pytania (zapomniałem składni) i ostatecznie stworzyłem własne zapytanie. Zabawne, jak czasem sprawy się układają.

pozdrowienia

echo_salik
źródło
2

Jeśli klucz podstawowy to Autoinkrementacja, po prostu określ każde pole z wyjątkiem klucza podstawowego.

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

Fedy Venom
źródło
2

Zaktualizowałem rozwiązanie @ LeonardChallis, ponieważ nie działało dla mnie jak żadne inne. Usunąłem WHEREklauzule i SET primaryKey = 0tabelę tymczasową, więc MySQL automatycznie zwiększa swój klucz primaryKey

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

Ma to oczywiście na celu zduplikowanie wszystkich wierszy w tabeli.

D4V1D
źródło
2

Użyłbym poniżej,

insert into ORDER_ITEM select * from ORDER_ITEM where ITEM_NUMBER =123;
Ishan Liyanage
źródło
1
To nie działa, jeśli ITEM_NUMBER jest Twoim kluczem podstawowym, co jest prawdopodobne w tej sytuacji.
Billy Pilgrim
2

W mojej bazie danych Koha wstawiłem zduplikowane elementy z prefiksem „C” w kolumnie z kodem kreskowym :

INSERT INTO items (`biblionumber`, `biblioitemnumber`, `barcode`, `dateaccessioned` ) SELECT `biblionumber`, `biblioitemnumber`,  CONCAT('C',`barcode`), `dateaccessioned` FROM `items` WHERE barcode='14832';
Rajiv Mahmud
źródło
1

Po prostu musiałem to zrobić i to było moje ręczne rozwiązanie:

  1. W phpmyadmin zaznacz wiersz, który chcesz skopiować
  2. Na dole pod operacjami wynikowymi zapytania kliknij „Eksportuj”
  3. Na następnej stronie zaznacz „Zapisz jako plik”, a następnie kliknij „Przejdź”
  4. Otwórz wyeksportowany plik za pomocą edytora tekstu, znajdź wartość pola podstawowego i zmień ją na coś unikalnego.
  5. Po powrocie do phpmyadmin kliknij kartę „Importuj” , znajdź plik do zaimportowania pliku .sql pod przeglądarką , kliknij „Idź” i należy wstawić zduplikowany wiersz.

Jeśli nie wiesz, co to jest pole PODSTAWOWE , spójrz wstecz na swoją stronę phpmyadmin , kliknij kartę „Struktura” , a na dole strony pod pozycją „Indeksy” pokaże się, które pole ma „Nazwę klucza” wartość „PODSTAWOWA” .

Trochę długa droga dookoła, ale jeśli nie chcesz zajmować się znacznikami i po prostu musisz zduplikować pojedynczy wiersz.

user27068
źródło
Świetnie, odpowiada na operację w nieszablonowy sposób. Oczywiście nie działa we wszystkich przypadkach, takich jak plamy i dane geoprzestrzenne, ale dość łatwe do usunięcia i działa w przypadku tych dziwnych zmian kuli.
Strixy
1

Pokazane powyżej rozwiązanie sprawdza się doskonale również dla wybranych rzędów. Na przykład tworzę wiersze demonstracyjne dla mojego projektu nice2work i działa to doskonale.

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;";
Ronald Stevens
źródło
0

Przepraszam za nekropostę, ale to właśnie znalazłem w Google i ponieważ uznałem to za pomocne, ale problematyczne, chciałem wnieść ważną modyfikację dla każdego, kto to wykopie.

Po pierwsze, używam SQL Server, a nie MySQL, ale myślę, że powinno działać podobnie. Użyłem rozwiązania Leonarda Challisa, ponieważ było najprostsze i spełniło wymagania, jednak jest z tym problem - jeśli po prostu weźmiesz PK i zwiększysz ją o 1, to co się stanie, jeśli dodałeś inne rekordy od czasu dodania danego wiersza . Zdecydowałem, że najlepiej będzie po prostu pozwolić systemowi zająć się autoinkrementacją PK, więc zrobiłem co następuje:

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

Uważam, że działałoby to podobnie w MySQL, ale nie mogę tego przetestować, przepraszam

maxx233
źródło
1
całkowicie bakwaas odpowiedź
AsadYarKhan
0

Wiem, że to stare pytanie, ale oto inne rozwiązanie:

Powoduje to duplikowanie wiersza w tabeli głównej, przy założeniu, że klucz podstawowy jest automatycznie zwiększany i tworzy kopie danych tabel połączonych z nowym identyfikatorem tabeli głównej.

Inne opcje pobierania nazw kolumn:
-POKAŻ KOLUMNY Z tablename; (Nazwa kolumny: Pole)
-DESCRIBE tablename (Nazwa kolumny: Pole)
-WYBIERZ nazwa_kolumny Z schematu_informacyjnego.columns WHERE nazwa_tabeli = 'nazwa_tabeli' (Nazwa kolumny: nazwa_kolumny)

//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__);
}
Paweł
źródło
0

max233 z pewnością był na dobrej drodze, przynajmniej w przypadku autoincrement. Jednak nie wykonuj ALTER TABLE. Po prostu ustaw pole autoinkrementacji w tabeli tymczasowej na NULL. Spowoduje to wystąpienie błędu, ale nastąpi następujące WSTAWIENIE wszystkich pól w tabeli tymczasowej, a pole automatyczne NULL otrzyma unikalną wartość.

user3067083
źródło
0

Utwórz tabelę

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

Wstaw wiersz

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

Klonuj wstawkę wiersza powyżej

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 Aydın
źródło
Uwaga: jeśli otrzymujesz błąd (# 1048), użyj „” zamiast NULL
Abdullah Aydın
Czy to tylko ja, czy właśnie tego OP nie chciał? (To znaczy ręcznie dodając każdą kolumnę do zapytania.)
Byson
Masz rację, właśnie przeczytałem zdanie OP „Chcę tylko skopiować jeden wiersz, aby wstawić go do tej samej tabeli”, być może i tak jest to nadal przydatne w przypadku „Powielenie wpisu 'xxx' dla klucza ???” błąd ^^
Abdullah Aydın
0

Oto odpowiedź, którą znalazłem w tej witrynie. Opisuje, jak wykonać powyższe 1. Odpowiedź znajduje się na dole strony. Zasadniczo to, co robisz, to kopiowanie wiersza do skopiowania do tymczasowej tabeli przechowywanej w pamięci. Następnie możesz zmienić numer klucza podstawowego za pomocą aktualizacji. Następnie wstaw go ponownie do tabeli docelowej. Następnie upuszczasz stół.

Oto kod:

UTWÓRZ TABELĘ TYMCZASOWĄ rescueteamSILNIK = WYBÓR PAMIĘCI * Z fitnessreport4GDZIE RID = 1; dotyczy to wiersza nr 1. UPDATE rescueteamSET rID = Null WHERE rID = 1; dotyczy wiersza nr 1 INSERT INTO fitnessreport4SELECT * FROM rescueteam; dotyczy wiersza nr 1. DROP TABLE rescueteam# MySQL zwrócił pusty zestaw wyników (tj. Zero
wierszy).

Stworzyłem tymczasowy stół ratunkowy. Skopiowałem wiersz z mojej oryginalnej tabeli fitnessreport4. Następnie ustawiam klucz podstawowy dla wiersza w tabeli tymczasowej na null, aby móc skopiować go z powrotem do oryginalnej tabeli bez otrzymywania błędu Duplicate Key. Wypróbowałem ten kod wczoraj wieczorem i zadziałał.

user2363682
źródło
0

To jest dodatkowe rozwiązanie dla odpowiedzi „Grim…” Pojawiły się komentarze na temat tego, że klucz podstawowy jest pusty. Kilka uwag o tym nie działa. I kilka uwag na temat rozwiązań. Żadne z rozwiązań nie zadziałało dla nas. Mamy MariaDB ze stołem InnoDB.

Nie mogliśmy ustawić klucza podstawowego, aby zezwolić na null. Użycie 0 zamiast NULL doprowadziło do zduplikowania błędu wartości dla klucza podstawowego. SET SQL_SAFE_UPDATES = 0;Nie działał też.

Rozwiązanie z „Ponurego ...” zadziałało, JEŚLI zamiast tego zmieniliśmy nasz KLUCZ PODSTAWOWY na UNIQUE

Szymon
źródło
-1

Chciałem tylko opublikować swój fragment kodu PHP, ponieważ myślę, że sposób, w jaki zbieram kolumny, jest nieco bardziej przejrzysty w kodzie niż w poprzednich przykładach. Pokazuje również, jak łatwo można zmienić pole, w tym przypadku dodając ciąg. Ale możesz również zastąpić pole klucza obcego nowo dodanym rekordem, na wypadek gdybyś chciał również skopiować niektóre rekordy podrzędne.

  // 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
źródło
-2

Aby uzyskać bardzo proste rozwiązanie, możesz użyć PHPMyAdmin do wyeksportowania wiersza jako pliku CSV, a następnie po prostu zaimportuj zmieniony plik CSV. Edycja kolumny ID / primarykey tak, aby nie pokazywała żadnej wartości przed jej zaimportowaniem.

SELECT * FROM table where primarykey=1

Następnie na dole strony:

wprowadź opis obrazu tutaj

Gdzie jest napisane „Eksportuj”, po prostu wyeksportuj, a następnie edytuj plik csv, aby usunąć wartość klucza podstawowego, tak aby był pusty, a następnie po prostu zaimportuj go do bazy danych, nowy klucz podstawowy zostanie przypisany podczas importu.

Dotacja
źródło