INSERT INTO ... SELECT para todas las columnas de MySQL

119

Estoy tratando de mover datos antiguos de:

this_table >> this_table_archive

copiando todas las columnas. He intentado esto, pero no funciona:

INSERT INTO this_table_archive (*) VALUES (SELECT * FROM this_table WHERE entry_date < '2011-01-01 00:00:00');

Nota: las tablas son idénticas y se han idconfigurado como clave primaria.

Kyle
fuente
1
Defina "no funciona". Estoy teniendo lo que puede ser un problema similar, ¡pero no puedo decirlo porque no dijiste cuál era tu problema!
Lightness Races in Orbit
No está roto, simplemente no funciona.
Webmaster G

Respuestas:

218

La sintaxis correcta se describe en el manual . Prueba esto:

INSERT INTO this_table_archive (col1, col2, ..., coln)
SELECT col1, col2, ..., coln
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00';

Si las columnas de identificación son una columna de incremento automático y ya tiene algunos datos en ambas tablas, en algunos casos, es posible que desee omitir la identificación de la lista de columnas y generar nuevas identificaciones en su lugar para evitar insertar una identificación que ya existe en el original. mesa. Si su tabla de destino está vacía, esto no será un problema.

Mark Byers
fuente
73

Para la sintaxis, se ve así (omita la lista de columnas para significar implícitamente "todos")

INSERT INTO this_table_archive
SELECT *
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00'

Para evitar errores de clave primaria si ya tiene datos en la tabla de archivo

INSERT INTO this_table_archive
SELECT t.*
FROM this_table t
LEFT JOIN this_table_archive a on a.id=t.id
WHERE t.entry_date < '2011-01-01 00:00:00'
  AND a.id is null  # does not yet exist in archive
RichardTheKiwi
fuente
6
+1 para la combinación izquierda para evitar colisiones de claves primarias.
Hartley Brody
23

Además de la respuesta de Mark Byers:

A veces también desea insertar detalles codificados, de lo contrario, puede haber una falla de restricción única, etc. Por lo tanto, use lo siguiente en una situación en la que anule algunos valores de las columnas.

INSERT INTO matrimony_domain_details (domain, type, logo_path)
SELECT 'www.example.com', type, logo_path
FROM matrimony_domain_details
WHERE id = 367

Aquí, yo agrego valor de dominio de forma codificada para deshacerme de la restricción única.

Pratik
fuente
4

¿No necesitas double () para el bit de valores? si no, intente esto (aunque debe haber una manera mejor

insert into this_table_archive (id, field_1, field_2, field_3) 
values
((select id from this_table where entry_date < '2001-01-01'), 
((select field_1 from this_table where entry_date < '2001-01-01'), 
((select field_2 from this_table where entry_date < '2001-01-01'), 
((select field_3 from this_table where entry_date < '2001-01-01'));
Daniel Casserly
fuente
2
El OP está usando INSERT INTO .. SELECT FROM, no INSERT INTO .. VALUES. Característica diferente.
Lightness Races in Orbit
0

Más ejemplos y detalles

    INSERT INTO vendors (
     name, 
     phone, 
     addressLine1,
     addressLine2,
     city,
     state,
     postalCode,
     country,
     customer_id
 )
 SELECT 
     name,
     phone,
     addressLine1,
     addressLine2,
     city,
     state ,
     postalCode,
     country,
     customer_id
 FROM 
     customers;
Desarrollador
fuente