He estado buscando por un tiempo pero no puedo encontrar una solución fácil para mi problema. Me gustaría duplicar un registro en una tabla, pero, por supuesto, es necesario actualizar la clave principal única.
Tengo esta consulta:
INSERT INTO invoices
SELECT * FROM invoices AS iv WHERE iv.ID=XXXXX
ON DUPLICATE KEY UPDATE ID = (SELECT MAX(ID)+1 FROM invoices)
el problema es que esto solo cambia el ID
de la fila en lugar de copiar la fila. Sabe alguien cómo arreglar esto ?
// editar: me gustaría hacer esto sin escribir todos los nombres de los campos porque los nombres de los campos pueden cambiar con el tiempo.
CREATE TEMPORARY TABLE tmp SELECT bla FROM invoices WHERE bla; UPDATE tmp SET id=NULL; INSERT INTO invoices SELECT * FROM tmp;
NOT NULL
configuréid
. Solo me preguntaba si tenía sugerencias para este caso. ¿Eso se considera una mala práctica?La respuesta de Alex necesita algo de cuidado (por ejemplo, bloqueo o una transacción) en entornos multicliente.
Suponiendo que el
AUTO ID
campo es el primero de la tabla (un caso habitual), podemos hacer uso de transacciones implícitas.De los documentos de MySQL:
fuente
NULL
o0
ambos son aceptables. ¿Puedes publicar capturas de pantalla del problema reproduciéndolas y compartiéndolas aquí?invoices
contiene unID
campo AUTO_INCREMENT . La tabla de origentmp
no lo hace. Para obtener la correlación necesaria 1: 1 durante la inserción, especifique a0
como primer campo de la selección, que es el campo AUTO_INCREMENT de la tabla de destino. Lostmp.*
selecciona todos los campos de la tabla de origentmp
. ¡Perfecto! Ahora tiene su correlación 1: 1. Impresionante respuesta @Tim.NULL
y0
no somos lo mismo. El contexto actual está enAUTO_INCREMENT
función. No puede insertar0
unNULL
valor o un valor en dichos campos. Pero cuando los usa como entradas en dicho campo, el siguiente valor de secuencia se asignará a ese campo automáticamente . Y de ahí mi comentario. Prueba en SQL Fiddle: sqlfiddle.com/#!9/d619f/1Usted SABE con certeza que la DUPLICATE KEY se activará, por lo que puede seleccionar el MAX (ID) +1 de antemano:
INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX
fuente
Su enfoque es bueno, pero el problema es que usa "*" en lugar de dar de alta los nombres de los campos. Si coloca todos los nombres de las columnas excepto la clave principal, su script funcionará como el encanto en uno o varios registros.
INSERT INTO invoices (iv.field_name, iv.field_name,iv.field_name ) SELECT iv.field_name, iv.field_name,iv.field_name FROM invoices AS iv WHERE iv.ID=XXXXX
fuente
Una respuesta tardía que sé, pero sigue siendo una pregunta común, me gustaría agregar otra respuesta que funcionó para mí, con solo usar una
insert into
declaración de una sola línea , y creo que es sencillo, sin crear ninguna tabla nueva (ya que podría ser un problema con losCREATE TEMPORARY TABLE
permisos):INSERT INTO invoices (col_1, col_2, col_3, ... etc) SELECT t.col_1, t.col_2, t.col_3, ... t.updated_date, FROM invoices t;
La solución funciona para la
AUTO_INCREMENT
columna de identificación; de lo contrario, también puede agregar unaID
columna a la declaración:INSERT INTO invoices (ID, col_1, col_2, col_3, ... etc) SELECT MAX(ID)+1, t.col_1, t.col_2, t.col_3, ... etc , FROM invoices t;
Es realmente fácil y sencillo, puede actualizar cualquier otra cosa en una sola línea sin ninguna segunda declaración de actualización para más adelante (por ejemplo, actualizar una columna de título con texto adicional o reemplazar una cadena con otra), también puede ser específico con qué exactamente desea duplicar, si es todo, entonces, si lo es, puede hacerlo.
fuente
INSERT into wp_options SELECT NULL, 'theme_mods_twopress', option_value, autoload FROM wp_options where option_name = 'theme_mods_onepress';
copiar mientras aumentaba la entrada (AUTO_INCREMENT
NULL
truco de arriba) y también eloption_name
campo.Solo quería extender la excelente respuesta de Alex para que sea apropiada si desea duplicar un conjunto completo de registros:
SET @x=7; CREATE TEMPORARY TABLE tmp SELECT * FROM invoices; UPDATE tmp SET id=id+@x; INSERT INTO invoices SELECT * FROM tmp;
¡Solo tenía que hacer esto y encontré la respuesta de Alex como un punto de partida perfecto !. Por supuesto, debe establecer @x en el número de fila más alto de la tabla (estoy seguro de que podría obtenerlo con una consulta). Esto solo es útil en esta situación muy específica, así que tenga cuidado al usarlo cuando no desee duplicar todas las filas. Ajuste las matemáticas según sea necesario.
fuente
Tengo un problema similar y esto es lo que estoy haciendo:
insert into Preguntas (`EncuestaID`, `Tipo` , `Seccion` , `RespuestaID` , `Texto` ) select '23', `Tipo`, `Seccion`, `RespuestaID`, `Texto` from Preguntas where `EncuestaID`= 18
Sido Preguntas:
CREATE TABLE IF NOT EXISTS `Preguntas` ( `ID` int(11) unsigned NOT NULL AUTO_INCREMENT, `EncuestaID` int(11) DEFAULT NULL, `Tipo` char(5) COLLATE utf8_unicode_ci DEFAULT NULL, `Seccion` int(11) DEFAULT NULL, `RespuestaID` bigint(11) DEFAULT NULL, `Texto` text COLLATE utf8_unicode_ci , PRIMARY KEY (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=522 ;
Entonces,
ID
se incrementa automáticamente y también estoy usando un valor fijo ('23') paraEncuestaID
.fuente
Yo también necesitaba esto; mi solución fue usar SQLYOG (versión gratuita) para exportar el registro deseado como SQL (crea una inserción).
Luego edité esto a mano para eliminar la identificación, ya que debe generarse automáticamente y luego copié la inserción en SQLYog para ejecutarla. Esto fue indoloro. Supongo que muchas otras GUI de MySQL también pueden hacer esto.
Esto me proporciona un registro que puedo usar con fines de prueba en un sistema en vivo.
Ahora también tengo este inserto para reutilizarlo, ya que la tabla se reescribe a diario.
fuente
Ligera variación, la principal diferencia es establecer el campo de clave principal ("varname") en nulo, lo que produce una advertencia pero funciona. Al establecer la clave principal en nula, el incremento automático funciona al insertar el registro en la última declaración.
Este código también limpia los intentos anteriores y se puede ejecutar más de una vez sin problemas:
DELETE FROM `tbl` WHERE varname="primary key value for new record"; DROP TABLE tmp; CREATE TEMPORARY TABLE tmp SELECT * FROM `tbl` WHERE varname="primary key value for old record"; UPDATE tmp SET varname=NULL; INSERT INTO `tbl` SELECT * FROM tmp;
fuente