2010-12-08 3 views
2

Ich muss eine Zeile basierend auf einer Bedingung (where-Klausel) aus einer Tabelle kopieren, einen doppelten Eintrag in derselben Tabelle erstellen und nur eine Spalte aktualisieren (eine foreign_key) . Aber weil "select * from Table_name" alle Felder einschließlich primary_key zurückgibt, ist es nicht möglich, die neue Zeile error: double key einzufügen.Zeile in derselben Tabelle kopieren und nur eine Spalte in MySQL aktualisieren

Ich kenne nicht alle Spalten der Tabelle, also kann ich primary_key nicht ignorieren, indem ich nur die erforderlichen Spaltennamen in der ausgewählten Abfrage gebe.

Gibt es eine Möglichkeit, primäre_key vom Abrufen selbst zu ignorieren .. oder kann ich die gesamte Zeile abrufen und den primary_key-Wert auf null setzen und dann die Zeile in Tabelle einfügen, so dass es den Primärschlüssel für neue Zeile automatisch inkrementiert hinzugefügt werden.

Danke.

Antwort

5

Es ist möglich, das zu tun, was Sie wollen, indem Sie die Informationsschematabellen abfragen und dynamisches SQL verwenden, um eine entsprechende Anweisung zu erstellen. Sie sollten jedoch große Sorgfalt mit diesem Ansatz, da die Daten in Tabellen zu modifizieren, für die Sie nicht die Spaltennamen wissen könnten alle Arten von Problemen führen:

DROP TABLE mytable; 

CREATE TABLE `mytable` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `col1` varchar(255) DEFAULT NULL, 
    `col2` varchar(255) DEFAULT NULL, 
    `col3` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 

INSERT INTO mytable (col1, col2, col3) VALUES ('A', 'B', 'C'); 

SELECT * FROM mytable; 

+----+------+------+------+ 
| id | col1 | col2 | col3 | 
+----+------+------+------+ 
| 1 | A | B | C | 
+----+------+------+------+ 

SET @columns := (
    SELECT 
    GROUP_CONCAT(column_name) 
    FROM information_schema.columns 
    WHERE table_schema = 'test' 
    AND table_name = 'mytable' 
    AND column_key <> 'PRI' 
); 

SET @sql := (
    SELECT CONCAT(
    'INSERT INTO mytable (', @columns, ') ', 
    'SELECT ', @columns, ' FROM mytable ', 
    'WHERE id = 1;' 
) 
); 

SELECT @sql; 

+---------------------------------------------------------------------------------------+ 
| @sql                     | 
+---------------------------------------------------------------------------------------+ 
| INSERT INTO mytable (col1,col2,col3) SELECT col1,col2,col3 FROM mytable WHERE id = 1; | 
+---------------------------------------------------------------------------------------+ 

PREPARE stmt FROM @sql; 

EXECUTE stmt; 

SELECT * FROM mytable; 

+----+------+------+------+ 
| id | col1 | col2 | col3 | 
+----+------+------+------+ 
| 1 | A | B | C | 
| 2 | A | B | C | 
+----+------+------+------+ 
+0

Dank, Mike .. Warum ich weiß nicht, die Spalte Namen ist weil, ich schreibe eine generische gespeicherte Prozedur für die Durchführung der gleichen Art von Operation auf mehrere verschiedene Arten von Tabelle, die ich habe. Also werde ich einfach den Tabellennamen und die zu verwendende "where-Klausel" kennen, die für alle Tabellen gleich sein wird. – shailesh

+0

@shailesh: Okay, der dynamische SQL-Ansatz mag für Sie funktionieren, aber meine Warnung steht immer noch. Viel Glück :-) – Mike

+0

Hey Mike, Es scheint nicht, es gibt eine bessere Alternative .. Ich benutze das .. Danke nochmal .. – shailesh

0

Wenn Sie Kenntnisse über die Sequenzen des Arrays haben, die Sie erhalten haben, können Sie nach dem Setzen einer Art von Bedingung das Feld mit dem Primärschlüssel ignorieren.

Überprüfen Sie dies, wenn es funktioniert

Vielen Dank.

0

Wie kann es sein, dass Sie wissen, was der Schlüssel ist, aber nicht wissen, was die anderen Spalten sind? Wenn das wirklich der Fall ist, dann denke ich, dass Sie etwas dynamisches SQL schreiben müssen - oder noch besser, geben Sie die Aufgabe jemandem, der die Tabellenstruktur kennt, tut.

Verwandte Themen