La sentencia de creación CREATE TABLE ... SELECT ... nos permite crear una tabla con los registros devueltos por una consulta de selección (SELECT).

Observemos un ejemplo:

Creamos una tabla origen:

CREATE TABLE tabla_origen (
  id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
  descripcion VARCHAR(30),
  fecha TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = MyISAM;

Insertamos una serie de filas y la tabla queda así de llena:

mysql> SELECT * FROM tabla_origen;
+----+------------------+---------------------+
| id | descripcion | fecha |
+----+------------------+---------------------+
| 1 | Primer Registro | 2008-07-20 16:42:16 |
| 2 | Segundo Registro | 2008-07-20 16:42:16 |
| 3 | Tercer Registro | 2008-07-20 16:42:16 |
| 4 | Cuarto Registro | 2008-07-20 16:42:16 |
| 5 | Quinto Registro | 2008-07-20 16:42:16 |
| 6 | Sexto Registro | 2008-07-20 16:42:16 |
| 7 | Séptimo Registro | 2008-07-20 16:42:16 |
| 8 | Octavo Registro | 2008-07-20 16:42:16 |
| 9 | Noveno Registro | 2008-07-20 16:42:16 |
| 10 | Décimo Registro | 2008-07-20 16:42:16 |
+----+------------------+---------------------+
10 rows in SET (0.00 sec)

Utilizamos el CREATE TABLE ... SELECT ...:

mysql> CREATE TABLE clone_select SELECT * FROM tabla_origen;
Query OK, 10 rows affected (0.08 sec)
Records: 10 Duplicates: 0 WARNINGS: 0

Observamos las diferencias de las tablas:

mysql> DESCRIBE tabla_origen;
+-------------+-------------+------+-----+-------------------+----------------
| Field | Type | Null | Key | Default | Extra
+-------------+-------------+------+-----+-------------------+----------------
| id | int(11) | NO | PRI | NULL | auto_increment
| descripcion | varchar(30) | YES | | NULL |
| fecha | timestamp | NO | | CURRENT_TIMESTAMP |
+-------------+-------------+------+-----+-------------------+----------------
3 rows in set (0.00 sec)

mysql> DESCRIBE clone_select;
+-------------+-------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------------------+-------+
| id | int(11) | NO | | 0 | |
| descripcion | varchar(30) | YES | | NULL | |
| fecha | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------+-------------+------+-----+---------------------+-------+
3 rows in set (0.00 sec)

mysql> SELECT table_name, engine FROM information_schema.tables WHERE table_name
IN ('tabla_origen','clone_select') AND table_schema = 'test';
+--------------+--------+
| table_name | engine |
+--------------+--------+
| clone_select | InnoDB |
| tabla_origen | MyISAM |
+--------------+--------+
2 rows in set (0.00 sec)

El método es algo tonto, pues solo se limita a enviar el resultado a una tabla (como si esa tabla se tratase de un archivo), consecuentemente tiene las siguientes limitaciones:

  • No traspasa PRIMARY KEYs
  • No traspasa FOREIGN KEYs
  • No traspasa las definiciones de AUTO_INCREMENT
  • No traspasa las definiciones de DEFAULT CURRENT_TIMESTAMP
  • La tabla se crea con el motor de almacenamiento por defecto de MySQL
  • Solo traspasa los registros afectados por la SELECT

Ahora, si lo que queremos es copiar es solo la estructura de la tabla, podemos utilizar la sentencia LIKE, por ejemplo, CREATE TABLE clone_like LIKE tabla_origen. Así clonaremos la tabla, pero no su contenido. Hay que aclarar además, que salvo las FOREIGN KEYs, el resto de la metadata así como el storage engine será bien clonado.

Vía: cambrico.net