same repeated one keep for duplicate delete but all mysql copy duplicates row

repeated - mysql select repeat rows



En MySQL, ¿puedo copiar una fila para insertarla en la misma tabla? (24)

Actualicé la solución de @ LeonardChallis ya que no funcionó para mí como ninguna de las otras. SET primaryKey = 0 cláusulas WHERE y SET primaryKey = 0 en la tabla temporal, por lo que MySQL se autoincreiza automáticamente en la clave primaria

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

Esto es, por supuesto, para duplicar todas las filas de la tabla.

insert into table select * from table where primarykey=1

Solo quiero copiar una fila para insertar en la misma tabla (es decir, quiero duplicar una fila existente en la tabla) pero quiero hacerlo sin tener que listar todas las columnas después de "seleccionar", porque esta tabla tiene demasiadas columnas.

Pero cuando hago esto, obtengo el error:

Entrada duplicada ''xxx'' para la tecla 1

Puedo manejar esto creando otra tabla con las mismas columnas que un contenedor temporal para el registro que quiero copiar:

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;

¿Hay alguna manera más simple de resolver esto?


Algunos de los siguientes fueron recogidos de este sitio. Esto es lo que hice para duplicar un registro en una tabla con cualquier cantidad de campos:

Esto también supone que tienes un campo AI al comienzo de la tabla

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 }


Aquí hay una respuesta que encontré en línea en este sitio. Describe cómo hacer lo anterior 1 Puede encontrar la respuesta en la parte inferior de la página. Básicamente, lo que haces es copiar la fila que se va a copiar a una tabla temporal retenida en la memoria. A continuación, cambie el número de clave principal con la actualización. A continuación, vuelve a insertarlo en la tabla de destino. A continuación, suelta la mesa.

Este es el código para esto:

CREAR MESA TEMPORAL rescueteam ENGINE = MEMORY SELECT * FROM fitnessreport4 WHERE rID = 1; # 1 fila afectada. ACTUALIZACIÓN rescueteam SET rID = NULL WHERE rID = 1; fila # 1 afectada. fitnessreport4 INTO fitnessreport4 SELECT * FROM rescueteam ; # 1 fila afectada. DROP TABLE rescueteam # MySQL devolvió un conjunto de resultados vacío (es decir, cero
filas).

Creé la tabla temporal rescueteam. Copié la fila de mi tabla original, FitnessReport4. Luego configuro la clave primaria de la fila en la tabla temporal para que sea nula, de modo que pueda copiarla nuevamente a la tabla original sin obtener un error de clave duplicada. Intenté este código ayer por la tarde y funcionó.


Casi lo tienes con la primera consulta, solo necesitas especificar las columnas, de esa manera puedes excluir tu clave principal en la inserción, que representará el autoincremento que probablemente tengas en la mesa para crear automáticamente una nueva clave principal para el entrada.

Por ejemplo, cambiar esto:

insert into table select * from table where primarykey=1

A esto:

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

Simplemente no incluya la columna de la clave principal en la lista de columnas para las partes INSERT o SELECT de la consulta.


Crea una mesa

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

Insertar una fila

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

Clone row insert anterior

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;

Prueba

SELECT * FROM `sample_table`;


Esta solución mostrada arriba funciona perfectamente también para filas seleccionadas. Por ejemplo, estoy creando filas de demostración para mi proyecto nice2work, y esto funciona perfecto.

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


Este procedimiento asume que:

  • no tienes _duplicate_temp_table
  • su clave principal es int
  • tienes acceso para crear una tabla

Por supuesto, esto no es perfecto, pero en algunos casos (probablemente la mayoría) funcionará.

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;


Esto se puede lograr con algo de creatividad:

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;

Esto dará como resultado que la nueva fila obtenga una identificación auto incrementada en lugar de la id de la fila seleccionada.


Para una solución muy simple, puede usar PHPMyAdmin para exportar la fila como un archivo CSV y luego simplemente importar el archivo CSV modificado. Editando la columna ID / primarykey para no mostrar ningún valor antes de importarlo.

SELECT * FROM table where primarykey=1

Luego en la parte inferior de la página:

Donde dice "Exportar" simplemente exporte, luego edite el archivo csv para eliminar el valor de la clave primaria, para que esté vacío, y luego simplemente importelo a la base de datos, se le asignará una nueva clave primaria en la importación.


Perdón por el necropost, pero esto es lo que encontré con google y dado que esto me pareció útil pero problemático, quería contribuir con una modificación importante para cualquier persona que lo descubra.

En primer lugar, estoy usando SQL Server, no MySQL, pero creo que debería funcionar de manera similar. Utilicé la solución de Leonard Challis porque era la más simple y cumplía con la necesidad, sin embargo hay un problema con esto: si simplemente toma el PK y lo incrementa en 1, entonces, ¿qué sucede si ha agregado otros registros desde que se agregó la fila en cuestión? . Decidí que era mejor dejar que el sistema manejara el autoincrementing del PK, así que hice lo siguiente:

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

Creo que esto funcionaría de manera similar en MySQL, pero no puedo probar esto, lo siento


Puede que llegue tarde, pero tengo una solución similar que me ha funcionado.

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

De esta forma no es necesario crear una tabla temporal, etc. Como la fila se copia en la misma tabla, la función Max(PK)+1 se puede usar fácilmente.

Vine buscando la solución a esta pregunta (había olvidado la sintaxis) y terminé haciendo mi propia consulta. Es curioso cómo las cosas funcionan algunas veces.

Saludos


Sé que es una vieja pregunta, pero aquí hay otra solución:

Esto duplica una fila en la tabla principal, suponiendo que la clave primaria se autoincrementa y crea copias de datos de tablas vinculadas con la nueva ID de la tabla principal.

Otras opciones para obtener nombres de columnas:
-SHOW COLUMNS FROM nombre de tablename ; (Nombre de columna: campo)
-DESCRIBE nombre de tablename (Nombre de columna: campo)
-SELECCIONAR column_name FROM information_schema.columns WHERE table_name = ''tablename'' (Nombre de columna: 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__); }


Si el campo de clave principal de su tabla es un campo de incremento automático, puede usar la consulta con columnas. Por ejemplo, su tabla llamada test_tbl tiene 3 campos como id, name, age . id es un campo de clave principal e incremento automático, por lo que puede usar la siguiente consulta para duplicar la fila:

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

Esta consulta da como resultado la duplicación de cada fila.

Si el campo de clave principal de su tabla no es un campo de incremento automático, puede usar el siguiente método:

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

El resultado de esta consulta es una fila duplicada de id=19 insertada como id=20 .


Si la clave principal es Aumento automático, simplemente especifique cada campo excepto la clave principal.

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


Solo quería publicar mi fragmento de código PHP, porque creo que la forma en que recopilo las columnas es un código más limpio que en los ejemplos anteriores. También muestra cómo podría modificar fácilmente un campo, en este caso, agregar una cadena. Pero también puede reemplazar un campo de clave externa con el registro recién agregado, en caso de que también desee copiar algunos registros secundarios.

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


Solo tenía que hacer esto y esta era mi solución manual:

  1. En phpmyadmin , compruebe la fila que desea copiar
  2. En la parte inferior de las operaciones de resultados de la consulta, haga clic en ''Exportar''
  3. En la página siguiente, marque ''Guardar como archivo'' y luego haga clic en ''Ir''.
  4. Abra el archivo exportado con un editor de texto, encuentre el valor del campo principal y cámbielo a algo único.
  5. De vuelta en phpmyadmin, haga clic en la pestaña ''Importar'' , ubique el archivo para importar el archivo .sql en la exploración , haga clic en ''Ir'' y se insertará la fila duplicada.

Si no sabes cuál es el campo PRIMARIO , mira hacia atrás en tu página phpmyadmin , haz clic en la pestaña ''Estructura'' y en la parte inferior de la página debajo de ''Índices'' te mostrará qué ''Campo'' tiene ''Nombre clave'' valor ''PRIMARIO'' .

Una especie de camino muy largo, pero si no quieres lidiar con el marcado y solo necesitas duplicar una sola fila, ahí tienes.


Supongo que quieres que el nuevo disco tenga una nueva primarykey . Si la primarykey es AUTO_INCREMENT , simplemente haz esto:

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

... donde col1, col2, col3, ... son todas las columnas de la tabla excepto la primarykey .

Si no es una columna AUTO_INCREMENT y desea poder elegir el nuevo valor para primarykey , es similar:

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

... donde 567 es el nuevo valor para la primarykey .


También podría intentar eliminar la tabla, encontrar el comando de inserción y editarlo:

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

El --skip-extended-insert le da un comando de inserción por fila. A continuación, puede encontrar la fila en su editor de texto favorito, extraer el comando y alterar la clave principal para "predeterminado".


Utilicé la técnica de Grim con un pequeño cambio: si alguien busca esta consulta es porque no puede hacer una consulta simple debido a un problema de clave principal:

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

Con mi instalación de MySql 5.6.26, la clave no puede contener nulos y produce un error:

#1048 - Column ''primakey'' cannot be null

Entonces, después de crear una tabla temporal, cambio la clave primaria a una tabla de anulación.

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;


Utilicé la técnica de Leonard Challis con algunos cambios:

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;

Como tabla temporal, nunca debe haber más de un registro, por lo que no debe preocuparse por la clave principal. Establecerlo como nulo permite a MySQL elegir el valor en sí mismo, por lo que no hay riesgo de crear un duplicado.

Si quiere estar seguro de que solo está obteniendo una fila para insertar, puede agregar LIMIT 1 al final de la línea INSERT INTO.

Tenga en cuenta que también agregué el valor de la clave primaria (1 en este caso) a mi nombre de tabla temporal.


Yo usaría a continuación,

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


clonar fila con campos de actualización y valor de incremento automático

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


max233 estaba ciertamente en el camino correcto, al menos para el caso de autoincrement. Sin embargo, no hagas ALTER TABLE. Simplemente configure el campo de incremento automático en la tabla temporal en NULL. Esto presentará un error, pero se producirá el siguiente INSERT de todos los campos en la tabla temporal y el campo automático NULL obtendrá un valor único.


Actualización 07/07/2014 - La respuesta basada en mi respuesta, por Grim ... , es una mejor solución, ya que mejora mi solución a continuación, por lo que sugiero usar eso.

Puede hacer esto sin enumerar todas las columnas con la siguiente sintaxis:

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;

Puede decidir cambiar la clave principal de otra manera.