Capítulo 13. Sintaxis de sentencias SQL
Anterior |  | Siguiente

## Capítulo 13. Sintaxis de sentencias SQL

Este capítulo describe la sintaxis para los comandos SQL soportados en MySQL.

## 13.1. Sentencias de definición de datos (Data Definition Statements)

### 13.1.1. Sintaxis de `ALTER DATABASE`

    ALTER {DATABASE | SCHEMA} [db_name]
        alter_specification [, alter_specification] ...

    alter_specification:
        [DEFAULT] CHARACTER SET charset_name
      | [DEFAULT] COLLATE collation_name

`ALTER DATABASE` le permite cambiar las características globales de una base de datos. Estas características se almacenan en el fichero `db.opt` en el directorio de la base de datos. Para usar `ALTER DATABASE`, necesita el permiso `ALTER` en la base de datos.

La cláusula `CHARACTER SET` cambia el conjunto de carácteres por defecto de la base de datos. La cláusula `COLLATE` cambia la colación por defecto de la base de datos. El conjunto de carácteres y la colación se discuten en Capítulo 10, Soporte de conjuntos de caracteres.

En MySQL 5.0, el nombre de base de datos puede omitirse. El comando se aplica a la base de datos por defecto. `ALTER SCHEMA` puede usarse desde MySQL 5.0.2.

### 13.1.2. Sintaxis de `ALTER TABLE`

    ALTER [IGNORE] TABLE tbl_name
        alter_specification [, alter_specification] ...

    alter_specification:
        ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
      | ADD [COLUMN] (column_definition,...)
      | ADD INDEX [index_name] [index_type] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            PRIMARY KEY [index_type] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            UNIQUE [index_name] [index_type] (index_col_name,...)
      | ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
      | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
      | CHANGE [COLUMN] old_col_name column_definition
            [FIRST|AFTER col_name]
      | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
      | DROP [COLUMN] col_name
      | DROP PRIMARY KEY
      | DROP INDEX index_name
      | DROP FOREIGN KEY fk_symbol
      | DISABLE KEYS
      | ENABLE KEYS
      | RENAME [TO] new_tbl_name
      | ORDER BY col_name
      | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
      | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
      | DISCARD TABLESPACE
      | IMPORT TABLESPACE
      | table_options

`ALTER TABLE` le permite cambiar la estructura de una tabla existente. Por ejemplo, puede añadir o borrar columnas, crear o destruir índices, cambiar el tipo de columnas existentes, o renombrar columnas o la misma tabla. Puede cambiar el comentario de la tabla y su tipo.

La sintaxis para varias de las alteraciones permitidas es similar a cláusulas del comando `CREATE TABLE`. Esto incluye modificaciones `table_options` , para opciones tales como `ENGINE`, `AUTO_INCREMENT`, y `AVG_ROW_LENGTH`. Consulte Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

Algunas operaciones pueden producir advertencias si se intentan en una tabla para que el motor de almacenamiento no soporte la operación. Estas advertencias pueden mostrarse con `SHOW WARNINGS`. Consulte Sección 13.5.4.22, “Sintaxis de `SHOW WARNINGS`”.

Si usa `ALTER TABLE` para cambiar la especificación de una columan pero `DESCRIBE `tbl_name`` indica que la columna no ha cambiado, es posible que MySQL haya ignorado las modificaciones por alguna de las razones descritas en Sección 13.1.5.1, “Cambios tácitos en la especificación de columnas”. Por ejemplo, si intenta cambiar una columna `VARCHAR` a `CHAR`, MySQL usa `VARCHAR` si la tabla contiene otras columnas de longitud variable.

`ALTER TABLE` funciona creando una copia temporal de la tabla original. La alteración se realiza en la copia, luego la tabla original se borra y se renombra la nueva. Mientras se ejecuta `ALTER TABLE` la tabla original es legible por otros clientes. Las actualizaciones y escrituras en la tabla se esperan hasta que la nueva tabla esté lista, luego se redirigen automáticamente a la nueva tabla sin ninguna actualización fallida.

Tenga en cuenta que si usa cualquier otra opción en `ALTER TABLE` distinta a `RENAME`, MySQL siempre crea una tabla temporal, incluso si los datos no necesitan ser copiados (tales como cuando cambia el nombre de una columna). Planeamos arreglar esto en el futuro, pero debido a que `ALTER TABLE` no es un comando que se use frecuentemente, no es un tema demasiado urgente. Para tablas `MyISAM` puede incrementar la velocidad de la operación de recrear índices (que es la parte más lenta del proceso de alteración) mediante la variable de sistema `myisam_sort_buffer_size` poniendo un valor alto.

- Para usar `ALTER TABLE`, necesita `ALTER`, `INSERT`, y permisos `CREATE` para la tabla.

- `IGNORE` es una extensión MySQL a SQL estándar. Controla cómo funciona `ALTER TABLE` si hay duplicados en las claves primarias en la nueva tabla o si ocuren advertencias cuando está activo el modo `STRICT`. Si no se especifica `IGNORE` la copia se aborta y no se ejecuta si hay errores de clave duplicada. Si se especifica `IGNORE` , entonces para duplicados con clave única, sólo se usa el primer registro. El resto de registros conflicitivos se borran. Los valores erróneos se truncan al valor más cercano aceptable.

- Puede ejecutar múltiples cláusulas `ADD`, `ALTER`, `DROP`, y `CHANGE` en un único comando `ALTER TABLE` . Esta es una extensión MySQL al estándar SQL, que permite sólo una de cada cláusula por comando `ALTER TABLE` . Por ejemplo, para borrar múltiples columnas en un único comando:

      mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;

- `CHANGE `col_name``, `DROP `col_name``, y `DROP INDEX` son extensiones MySQL al estándar SQL.

- `MODIFY` es una extensión de Oracle a `ALTER TABLE`.

- La palabra `COLUMN` es opcional y puede omitirse.

- Si usa `ALTER TABLE `tbl_name` RENAME TO `new_tbl_name`` sin ninguna otra opción, MySQL símplemente renombra cualquier fichero que se corresponda a la tabla `tbl_name`. No es necesario crear una tabla temporal. (Puede usar el comando `RENAME TABLE` para renombrar tablas. Consulte Sección 13.1.9, “Sintaxis de `RENAME TABLE`”.)

- Las cláusulas `column_definition` usan la misma sintaxis para `ADD` y `CHANGE` así como `CREATE TABLE`. Tenga en cuenta que esta sintaxis incluye el nombre de la columna, no sólo el tipo. Consulte Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

- Puede renombrar una columna usando `CHANGE `old_col_name` `column_definition``. Para ello, especifique el nombre de columna viejo y nuevo y el tipo de la columna actual. Por ejemplo, para renombrar una columna `INTEGER` de `a` a `b`, puede hacer:

      mysql> ALTER TABLE t1 CHANGE a b INTEGER;

  Si quiere cambiar el tipo de una columna pero no el nombre, la sintaxis `CHANGE` necesita un nombre viejo y nuevo de columna, incluso si son iguales. Por ejemplo:

      mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;

  Puede usar `MODIFY` para cambiar el tipo de una columna sin renombrarla:

      mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

- Si usa `CHANGE` o `MODIFY` para acortar una columna para la que existe un índice en la columna, y la longitud de la columna resultante es menor que la del índice, MySQL reduce el índice automáticamente.

- Cuando cambia un tipo de columna usando `CHANGE` o `MODIFY`, MySQL intenta convertir valores de columna existentes al nuevo tipo lo mejor posible.

- En MySQL 5.0, puede usar `FIRST` o `AFTER `col_name`` para añadir una columna a una posición específica sin un registro de tabla. Por defecto se añade al final. Puede usar `FIRST` y `AFTER` en operaciones `CHANGE` o `MODIFY` en MySQL 5.0.

- `ALTER COLUMN` especifica un nuevo valor por defecto para una columna o borra el antiguo valor por defecto. Si el antiguo valor por defecto se borra y la columna puede ser `NULL`, el nuevo valor por defecto es `NULL`. Si la columna no puede ser `NULL`, MySQL asigna un valor por defecto, como se describe en Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

- `DROP INDEX` borra un índice. Es una extensión MySQL al estándar SQL. Consulte Sección 13.1.7, “Sintaxis de `DROP INDEX`”.

- Si las columnas se borran de una tabla, las columnas también se borran de cualquier índice del que formaran parte. Si todas las columnas que crean un índice se borran, también se borra el índice.

- Si una tabla contiene sólo una columna, la columna no puede borrarse. Si lo que quiere es borrar la tabla, use `DROP TABLE` .

- `DROP PRIMARY KEY` borra el índice primario. Nota: En versiones anteriores de MySQL, si no existe clave primaria, entonces `DROP PRIMARY KEY` borraría el primer índice `UNIQUE` de la tabla. Esto ya no es así en MySQL 5.0, cuando trata de usar `DROP PRIMARY KEY` en una tabla sin clave primaria daría lugar a un error.

  Si añade `UNIQUE INDEX` o `PRIMARY KEY` a una tabla, se almacena antes que cualquier índice no único para que MySQL pueda detactar claves duplicadas tan rápido como sea posible.

- `ORDER BY` le permite crear la nueva tabla con los registros en un orden específico. Tenga en cuenta que la tabla no queda en este orden tras las inserciones y borrados. Esta opción es útil cuando sabe que normalmente consultará los registros en el mismo orden; usando esta opción tras grandes cambios en la tabla, puede ser capaz de obtener un mejor rendimiento. En algunos casos, puede hacer la ordenación más fácil para MySQL si la tabla está en el orden de la columna por la que quiere ordenar posteriormente.

- Si usa `ALTER TABLE` en una tabla `MyISAM` , todos los índices no únicos se crean en un batch separado (como para `REPAIR TABLE`). Esto debe hacer `ALTER TABLE` mucho más rápido cuando tiene muchos índices.

  En MySQL 5.0, esta característica puede activarse explícitamente `ALTER TABLE ... DISABLE KEYS` le dice a MySQL que pare de actualizar índices no únicos para una tabla `MyISAM` . `ALTER TABLE ... ENABLE KEYS` debe usarse para recrear índices perdidos. MySQL lo hace con un algoritmo especial que es mucho más rápido que insertar claves una a una, así que deshabilitar claves antes de realizar operaciones de inserción masivas debería dar una mejora de velocidad. Usar `ALTER TABLE ... DISABLE KEYS` requiere del permiso `INDEX` además de los permisos mencionados anteriormente.

- Las cláusulas `FOREIGN KEY` y `REFERENCES` son soportadas por el motor `InnoDB`, que implementa `ADD [CONSTRAINT [`symbol`]] FOREIGN KEY (...) REFERENCES ... (...)`. Consulte Sección 15.6.4, “Restricciones (constraints) `FOREIGN KEY`”. Para otros motores de almacenamiento, las cláusulas se parsean pero se ignoran. La cláusula `CHECK` se parsea pero se ignora por todos los motores de almacenamiento. Consulte Sección 13.1.5, “Sintaxis de `CREATE TABLE`”. La razón para aceptar pero ignorar las cláusulas es para compatibilidad, para hacer más fácil portar código de otros servidores SQL, y para ejecutar aplicaciones que crean tablas con referencias. Consulte Sección 1.7.5, “Diferencias en MySQL del estándar SQL”.

- En MySQL 5.0, `InnoDB` soporta el uso de `ALTER TABLE` para borrar claves foranas:

      ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;

  Para más información, consulte Sección 15.6.4, “Restricciones (constraints) `FOREIGN KEY`”.

- `ALTER TABLE` ignora las opciones `DATA DIRECTORY` y `INDEX DIRECTORY`.

- Si quiere cambiar el conjunto de carácteres por defecto de la tabla y todas las columnas de carácteres (`CHAR`, `VARCHAR`, `TEXT`) a un nuevo conjunto de carácteres, use un comando como:

      ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

  Atención: La operación precedente convierte los valores de columnas entre conjuntos de carácteres. Esto no es lo que quiere hacer si tiene una columna en un conjunto de carácteres (como `latin1`) pero los valores almacenados realmente usan otro conjunto de carácteres incompatible (como `utf8`). En este caso, tiene que hacer lo siguiente para cada una de tales columnas:

      ALTER TABLE t1 CHANGE c1 c1 BLOB;
      ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

  La razón de que esto funcione es que no hay conversión cuando convierte desde o hacia columnas `BLOB` .

  Si especifica `CONVERT TO CHARACTER SET binary`, las columnas `CHAR`, `VARCHAR`, y `TEXT` se converten a sus cadenas de carácteres binarias (`BINARY`, `VARBINARY`, `BLOB`). Esto significa que las columnas no tendrán un conjunto de carácters y que siguientes operaciones `CONVERT TO` no se les aplicarán.

  Para sólo cambiar el conjunto de carácteres por defecto de una tabla, use este comando:

      ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;

  La palabra `DEFAULT` es opcional. El conjunto de carácteres por defecto es el que se usa si no especifica uno para una nueva columna que añada a la tabla (por ejemplo, con `ALTER TABLE ... ADD column`).

  Atención: En MySQL 5.0, `ALTER TABLE ... DEFAULT CHARACTER SET` y `ALTER TABLE ... CHARACTER SET` son equivalentes y cambian sólo el conjunto de carácteres por defecto de la tabla.

- Para una tabla `InnoDB` creada con su propio espacio de tablas en un fichero `.ibd`, este fichero puede descartarse e importarse. Para descatar el fichero `.ibd` , use este comando:

      ALTER TABLE tbl_name DISCARD TABLESPACE;

  Esto borra el fichero `.ibd` actual, así que asegúrese que tiene primero una copia de seguridad. Tratar de acceder a la tabla mientras se descarta el fichero provoca un error.

  Para importar el fichero `.ibd` de la copia de seguridad de nuevo a la tabla, cópielo en el directorio de la base de datos, luego realice el comando:

      ALTER TABLE tbl_name IMPORT TABLESPACE;

  Consulte Sección 15.6.6, “Usar un espacio de tablas para cada tabla”.

- Con la función `mysql_info()` de la API de C, puede consultar el número de registros copiados, y (cuando se usa `IGNORE` ) cuántos registros se borraron debido a duplicación de valores de claves única. Consulte Sección 24.3.3.32, “`mysql_info()`”.

Hay algunos ejemplos que muestran usos de `ALTER TABLE`. Comienza con una tabla `t1` que se crea como se muestra:

    mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

Para renombrar la tabla de `t1` a `t2`:

    mysql> ALTER TABLE t1 RENAME t2;

Para cambiar la columna `a` desde `INTEGER` a `TINYINT NOT NULL` (dejando el mismo nombre), y para cambiar la columna `b` desde `CHAR(10)` a `CHAR(20)` así como dejarla de `b` a `c`:

    mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

Para añadir una nueva columna `TIMESTAMP` llamada `d`:

    mysql> ALTER TABLE t2 ADD d TIMESTAMP;

Para añadir índices en las columnas `d` y `a`:

    mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);

Para borrar la columna `c`:

    mysql> ALTER TABLE t2 DROP COLUMN c;

Para añadir una nueva columna entera `AUTO_INCREMENT` llamada `c`:

    mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
        ->     ADD PRIMARY KEY (c);

Tenga en cuenta que indexamos `c` (como `PRIMARY KEY`), ya que las columnas `AUTO_INCREMENT` deben indexarse, y también que declaramos `c` como `NOT NULL`, ya que las columnas de clave primara no pueden ser `NULL`.

Cuando añade una columna `AUTO_INCREMENT` los valores se rellenan con números secuenciales automáticamente. Para tablas `MyISAM` puede asignar el primer número de secuencia ejecutando `SET INSERT_ID=`value`` antes de `ALTER TABLE` o usando la opción de tabla `AUTO_INCREMENT=`value``. Consulte Sección 13.5.3, “Sintaxis de `SET`”.

Desde MySQL 5.0.3, puede usar la opción de tabla `ALTER TABLE ... AUTO_INCREMENT=`value`` para `InnoDB` para asignar el número de secuencia de nuevos registros si el valor es mayor que el máximo valor en la columna `AUTO_INCREMENT` . Si el valor es menor que el máximo actual en la columna, no se da ningún mensaje de error y el valor de secuencia actual no se cambia.

Con tablas `MyISAM` , si no cambia la columna `AUTO_INCREMENT` , el número de secuencia no se ve afectado. Si elimina una columna `AUTO_INCREMENT` y luego añade otra columna `AUTO_INCREMENT` los números se resecuencian comenzando en 1.

Consulte Sección A.7.1, “Problemas con `ALTER TABLE`”.

### 13.1.3. Sintaxis de `CREATE DATABASE`

    CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
        [create_specification [, create_specification] ...]

    create_specification:
        [DEFAULT] CHARACTER SET charset_name
      | [DEFAULT] COLLATE collation_name

`CREATE DATABASE` crea una base de datos con el nombre dado. Para usar `CREATE DATABASE`, necesita el permiso `CREATE` en la base de datos.

Las reglas para nombres de bases de datos permitidos se dan en Sección 9.2, “Nombres de bases de datos, tablas, índices, columnas y alias”. Ocurre un error si la base de datos existe y no especifica `IF NOT EXISTS`.

En MySQL 5.0, las opciones `create_specification` pueden darse para especificar característica de la base de datos. Las características se almacenan en el fichero `db.opt` en el directorio de la base de datos. La cláusula `CHARACTER SET` especifica el conjunto de carácteres por defecto de la base de datos. La cláusula `COLLATE` especifica la colación por defecto de la base de datos. Los nombres de colación y de conjunto de carácteres se discuten en Capítulo 10, Soporte de conjuntos de caracteres.

Las bases de datos en MySQL se implementan como directorios que contienen ficheros que se corresponden a tablas en la base de datos. Como no hay tablas en la base de datos cuando se crean inicialmente, el comando `CREATE DATABASE` en MySQL 5.0 crea sólo un directorio bajo el directorio de datos de MySQL y el fichero `db.opt` file.

Si crea manualmente un directorio bajo el directorio de datos (por ejemplo, con mkdir), el servidor lo considera como un directorio de base de datos y muestra la salida de `SHOW DATABASES`.

`CREATE SCHEMA` puede usarse desde MySQL 5.0.2.

También puede usar el programa mysqladmin para crear bases de datos. Consulte Sección 8.4, “Administrar un servidor MySQL con mysqladmin”.

### 13.1.4. Sintaxis de `CREATE INDEX`

    CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
        [USING index_type]
        ON tbl_name (index_col_name,...)

    index_col_name:
        col_name [(length)] [ASC | DESC]

En MySQL 5.0, `CREATE INDEX` se mapea a un comando `ALTER TABLE` para crear índices. Consulte Sección 13.1.2, “Sintaxis de `ALTER TABLE`”.

Normalmente, crea todos los índices en una tabla cuando se crea la propia tabla con `CREATE TABLE`. Consulte Sección 13.1.5, “Sintaxis de `CREATE TABLE`”. `CREATE INDEX` le permite añadir índices a tablas existentes.

Una lista de columnas de la forma `(col1,col2,...)` crea un índice de múltiples columnas. Los valores de índice se forman al concatenar los valores de las columnas dadas.

Para columnas `CHAR` y `VARCHAR`, los índices pueden crearse para que usen sólo parte de una columna, usando ``col_name`(`length`)` para indexar un prefijo consistente en los primeros `length` carácteres de cada valor de la columna. `BLOB` t `TEXT` pueden indexarse, pero se debe dar una longitud de prefijo.

El comando mostrado aquí crea un índice usando los primeros 10 carácteres de la columna `name` :

    CREATE INDEX part_of_name ON customer (name(10));

Como la mayoría de nombres usualmente difieren en los primeros 10 carácteres, este índice no debería ser mucho más lento que un índice creado con la columna `name` entera. Además, usar columnas parcialmente para índices puede hacer un fichero índice mucho menor, que puede ahorrar mucho espacio de disco y además acelarar las operaciones `INSERT` .

Los prefijos pueden tener una longitud de hasta 255 bytes. Para tablas `MyISAM` y `InnoDB` en MySQL 5.0, pueden tener una longitud de hasta 1000 bytes . Tenga en cuenta que los límites de los prefijos se miden en bytes, mientras que la longitud de prefijo en comandos `CREATE INDEX` se interpreta como el número de carácteres. Tenga esto en cuenta cuando especifique una longitud de prefijo para una columna que use un conjunto de carácteres de múltiples bytes.

En MySQL 5.0:

- Puede añadir un índice en una columna que puede tener valores `NULL` sólo si está usando `MyISAM`, `InnoDB`, o `BDB` .

- Puede añadir un índice en una columna `BLOB` o `TEXT` sólo si está usando el tipo de tabla `MyISAM`, `BDB`, o `InnoDB` .

Una especificación `index_col_name` puede acabar con `ASC` o `DESC`. Estas palabras se permiten para extensiones futuras para especificar almacenamiento de índice ascendente o descendente. Actualmente se parsean pero se ignoran; los valores de índice siempre se almacenan en orden ascendente.

En MySQL 5.0, algunos motores le permiten especificar un tipo de índice cuando se crea un índice. La sintaxis para el especificador `index_type` es `USING `type_name``. Los valores `type_name` posibles soportados por distintos motores se muestran en la siguiente tabla. Donde se muestran múltiples tipos de índice , el primero es el tipo por defecto cuando no se especifica `index_type` .

Motor de almacenamiento | Tipos de índice permitidos
`MyISAM` | `BTREE`
`InnoDB` | `BTREE`
`MEMORY/HEAP` | `HASH`, `BTREE`

Ejemplo:

    CREATE TABLE lookup (id INT) ENGINE = MEMORY;
    CREATE INDEX id_index USING BTREE ON lookup (id);

`TYPE `type_name`` puede usarse como sinónimo de `USING `type_name`` para especificar un tipo de índice. Sin embargo, `USING` es la forma preferida. Además, el nombre de índice que precede el tipo de índice en la especificación de la sintaxis de índice no es opcional con `TYPE`. Esto es debido a que, en contra de `USING`, `TYPE` no es una palabra reservada y se interpreta como nombre de índice.

Si especifica un tipo de índice que no es legal para un motor de almacenamiento, pero hay otro tipo de índice disponible que puede usar el motor sin afectar los resultados de la consulta, el motor usa el tipo disponible.

Para más información sobre cómo MySQL usa índices, consulte Sección 7.4.5, “Cómo utiliza MySQL los índices”.

Índices `FULLTEXT` en MySQL 5.0 puede indexar sólo columnas `CHAR`, `VARCHAR`, y `TEXT` , y sólo en tablas `MyISAM` . Consulte Sección 12.7, “Funciones de búsqueda de texto completo (Full-Text)”.

Índices `SPATIAL` en MySQL 5.0 puede indexar sólo columnas espaciales, y sólo en tablas `MyISAM` . Los tipo de columna espaciales se describen en Capítulo 18, Extensiones espaciales de MySQL.

### 13.1.5. Sintaxis de `CREATE TABLE`

    CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
        [(create_definition,...)]
        [table_options] [select_statement]

O:

    CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
        [(] LIKE old_tbl_name [)];

    create_definition:
        column_definition
      | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
      | KEY [index_name] [index_type] (index_col_name,...)
      | INDEX [index_name] [index_type] (index_col_name,...)
      | [CONSTRAINT [symbol]] UNIQUE [INDEX]
            [index_name] [index_type] (index_col_name,...)
      | [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...)
      | [CONSTRAINT [symbol]] FOREIGN KEY
            [index_name] (index_col_name,...) [reference_definition]
      | CHECK (expr)

    column_definition:
        col_name type [NOT NULL | NULL] [DEFAULT default_value]
            [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY]
            [COMMENT 'string'] [reference_definition]

    type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
      | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
      | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
      | INT[(length)] [UNSIGNED] [ZEROFILL]
      | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
      | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
      | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
      | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
      | DATE
      | TIME
      | TIMESTAMP
      | DATETIME
      | CHAR(length) [BINARY | ASCII | UNICODE]
      | VARCHAR(length) [BINARY]
      | TINYBLOB
      | BLOB
      | MEDIUMBLOB
      | LONGBLOB
      | TINYTEXT [BINARY]
      | TEXT [BINARY]
      | MEDIUMTEXT [BINARY]
      | LONGTEXT [BINARY]
      | ENUM(value1,value2,value3,...)
      | SET(value1,value2,value3,...)
      | spatial_type

    index_col_name:
        col_name [(length)] [ASC | DESC]

    reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

    reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION

    table_options: table_option [table_option] ...

    table_option:
        {ENGINE|TYPE} = engine_name
      | AUTO_INCREMENT = value
      | AVG_ROW_LENGTH = value
      | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
      | CHECKSUM = {0 | 1}
      | COMMENT = 'string'
      | MAX_ROWS = value
      | MIN_ROWS = value
      | PACK_KEYS = {0 | 1 | DEFAULT}
      | PASSWORD = 'string'
      | DELAY_KEY_WRITE = {0 | 1}
      | ROW_FORMAT = {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}
      | RAID_TYPE = { 1 | STRIPED | RAID0 }
            RAID_CHUNKS = value
            RAID_CHUNKSIZE = value
      | UNION = (tbl_name[,tbl_name]...)
      | INSERT_METHOD = { NO | FIRST | LAST }
      | DATA DIRECTORY = 'absolute path to directory'
      | INDEX DIRECTORY = 'absolute path to directory'

    select_statement:
        [IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

`CREATE TABLE` crea una tabla con el nombre dado. Debe tener el permiso `CREATE` para la tabla.

Las reglas para nombres de tabla permitidos se dan en Sección 9.2, “Nombres de bases de datos, tablas, índices, columnas y alias”. Por defecto, la tabla se crea en la base de datos actual. Ocurre un error si la tabla existe, si no hay base de datos actual o si la base de datos no existe.

En MySQL 5.0, el nombre de tabla puede especificarse como `db_name.tbl_name` para crear la tabla en la base de datos específica. Esto funciona haya una base de datos actual o no. Si usa identificadores entre comillas, entrecomille el nombre de base de datos y de tabla por separado. Por ejemplo, ``mydb`.`mytbl`` es legal, pero ``mydb.mytbl`` no.

Puede usar la palabra `TEMPORARY` al crear una tabla. Una tabla `TEMPORARY` es visible sólo para la conexión actual, y se borra automáticamente cuando la conexión se cierra. Esto significa que dos conexiones distintas pueden usar el mismo nombre de tabla temporal sin entrar en conflicto entre ellas ni con tablas no `TEMPORARY` con el mismo nombre. (La tabla existente se oculta hasta que se borra la tabla temporal.) En MySQL 5.0, debe tener el permiso `CREATE TEMPORARY TABLES` para crear tablas temporales.

MySQL 5.0 soporta las palabras `IF NOT EXISTS` para que no ocurra un error si la tabla existe. Tenga en cuenta que no hay verificación que la tabla existente tenga una estructura idéntica a la indicada por el comando `CREATE TABLE` . Nota: Si usa `IF NOT EXISTS` en un comando `CREATE TABLE ... SELECT` ,cualquier registro seleccionado por la parte `SELECT` se inserta si la tabla existe o no.

MySQL representa cada tabla mediante un fichero `.frm` de formato de tabla (definición) en el directorio de base de datos. El motor para la tabla puede crear otros ficheros también. En el caso de tablas `MyISAM` , el motor crea ficheros índice y de datos. Por lo tanto, para cada tabla `MyISAM` `tbl_name`, hay tres ficheros de disco:

Fichero | Propósito
``tbl_name`.frm` | Fichero de formato de tabla (definición)
``tbl_name`.MYD` | Fichero de datos
``tbl_name`.MYI` | Fichero índice

Los ficheros creados por cada motor de almacenamiento para representar tablas se describen en Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.

Para información general de las propiedades de los diversos tipos de columna, consulte Capítulo 11, Tipos de columna. Para información acerca de tipos de columna espaciales, consulte Capítulo 18, Extensiones espaciales de MySQL.

- Si no se especifica `NULL` ni `NOT NULL`, la columna se trata como si se especificara `NULL` .

- Una columna entera puede tener el atributo adicional `AUTO_INCREMENT`. Cuando inserta un valor de `NULL` (recomendado) o `0` en una columna `AUTO_INCREMENT` autoindexada, la columna se asigna al siguiente valor de secuencia. Típicamente esto es ``value`+1`, donde `value` es el mayor valor posible para la columna en la tabla. Secuencias `AUTO_INCREMENT` comienzan con `1`. Tales columnas deben definirse como uno de los tipos enteros como se describe en Sección 11.1.1, “Panorámica de tipos numéricos”. (El valor 1.0 no es un entero.) Consulte Sección 24.3.3.34, “`mysql_insert_id()`”.

  En MySQL 5.0, especificar `NO_AUTO_VALUE_ON_ZERO` para la opción de servidor `--sql-mode` o la variable de sistema `sql_mode` le permite almacenar `0` en columnas `AUTO_INCREMENT` como `0` sin generar un nuevo valor de secuencia. Consulte Sección 5.3.1, “Opciones del comando mysqld”.

  Nota: Sólo puede haber una columna `AUTO_INCREMENT` por tabla, debe estar indexada, y no puede tener un valor `DEFAULT` . Una columna `AUTO_INCREMENT` funciona correctamente sólo si contiene sólo valores positivos. Insertar un número negativo se trata como insertar un número positivo muy grande. Esto se hace para evitar problemas de precisión cuando los números “cambian” de positivos a negativos y asegura que no obtiene accidentalmente una columna `AUTO_INCREMENT` que contenga `0`.

  Para tablas `MyISAM` y `BDB` , puede especificar una columna `AUTO_INCREMENT` secundaria en una clave de múltiples columnas. Consulte Sección 3.6.9, “Utilización de `AUTO_INCREMENT`”.

  Para hacer MySQL compatible con otras aplicaciones ODBC , puede encontrar el valor `AUTO_INCREMENT` para el último registro insertado con la siguiente consulta:

      SELECT * FROM tbl_name WHERE auto_col IS NULL

- En MySQL 5.0, las definiciones de columnas de carácteres puede incluir un atributo `CHARACTER SET` para especificar el conjunto de carácteres y, opcionalmente, una colación para la columna. Para detalles, consulte Capítulo 10, Soporte de conjuntos de caracteres. `CHARSET` es sinónimo de `CHARACTER SET`.

      CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);

  MySQL 5.0 interpreta las especificaciones de longitud en definiciones de columna en carácteres. (Algunas versiones anteriores los interpretan en bytes.)

- La cláusula `DEFAULT` especifica el valor por defecto para una columna. Con una excepción, el valor por defecto debe ser constante; no puede ser una función o una expresión. Esto significa , por ejemplo, que no puede poner como valor por defecto de una columna el valor de una función como `NOW()` o `CURRENT_DATE`. La excepción es que pude especificar `CURRENT_TIMESTAMP` como defecto para columnas `TIMESTAMP` . Consulte Sección 11.3.1.1, “Propiedades de `TIMESTAMP` desde MySQL 4.1”.

  Antes de MySQL 5.0.2, si una definición de columna no incluye valor `DEFAULT` explícito, MySQL determina el valor por defecto como sigue:

  Si la columna puede tener valores `NULL` , la columna se define como una cláusula `DEFAULT NULL` explícita.

  Si la columna no puede tener valores `NULL` , MySQL define la columna con una cláusula `DEFAULT` explícita, usando el valor por defecto implícito para el tipo de datos de la columna . Los valores por defecto implícitos se definen como sigue:

  - Para tipos numéricos distintos a los declarados con el atributo `AUTO_INCREMENT` , por defecto es `0`. Para una columna `AUTO_INCREMENT` , el valor por defecto es el siguiente valor de la secuencia.

  - Para tipos de fecha y hora distintos a `TIMESTAMP`, el valor por defecto es el valor “cero” apropiado para el tipo. Para la primera columna `TIMESTAMP` en una tabla, el valor por defecto es la fecha actual y la hora. Consulte Sección 11.3, “Tipos de fecha y hora”.

  - Para tipos de cadenas distintos a `ENUM`, el valor por defecto es la cadena vacía. Para `ENUM`, el valor por defecto es el primer valor de la enumeración.

  Las columnas `BLOB` y `TEXT` no pueden tener un valor por defecto.

  Desde MySQL 5.0.2, si una definición de columna no incluye valor `DEFAULT` explícito , MySQL determina el valor por defecto como sigue:

  Si la columna puede tener `NULL` como valor, la columna se define con una cláusula `DEFAULT NULL` explícita. Esto es lo mismo que antes de 5.0.2.

  Si la columna no puede tener valores `NULL` , MySQL define la columna sin cláusula `DEFAULT` explícita. Para entradas de datos, si un comando `INSERT` o `REPLACE` no incluye valor para la columna, MySQL trata la columna según el modo SQL activo en ese momento:

  - Si el modo estricto no está activado, MySQL pone en la columna el valor por defecto implícito para el tipo de datos de la columna.

  - Si está activo el modo estricto, ocurre un error para tablas transaccionales y el comando se deshace. Para tablas no transaccionales, ocurre un error, pero si esto ocurre para el segundo registro o siguientes de un comando de múltiples registros, los registros precedentes se insertarán.

  Suponga que una tabla `t` se define como sigue:

      CREATE TABLE t (i INT NOT NULL);

  En este caso, `i` no tiene valor explícito, así que en modo estricto todos los siguientes comandos producen un error en modo estricto y no se inserta ningún registro. Para modo no estricto, sólo el tercer comando produce un error; el valor implícito por defecto se inserta para las dos primeras, pero la tercera falla ya que `DEFAULT(i)` no puede producir un valor:

      INSERT INTO t VALUES();
      INSERT INTO t VALUES(DEFAULT);
      INSERT INTO t VALUES(DEFAULT(i));

  Consulte Sección 5.3.2, “El modo SQL del servidor”.

  Para una tabla dada, puede usar el comando `SHOW CREATE TABLE` para ver qué columnas puede tener una cláusula explícita `DEFAULT`.

- Un comentario para una columna puede especificarse en MySQL 5.0 con la opción `COMMENT` . El comentario se muestra con los comandos `SHOW CREATE TABLE` y `SHOW FULL COLUMNS` .

- En MySQL 5.0, el atributo `SERIAL` puede usarse como un alias para `BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE`.

- `KEY` normalemente es sinónimo para `INDEX`. En MySQL 5.0, el atributo clave `PRIMARY KEY` puede especificarse como `KEY` cuando se da en una definición de columna. Esto se implementó por compatibilidad con otros sistemas de bases de datos.

- En MySQL, un índice `UNIQUE` es uno en que todos los valores en el índice deben ser distintos. Ocurre un error si intenta añadir un nuevo registro con una clave que coincida con un registro existente. La excepción es que una columna en el índice puede contener valores `NULL` , puede contener valores `NULL` múltiples. Esta excepción no se aplica a tablas `BDB` , en las que una columna indexada le permita un único `NULL`.

- Una `PRIMARY KEY` es una `KEY` única donde todas las columnas de la clave deben definirse como `NOT NULL`. Si no se declaran explícitamente como `NOT NULL`, MySQL las declara implícitamente ( y sin decirlo ) . Una tabla puede tener sólo una `PRIMARY KEY`. Si no tiene una `PRIMARY KEY` y una aplicación pide una `PRIMARY KEY` en sus tablas, MySQL retorna el primer índice `UNIQUE` que no tenga columnas `NULL` como la `PRIMARY KEY`.

- En la tabla creada, una `PRIMARY KEY` se guarda en primer lugar, seguida por todos los índices `UNIQUE`, y luego los índices no únicos. Esto ayuda al optimizador MySQL a priorizar qué indice usar y también detectar más rápido claves `UNIQUE` duplicadas.

- Una `PRIMARY KEY` puede ser un índice de múltiples columnas. Sin embargo, no puede crear un índice de múltiples columnas usando el atributo de clave `PRIMARY KEY` en una especificación de columna. Hacerlo sólo marca la columna como primaria. Debe usar una cláusula `PRIMARY KEY(index_col_name, ...)` separada.

- Si un índice `PRIMARY KEY` o `UNIQUE` consite sólo de una columna que tenga un tipo entero, puede referirse a la columna como `_rowid` en comandos `SELECT`.

- En MySQL, el nombre de una `PRIMARY KEY` es `PRIMARY`. Para otros índices, si no asigna un nombre, el índice tieen el mismo nombre que la primera columna indexada, con un sufijo opcional (`_2`, `_3`, `...`) para hacerlo único. Puede ver los nombres de índice para una tabla usando `SHOW INDEX FROM `tbl_name``. Consulte Sección 13.5.4.11, “Sintaxis de `SHOW INDEX`”.

- A partir de MySQL 5.0, algunos motores de almacenamiento le permiten especificar un tipo de índice al crear el índice. Consulte Sección 13.1.4, “Sintaxis de `CREATE INDEX`”.

  Para más información acerca de cómo usa los índices MySQL, consulte Sección 7.4.5, “Cómo utiliza MySQL los índices”.

- En MySQL 5.0, sólo los motores `MyISAM`, `InnoDB`, `BDB`, y `MEMORY` soporta índices en columnas que pueden tener valores `NULL` . En otros casos, debe declarar columnas indexadas como `NOT NULL` u ocurre un error.

- Con sintaxis ``col_name`(`length`)` en una especificación de índice, puede crear un índice que use sólo los primeros `length` carácteres de una columna `CHAR` o `VARCHAR` . Indexar sólo un prefijo de valores de columna como este puede hacer el fichero de índice mucho más pequeño. Consulte Sección 7.4.3, “Índices de columna”.

  En MySQL 5.0, los motores `MyISAM` y `InnoDB` soportan indexación en columnas `BLOB` y `TEXT` . Al indexar columnas `BLOB` o `TEXT` debe especificar una longitud de prefijo para el índice. Por ejemplo:

      CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

  En MySQL 5.0, los prefijos pueden tener hasta 1000 bytes de longitud para tablas `MyISAM` y `InnoDB` y 255 bytes para otros tipos de tabla. Tenga en cuenta que los límites de prefijo se miden en bytes, mientras que la longitud de prefijo en comandos `CREATE TABLE` se interpretan como el número de carácteres. Asegúrese de tener esto en cuenta al especificar una longitud de prefijo para una columna que use un conjunto de carácteres multi-byte .

- Una especificación `index_col_name` puede acabar con `ASC` o `DESC`. Estas palabras clave se permiten para extensiones futuras para especificar almacenamiento de índices ascendente o descendentemente. Actualmente se parsean pero se ignoran; los valores de índice siempre se almacenan en orden ascendente.

- Cuando usa `ORDER BY` o `GROUP BY` en una columna `TEXT` o `BLOB` en un `SELECT`, el servidor ordena los valores usando sólo el número inicial de bytes indicados por la variable de sistema `max_sort_length` . Consulte Sección 11.4.3, “Los tipos `BLOB` y `TEXT`”.

- En MySQL 5.0, puede crear índices especiales `FULLTEXT` , que se usan para índices full-text . Sólo las tablas `MyISAM` soportan índices `FULLTEXT` . Pueden crearse sólo desde columnas `CHAR`, `VARCHAR`, y `TEXT`. La indexación siempre se hace sobre la columna entera; la indexación parcial no se soporta y cualquier longitud de prefijo se ignora. Consulte Sección 12.7, “Funciones de búsqueda de texto completo (Full-Text)” para más detalles.

- En MySQL 5.0, puede crear índices `SPATIAL` en tipos de columna espaciales. Los tipos espaciales se soportan sólo para tablas `MyISAM` y las columnas indexadas deben declararase como `NOT NULL`. Consulte Capítulo 18, Extensiones espaciales de MySQL.

- En MySQL 5.0, las tablas `InnoDB` soportan el chequeo de restricciones de claves foráneas . Consulte Capítulo 15, El motor de almacenamiento `InnoDB`. Tenga en cuenta que la sintaxis `FOREIGN KEY` en `InnoDB` es más restrictiva que la sintaxis presentada para el comando `CREATE TABLE` al inicio de esta sección: las columnas en la tabla referenciada debe siempre nombrarse explícitamente. `InnoDB` soporta tanto acciones `ON DELETE` como `ON UPDATE` en MySQL 5.0. Para la sintaxis precisa, consulte Sección 15.6.4, “Restricciones (constraints) `FOREIGN KEY`”.

  Para otros motores de almacenamiento, MySQL Server parsea la sintaxis `FOREIGN KEY` y `REFERENCES` en comandos `CREATE TABLE` , pero no hace nada. La cláusula `CHECK` se parsea paro se ignora en todos los motores de almacenamiento. Consulte Sección 1.7.5.5, “Claves foráneas (foreign keys)”.

- Para tablas `MyISAM` cada columna `NULL` ocupa un bit extra, redondeado al byte más próximo. La máxima longitud de registro en bytes puede calcularse como sigue:

      row length = 1
                   + (sum of column lengths)
                   + (number of NULL columns + delete_flag + 7)/8
                   + (number of variable-length columns)

  `delete_flag` es 1 para tables con formato de registro estático. Las tablas estáticas usan un bit en el registro para un flag que indica si el registro se ha borrado. `delete_flag` es 0 para tablas dinámicas ya que el flag se almacena en una cabecera de registro dinámica.

  Estos cálculos no se aplican en tablas `InnoDB` , en las que el tamaño de almacenamiento no es distinto para columnas `NULL` y `NOT NULL` .

La parte `table_options` de la sintaxis `CREATE TABLE` puede usarse desde MySQL 3.23.

Las opciones `ENGINE` y `TYPE` especifican el motor de almacenamiento para la tabla. `ENGINE` es el nombre preferido para la opción en MySQL 5.0, y `TYPE` está obsoleto. El soporte para la palabra `TYPE` usada en este contexto desaparecerá en MySQL 5.1.

Las opciones `ENGINE` y `TYPE` pueden tener los siguientes valores:

Motor de almacenamiento | Descripción
`ARCHIVE` | El motor de almacenamiento para archivar. Consulte Sección 14.7, “El motor de almacenamiento `ARCHIVE`”.
`BDB` | Tablas transaccionales con bloqueo de página. Conocidas como `BerkeleyDB`. Consulte Sección 14.4, “El motor de almacenamiento `BDB` (`BerkeleyDB`)”.
`CSV` | Tablas que almacenan registros en valores separados por comas. Consulte Sección 14.8, “El motor de almacenamiento `CSV`”.
`EXAMPLE` | Motor de ejemplo. Consulte Sección 14.5, “El motor de almacenamiento `EXAMPLE`”.
`FEDERATED` | Motor que accede a tablas remotas. Consulte Sección 14.6, “El motor de almacenamiento `FEDERATED`”.
`HEAP` | Consulte Sección 14.3, “El motor de almacenamiento `MEMORY` (`HEAP`)”.
(OBSOLETE) `ISAM` | No disponible en MySQL 5.0. Si está actualizando a MySQL 5.0 desde una versión prévia, debe convertir cualquier tabla `ISAM` existente a `MyISAM` antes de la actualización. Consulte Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.
`InnoDB` | Tablas transaccionales con bloqueo de registro y claves foráneas. Consulte Capítulo 15, El motor de almacenamiento `InnoDB`.
`MEMORY` | Los datos de este tipo de tabla se almacenan sólo en memoria. (Conocido anteriormente como `HEAP`.)
`MERGE` | Colección de tablas `MyISAM` usadas como una sola tabla. También conocido como `MRG_MyISAM`. Consulte Sección 14.2, “El motor de almacenamiento `MERGE`”.
`MyISAM` | Motor binario portable que es el motor por defecto usado en MySQL. Consulte Sección 14.1, “El motor de almacenamiento `MyISAM`”.
`NDBCLUSTER` | Clusterizado, tolerante a errores, tablas en memoria. También conocido como `NDB`. Consulte Capítulo 16, MySQL Cluster.

Para más información acerca de motores MySQL, consulte Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.

Si un motor no está disponible, MySQL usa en su lugar `MyISAM` . Por ejemplo, si una definición de tabla incluye la opción `ENGINE=BDB` pero el servidor MySQL no soporta tablas `BDB` , la tabla se crea como `MyISAM` . Esto hace posible tener un entorno de replicación donde tiene tablas transaccionales en el maestro pero tablas no transaccionales en el esclavo (para tener más velocidad). En MySQL 5.0, aparece una advertencia si la especificación del motor no es correcta.

Las otras opciones de tabla se usan para optimizar el comportamiento de la tabla. En la mayoría de casos, no tiene que especificar ninguna de ellas. La opción funciona para todos los motores a no ser que se indique lo contrario:

- `AUTO_INCREMENT`

  El valor inicial para `AUTO_INCREMENT` para la tabla. En MySQL 5.0, sólo funciona para tablas `MyISAM` y `MEMORY`. También se soporta para `InnoDB` desde MySQL 5.0.3. Para inicializar el primer valor de auto incremento para motores que no soporten esta opción, inserte un registro de prueba con un valor que sea uno menor al deseado tras crear la tabla, y luego borre este registro.

  Para motores que soportan la opción de tabla `AUTO_INCREMENT` en comandos `CREATE TABLE` puede usar `ALTER TABLE `tbl_name` AUTO_INCREMENT = `n`` para resetear el valor `AUTO_INCREMENT` .

- `AVG_ROW_LENGTH`

  Una aproximación de la longitud media de registro para su tabla. Necesita inicializarla sólo para tablas grandes con registros de longitud variable.

  Cuando crea una tabla `MyISAM` , MySQL usa el producto de las opciones `MAX_ROWS` y `AVG_ROW_LENGTH` para decidir el tamaño de la tabla resultante. Si no las especifica, el tamaño máximo para la tabla es 65,536TB de datos (4GB antes de MySQL 5.0.6). (Si su sistema operativo no soporta ficheros de este tamaño, los tamaños de fichero se restringen al límite del sistema operativo.) Si quiere mantener bajos los tamaños de los punteros para que el índice sea pequeño y rápido y no necesita realmente ficheros grandes, puede decrementar el tamaño de puntero por defecto mediante la variable de sistema `myisam_data_pointer_size` que se añadió en MySQL 4.1.2. (Consulte Sección 5.3.3, “Variables de sistema del servidor”.) Si quiere que todas sus tablas sean capaces de crecer por encima del límite por defecto y quiere mantener sus tablas ligeramente más lentas y más grandes de lo necesario, puede incrementar el tamaño de punter por defecto cambiando esta variable.

- `[DEFAULT] CHARACTER SET`

  Especifica el conjunto de carácteres para la tabla. `CHARSET` es un sinónimo.

  para `CHARACTER SET`.

- `COLLATE`

  Especifica la colación por defecto de la tabla.

- `CHECKSUM`

  Póngalo a 1 si quiere que MySQL mantenga un checksum para todos los registros (un checksum que MySQL actualiza automáticamente según cambia la tabla). Esto hace que la tabla tenga actualizaciones más lentas, pero hace más fácil encontrar tablas corruptas. El comando `CHECKSUM TABLE` muestra el checksum (sólo para `MyISAM`).

- `COMMENT`

  Un comentario para su tabla, hasta 60 carácteres.

- `MAX_ROWS`

  Máximo número de registros que planea almacenar en la tabla. No es un límite absoluto, sino un indicador que la tabla debe ser capaz de almacenar al menos estos registros.

- `MIN_ROWS`

  Mínimo número de registros que planea almacenar en la tabla.

- `PACK_KEYS`

  Ponga esta opción a 1 si quiere tener índices más pequeños. Esto hace normalmente que las actualizaciones sean más lentas y las lecturas más rápidas. Poner esta opción a 0 deshabilita la compresión de claves. Ponerla a `DEFAULT` le dice al motor que comprima sólo columnas `CHAR`/`VARCHAR` largas (`MyISAM` y `ISAM` sólo).

  Si no usa `PACK_KEYS`, por defecto se comprimen sólo cadenas, no números. Si usa `PACK_KEYS=1`, también se empaquetan números.

  Al comprimir claves de números binarios, MySQL usa compresión de prefijo:

  - Cada clave necesita un byte extra para indicar cuántos bytes de la clave previa son los mismos para la siguiente clave.

  - El puntero al registro se almacena en orden de el-mayor-byte-primero directamente tras la clave, para mejorar la compresión.

  Esto significa que si tiene muchas claves iguales en dos registros consecutivos, todas las “mismas” claves siguientes usualmente sólo ocupan dos bytes (incluyendo el puntero al registro). Comparar esto con el caso ordinario donde las siguente claves ocupan `storage_size_for_key + pointer_size` (donde el tamaño del puntero es usualmente 4). Obtiene un gran beneficio a partir de la compresión de prefijos sñolo si tiene muchos números que sean el mismo. Si todas las claves son totalmente distintas, usa un byte más por clave, si la clave no es una clave que pueda tener valores `NULL` . (En ese caso, el tamaño empaquetado de la clave se almacena en el mismo byte que se usa para marcar si una clave es `NULL`.)

- `PASSWORD`

  Encripta el fichero `.frm` con una contraseña. Esta opción no hace nada en la versión estándar de MySQL.

- `DELAY_KEY_WRITE`

  Póngalo a 1 si quiere retardar actualizaciones de clave para la tabla hasta que la tabla se cierra (sólo en `MyISAM`).

- `ROW_FORMAT`

  Define cómo deben almacenarse los registros. Actualmente esta opción sólo funciona con tablas `MyISAM`. El valor de la opción puede ser `FIXED` o `DYNAMIC` para formato de longitud estática o variable. myisampack cambia el tipo a `COMPRESSED`. Consulte Sección 14.1.3, “Formatos de almacenamiento de tablas `MyISAM`”.

  Desde MySQL/InnoDB-5.0.3, los registros de InnoDB se almacenan de forma más compacta (`ROW_FORMAT=COMPACT`) por defecto. El antiguo formato puede usarse espeficicando `ROW_FORMAT=REDUNDANT`.

- `RAID_TYPE`

  Tenga en cuenta que el soporte para `RAID` se ha eliminado desde MySQL 5.0. Para información sobre `RAID`, consulte Manual de referencia de MySQL 4.1.

- `UNION`

  `UNION` se usa cuando quiere usar una colección de tablas idénticas como una. Funciona sólo con tablas `MERGE` . Consulte Sección 14.2, “El motor de almacenamiento `MERGE`”.

  En MySQL 5.0, debe tener permisos `SELECT`, `UPDATE`, y `DELETE` para las tablas mapeadas en una tabla `MERGE` . (Nota: Originalmente, todas las tablas usadas tenían que estar en la misma base de datos que la tabla `MERGE`. Esta restricción se ha eliminado.)

- `INSERT_METHOD`

  Si quiere insertar datos en una tabla `MERGE` debe especificarlo con `INSERT_METHOD` en la tabla en que se debe insertar el registro. `INSERT_METHOD` es una opción útil para tablas `MERGE` sólo. Use un valor dee `FIRST` o `LAST` para que las inserciones vayan a la primera o última tabla, o un valor de `NO` para evitar inserciones. Consulte Sección 14.2, “El motor de almacenamiento `MERGE`”.

- `DATA DIRECTORY`, `INDEX DIRECTORY`

  Usando `DATA DIRECTORY='`directory`'` o `INDEX DIRECTORY='`directory`'` puede especificar dónde debe el moto `MyISAM` buardar un fichero de datos e índice de una tabla. Tenga en cuenta que el directorio debe ser una ruta completa al directorio (no una ruta relativa).

  Estas opciones sólo funcionan cuando no usa la opción `--skip-symbolic-links` . Su sistema operativo debe tener una llamada `realpath()` que funcione bien. Consulte Sección 7.6.1.2, “Utilización de enlaces simbólicos para tablas en Unix” para más información.

En MySQL 5.0, puede crear una tabla de otra añadiendo un comando `SELECT` al final del comando `CREATE TABLE` :

    CREATE TABLE new_tbl SELECT * FROM orig_tbl;

MySQL crea nuevas columnas para todos los elementos en un `SELECT`. Por ejemplo:

    mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
        ->        PRIMARY KEY (a), KEY(b))
        ->        TYPE=MyISAM SELECT b,c FROM test2;

Esto crea una tabla `MyISAM` con tres columnas, `a`, `b`, y `c`. Tenga en cuenta que las columnas para el comando `SELECT` se añaden a la derecha de la tabla, no se sobreescriben en la misma. Consulte el siguiente ejemplo:

    mysql> SELECT * FROM foo;
    +---+
    | n |
    +---+
    | 1 |
    +---+

    mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
    Query OK, 1 row affected (0.02 sec)
    Records: 1  Duplicates: 0  Warnings: 0

    mysql> SELECT * FROM bar;
    +------+---+
    | m    | n |
    +------+---+
    | NULL | 1 |
    +------+---+
    1 row in set (0.00 sec)

Para cada registro en la tabla `foo`, se inserta un registro en `bar` con los valores de `foo` y valores por defecto para las nuevas columnas:

Si hay cualquier error al copiar los datos a la tabla, se borra automáticamente y no se crea.

`CREATE TABLE ... SELECT` no crea ningún índice automáticamente. Se hace a propósito para hacer el comando lo más flexible posible. Si quiere tener índices en la tabla creada, debe especificarlo antes del comando `SELECT` :

    mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

Algunas conversiones de tipos de columnas pueden ocurrir. Por ejemplo, el atributo `AUTO_INCREMENT` no se preserva, y las columnas `VARCHAR` pueden ser `CHAR` .

Al crear una tabla con `CREATE ... SELECT`, asegurése de poner un alias para cualquier llamada a función o expresión en la consulta. Si no lo hace, el comando `CREATE` puede fallar o crear nombres de columnas no deseados.

    CREATE TABLE artists_and_works
    SELECT artist.name, COUNT(work.artist_id) AS number_of_works
    FROM artist LEFT JOIN work ON artist.id = work.artist_id
    GROUP BY artist.id;

Puede especificar explícitamente el tipo de una columna generada:

    CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

En MySQL 5.0, use `LIKE` para crear una tabla vacía basada en la definición de otra tabla, incluyendo cualquier atributo de columna e índice definido en la tabla original:

    CREATE TABLE new_tbl LIKE orig_tbl;

`CREATE TABLE ... LIKE` no copia ninguna opción de tabla `DATA DIRECTORY` o `INDEX DIRECTORY` especificadas en la tabla original, ni ninguna definición de clave foránea.

Puede preceder `SELECT` con `IGNORE` o `REPLACE` para indicar cómo tratar registros que dupliquen claves únicas. Con `IGNORE`, los nuevos registros que duplican un registro único existente se descartan. Con `REPLACE`, los nuevos registros reemplazan a los antiguos con el mismo valor. Si ni `IGNORE` ni `REPLACE` se indican, los valores únicos duplicados dan un error.

Para asegurar que el log de update o binario puede usarse para recrear tablas originales, MySQL no permite inserciones concurrentes durante `CREATE TABLE ... SELECT`.

#### 13.1.5.1. Cambios tácitos en la especificación de columnas

En algunos casos, MySQL cambia especificaciones de columnas silencioasmente de las dadas en un comando `CREATE TABLE` o `ALTER TABLE` . Pueden ser cambiso a un tipo de datos, a atributos asociados con un tipo de datos o a una especificación de índice.

Los posibles cambios de tipos de datos se dan en la siguiente lista. Ocurren antes de MySQL 5.0.3. Desde 5.0.3, ocurre un error si no se puede crear una columna usando el tipo de datos especificado.

- Columnas `VARCHAR` con una longitudo menor que cuatro se cambian a `CHAR`.

- Si cualquier columna en una tabla tiene una longitud variable, el registro entero pasa a tener longitud variable. Por lo tanto, si una tabla contiene cualquier columna de longitud variable (`VARCHAR`, `TEXT`, o `BLOB`), toda columna `CHAR` con más de tres carácteres se cambia a columna `VARCHAR` . Esto no afecta cómo usa las columnas en ningún modo; en MySQL, `VARCHAR` es sólo un modo distinto de almacenar carácteres. MySQL realiza esta conversión porque ahorra espacio y hacer las operaciones de tabla más rápidas. Consulte Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.

- Antes de MySQL 5.0.3, una columna `CHAR` o `VARCHAR` con una longitud mayor a 255 se convierte al tipo `TEXT` más pequeño que puede contener valores de la longitud dada. Por ejemplo, `VARCHAR(500)` se convierte en `TEXT`, y `VARCHAR(200000)` se convierte en `MEDIUMTEXT`. Tenga en cuenta que esta conversión resulta en un cambio de comportamiento del tratamiento de espacios finales.

  Conversiones similares ocurren para `BINARY` y `VARBINARY`, excepto que se convierten en tipo `BLOB`.

  Desde MySQL 5.0.3, una columna `CHAR` o `BINARY` con una longitud mayor a 255 no se convierte silenciosamente . En su lugar, ocurre un error. Desde MySQL 5.0.6 , la conversión silenciosa de columnas `VARCHAR` y `VARBINARY` con una longitudo mayor a 65,535 no ocurre si el modo estricto SQL está activado. En su lugar, ocurre un error.

- Para una especificación de `DECIMAL(`M`,`D`)`, si `M` no es mayor que `D`, se ajusta por encima. Por ejemplo `DECIMAL(10,10)` pasa a ser `DECIMAL(11,10)`.

Otros cambios de columna incluyen cambios de atributos o especficación de índice:

- Los tamaños de muestra de `TIMESTAMP` se descartan. Tenga en cuenta que columnas `TIMESTAMP` han cambiado considrablemente en versiones recientes de MySQL anteriores a 5.0; para una descripción, consulte Manual de referencia de MySQL 4.1.

- Las columnas que son parte de `PRIMARY KEY` son `NOT NULL` incluso si no se declaran como tales.

- Los espacios finales se borran automáticamente para `ENUM` y `SET` cuando se crea la tabla.

- MySQL mapea ciertos tipos de columna usados por otras bases de datos SQL a tipos MySQL . Consulte Sección 11.7, “Usar tipos de columnas de otros motores de bases de datos”.

- Si incluye una cláusula `USING` para especificar un tipo de índice que no sea legal para un motor de almacenamiento dado, pero hay otro tipo de índice disponible que puede usar el motor sin afectar el resultado de la consulta, el motor usa el tipo disponible.

Para ver si MySQL usa un tipo de columna distinto al especificado, realice un comando `DESCRIBE` o `SHOW CREATE TABLE` tras crear o alterar la tabla.

Otros cambios de tipo de columna pueden ocurrir si comprime una tabla usando myisampack. Consulte Sección 14.1.3.3, “Características de las tablas comprimidas”.

### 13.1.6. Sintaxis de `DROP DATABASE`

    DROP {DATABASE | SCHEMA} [IF EXISTS] db_name

`DROP DATABASE` borrar todas las tablas en la base de datos y borrar la base de datos. Sea muy cuidadoso con este comando! Para usar`DROP DATABASE`, necesita el permiso `DROP` en la base de datos.

`IF EXISTS` se usa para evitar un error si la base de datos no existe.

`DROP SCHEMA` puede usarse desde MySQL 5.0.2.

Si usa `DROP DATABASE` en una base de datos enlazada simbólicamente, tanto el enlace como la base de datos se borran.

`DROP DATABASE` retorna el número de tablas que se eliminan. Se corresponde con el número de ficheros `.frm` borrados.

El comando `DROP DATABASE` borrar del directorio de base de datos los ficheros y directorios que MySQL puede crear durante operaciones normales:

- Todos los ficheros con estas extensiones:

  `.BAK` | `.DAT` | `.HSH` |
  `.MRG` | `.MYD` | `.ISD` |
  `.MYI` | `.db` | `.frm` |

- Todos los subdirectorios con nombres que tienen dos dígitos hexadecimales `00`-`ff`. Son subdirectorios usados por tablas `RAID` . (Estos directorios no se borran desde MySQL 5.0, cuando se eliminó el soporte para tablas `RAID` . Debe convertir las tablas `RAID` y eliminar estos directorios manualmente antes de actualizar a MySQL 5.0. Consulte Sección 2.10.1, “Aumentar la versión de 4.1 a 5.0”.)

- El fichero `db.opt` , si existe.

Si permanecen otros ficheros o directorios en el directorio de la base de datos tras que MySQL borre los ficheros listados, el directorio de base de datos no puede borrarse. En este caso, debe borrar cualquier fichero restante manualmente y realizar el comando `DROP DATABASE` de nuevo.

Puede borrar bases de datos con mysqladmin. Consulte Sección 8.4, “Administrar un servidor MySQL con mysqladmin”.

### 13.1.7. Sintaxis de `DROP INDEX`

    DROP INDEX index_name ON tbl_name

`DROP INDEX` borra el índice llamado `index_name` de la tabla `tbl_name`. En MySQL 5.0, `DROP INDEX` se mapea a comando `ALTER TABLE` para borrar el índice. Consulte Sección 13.1.2, “Sintaxis de `ALTER TABLE`”.

### 13.1.8. Sintaxis de `DROP TABLE`

    DROP [TEMPORARY] TABLE [IF EXISTS]
        tbl_name [, tbl_name] ...
        [RESTRICT | CASCADE]

`DROP TABLE` borra una o más tablas. Debe tener el permiso `DROP` para cada tabla. Todos los datos de la definición de tabla son borrados, así que tenga cuidado con este comando!

Use `IF EXISTS` para evitar un error para tablas que no existan. Un `NOTE` se genera para cada tabla no existente cuando se usa `IF EXISTS`. Consulte Sección 13.5.4.22, “Sintaxis de `SHOW WARNINGS`”.

`RESTRICT` y `CASCADE` se permiten para hacer la portabilidad más fácil. De momento, no hacen nada.

Nota: `DROP TABLE` hace un commit automáticamente con la transacción activa,a no ser que use la palabra `TEMPORARY`.

La palabra `TEMPORARY` tiene el siguiente efecto:

- El comando sólo borra tablas `TEMPORARY`.

- El comando no acaba una transacción en marcha.

- No se chequean derechos de acceso. (Una tabla `TEMPORARY` es visible sólo para el cliente que la ha creado, así que no es necesario.)

Usar `TEMPORARY` es una buena forma de asegurar que no borra accidentalmente una tabla no `TEMPORARY`.

### 13.1.9. Sintaxis de `RENAME TABLE`

    RENAME TABLE tbl_name TO new_tbl_name
        [, tbl_name2 TO new_tbl_name2] ...

Este comando renombra una o más tablas.

La operación de renombrar se hace automáticamente, lo que significa que ningún otro flujo puede acceder a ninguna de las tablas mientras se ejecuta el renombrado. Por ejemplo, si tiene una tabla existente `old_table`, puede crear otra tabla `new_table` con la misma estructura pero vacía, y luego reemplazar la tabla existente con la vacía como sigue:

    CREATE TABLE new_table (...);
    RENAME TABLE old_table TO backup_table, new_table TO old_table;

Si el comando renombra más de una tabla, las operaciones de renombrado se realizan de izquierda a derecha. Si quiere intercambiar dos nombres de tablas, puede hacerlo así (asumiendo que no existe ninguna tabla llamada `tmp_table`):

    RENAME TABLE old_table TO tmp_table,
                 new_table TO old_table,
                 tmp_table TO new_table;

Mientras haya dos bases de datos en el mismo sistema de ficheros puede renombrar una tabla para moverla de una base de datos a otra:

    RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

Cuando ejecuta `RENAME`, no puede tener ninguna tabla bloqueada o transacciones activas. Debe tener los permisos `ALTER` y `DROP` en la tabla original, y los permisos `CREATE` y `INSERT` en la nueva tabla.

Si MySQL encuentra cualquier error en un renombrado múltiple, hace un renombrado inverso para todas las tablas renombradas para devolver todo a su estado original.

## 13.2. Sentencias de manipulación de datos (Data Manipulation Statements)

### 13.2.1. Sintaxis de `DELETE`

Sintaxis para una tabla:

             DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
             [WHERE where_definition]
             [ORDER BY ...]
             [LIMIT row_count]

Sintaxis para múltiples tablas:

           DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
           tbl_name[.*] [, tbl_name[.*] ...]
           FROM table_references
           [WHERE where_definition]

O:

           DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
           FROM tbl_name[.*] [, tbl_name[.*] ...]
           USING table_references
           [WHERE where_definition]

`DELETE` borra los registros de `tbl_name` que satisfacen la condición dada por `where_definition`, y retorna el número de registros borrados.

Si realiza un comando `DELETE` sin cláusula `WHERE` se borran todos los registros. Una forma más rápida de hacerlo, cuando no quiere saber el número de registros borrados, se usa `TRUNCATE TABLE`. Consulte Sección 13.2.9, “Sintaxis de `TRUNCATE`”.

Si borra el registro conteniendo el máximo valor para una columna `AUTO_INCREMENT` , el valor se reúsa para una tabla `BDB` , pero no para tablas `MyISAM` o `InnoDB` . Si borra todos los registros en la tabla con `DELETE FROM `tbl_name`` (sin cláusula `WHERE` ) en modo `AUTOCOMMIT` , la secuencia comienza para todos los tipos de tabla excepto para `InnoDB` y `MyISAM`. Hay algunas excepciones para este comportamiento para tablas `InnoDB` , como se discute en Sección 15.6.3, “Cómo funciona una columna `AUTO_INCREMENT` en `InnoDB`”.

Para tablas `MyISAM` y `BDB` , puede especificar una columna `AUTO_INCREMENT` secundaria en una clave de múltiples columnas. En este caso, el reúso de valores borrados del inicio de la secuencia se realiza incluso para tablas `MyISAM` . Consulte Sección 3.6.9, “Utilización de `AUTO_INCREMENT`”.

El comando `DELETE` soporta los siguientes modificadores:

- Si especifica `LOW_PRIORITY`, la ejecución de `DELETE` se retarda hasta que no hay más clientes leyendo de la tabla.

- Para tablas `MyISAM` , si usa la palabra `QUICK` , el motor de almacenamiento no mezcla las hojas del índice durante el borrado, que puede acelerar algunos tipos de operaciones de borrado.

- En MySQL 5.0, la palabra clave `IGNORE` hace que MySQL ignore todos los errores durante el proceso de borrar registros. (Los errores encontrados durante la etapa de parseo se procesan de la forma habitual.) Los errores que se ignoran debido al uso de esta opción se retornan como advertencias.

La velocidad de las operaciones de borrado pueden verse afectadas por factores discutidos en Sección 7.2.16, “Velocidad de sentencias `DELETE`”.

En tablas `MyISAM` , los registros borrados se mantienen en una lista enlazada y las operaciones `INSERT` siguientes reúsan antiguas posiciones de registro. Para reclamar espacio no usado y reducir tamaño de fichero, use el comando `OPTIMIZE TABLE` o la utilidad myisamchk para reorganizar las tablas. `OPTIMIZE TABLE` es más sencillo, pero myisamchk es más rápido. Consulte Sección 13.5.2.5, “Sintaxis de `OPTIMIZE TABLE`” y Sección 5.8.3.10, “Optimización de tablas”.

El modificador `QUICK` afecta si las hojas del índice es mezclan en operaciones de borrado. `DELETE QUICK` es más útil para aplicaciones en que los valores del índice para registros borrados se replazan con valores similares de registros insertados posteriormente. En este caso, los agujeros dejados por los valores borrados se reúsan.

`DELETE QUICK` no es útil cuando los valores borrados conducen a bloques de índices no rellenos con un rango de valores índice para el que vuelven a ocurrir nuevas inserciones. En este caso, el uso de `QUICK` puede conducir a un gasto de espacio que queda sin reclamar. Aquí hay un ejemplo de este escenario:

1. Cree una tabla que contenga una columna `AUTO_INCREMENT` indexada.

2. Inserta varios registros en la tabla. Cada inserción resulta en un valor índice que se añade al final del índice.

3. Borra un bloque de registros al final del rango de la columna usando `DELETE QUICK`.

En este escenario, los bloques de índice asociados con los valores de índice borrado quedan sin rellenar pero no se mezclan con otros bloques de índice debido al uso de `QUICK`. Quedan sin rellenar cuando hay nuevas inserciones, ya que los nuevos registros no tienen valores índice en el rango borrado. Además, quedan sin rellenar incluso si luego usa `DELETE` sin `QUICK`, a no ser que algunos de los valores de índice borrados estén en los bloques de índice dentro o adyacentes a los bloques no rellenos. Para reclamar el espacio de índice sin usar bajo estas circunstancias use `OPTIMIZE TABLE`.

Si va a borrar varios registros de una tabla, puede ser más sencillo usar `DELETE QUICK` seguido por `OPTIMIZE TABLE`. Esto reconstruye el índice en lugar de realizar varias operaciones de mezcla de bloques de índice.

La opción de MySQL `LIMIT `row_count`` para `DELETE` le dice al servidor el máximo número de registros a borrar antes de retornar el control al cliente. Esto puede usarse para asegurar que un comando `DELETE` específico no tarada demasiado tiempo. Puede simplemente repetir el comando `DELETE` hasta que el número de registros afectados sea menor que el valor `LIMIT` .

Si el comando `DELETE` incluye una cláusula `ORDER BY` , los registros se borran en el orden especificado por la cláusula. Esto es muy útil sólo en conjunción con `LIMIT`. Por ejemplo, el siguiente ejemplo encuentra registros coincidentes con la cláusula `WHERE` ordenados por `timestamp_column`, y borra el primero (el más viejo).

    DELETE FROM somelog
    WHERE user = 'jcole'
    ORDER BY timestamp_column
    LIMIT 1;

Puede especificar múltiples tablas en un comando `DELETE` para borrar registros de una o más tablas dependiendo de una condición particular en múltiples tablas. Sin embargo, no puede usar `ORDER BY` o `LIMIT` en un `DELETE` de múltiples tablas.

La parte `table_references` lista las tablas involucradas en el join. Esta sintaxis se describe en Sección 13.2.7.1, “Sintaxis de `JOIN`”.

Para la primera sintaxis, sólo los registros coincidentes de las tablas listadas antes de la cláusula `FROM` se borran. Para la segunda sintaxis, sólo los registros coincidentes de las tablas listadas en la cláusula `FROM` (antes de la cláusula `USING` ) se borran. El efecto es que puede borrar registros para varias tablas al mismo tiempo y tienen tablas adicionales que se usan para buscar:

    DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

O:

    DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

Estos comandos usan las tres tablas al buscar registros a borrar, pero borrar los registros coincidentes sólo para las tablas `t1` y `t2`.

Los ejemplos anteriores muestran inner joins usando el operador coma, pero comandos `DELETE` de varias tablas pueden usar cualquier tipo de join permitido por comandos `SELECT` tales como `LEFT JOIN`.

La sintaxis permite `.*` tras los nombres de tabla para compatibilidad con `Access`.

Si usa un comando `DELETE` de varias tablas incluyendo tablas `InnoDB` para las que hay restricciones de clave foránea, el optimizador MySQL puede procesar tablas en un orden ditinto del de su relación padre/hijo. En este caso, el comando falla y se deshace. En su lugar, debe borrar de una tabla úncia y confiar en la capacidad de `ON DELETE` que proporciona `InnoDB` para hacer que las otras tablas se modifiquen correctamente.

Nota: En MySQL 5.0, debe usar el alias (si se dió) al referirse a un nombre de tabla:

En MySQL 4.1:

    DELETE t1 FROM test AS t1, test2 WHERE ...

Borrados cruzados entre bases de datos se soportan para borrados de varias tablas, pero en este caso, debe referirse a las tablas sin usar alias. Por ejemplo:

    DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...

Actualmente, no puede borrar desde una tabla y seleccionar de la misma tabla en una subconsulta.

### 13.2.2. Sintaxis de `DO`

           DO expr [, expr] ...

`DO` ejecuta la expresión pero no retorna ningún resultado. Esto es una abreviación de `SELECT `expr`, ...`, pero tiene la ventaja que es más rápido cuando no le importa el resultado.

`DO` es útil principalmente con funciones que tienen efectos colaterales, tales como `RELEASE_LOCK()`.

### 13.2.3. Sintaxis de `HANDLER`

    HANDLER tbl_name OPEN [ AS alias ]
    HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
    [ WHERE where_condition ] [LIMIT ... ]
    HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE where_condition ] [LIMIT ... ]
    HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE where_condition ] [LIMIT ... ]
    HANDLER tbl_name CLOSE

El comando `HANDLER` proporciona acceso directo a las interfaces del motor de la tabla. En MySQL 5.0, está disponible para tablas `MyISAM` y `InnoDB` .

El comando `HANDLER ... OPEN` abre una tabla, haciéndola accesible mediante posteriores comandos `HANDLER ... READ` . Este objeto de tabla no se comparte con otros flujos y no se cierra hasta que el flujo llama `HANDLER ... CLOSE` o el flujo termina. Si abre la tabla usando un alias, referencias posteriores a la tabla con otros comandos `HANDLER` deben usar el alias en lugar del nombre de la tabla.

La primera sintaxis `HANDLER ... READ` recibe un registro donde el índice especificado satisface los valores dados y la condición `WHERE` se cumple. Si tiene un índice de múltiples columnas, especifique los valores de la columna índice como una lista separada por comas. Los valores epecificados para todas las columnas en el índice, o los valores específicos para un prefijo a la izquierda de las columnas índice. Suponga que un índice incluye tres columnas llamadas `col_a`, `col_b`, y `col_c`, en ese orden. El comando `HANDLER` puede especificar valores para las tres columnas en el índice, o para las columnas en el prefijo a la izquierda. Por ejemplo:

    HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
    HANDLER ... index_name = (col_a_val,col_b_val) ...
    HANDLER ... index_name = (col_a_val) ...

La segunda sintaxis `HANDLER ... READ` recibe un registro de la tabla en orden del índice que cumple la condición `WHERE` .

La tercera sintaxis `HANDLER ... READ` recibe un registro de la tabla en orden de registro natural que cumple la condición `WHERE` . Es más rápido que `HANDLER `tbl_name` READ index_name` cuando se desea un escaneo completo de tabla. El orden de registro natural es el orden en que se almacenan los registros en un fichero de datos de una tabla `MyISAM`. Este comando funciona para tablas `InnoDB` también, pero no hay tal concepto porque no hay un fichero de datos separado.

Sin una cláusula `LIMIT` , todas las formas de `HANDLER ... READ` reciben un único registros si una está disponible. Para retornar un número específico de registros, incluya una cláusula `LIMIT` . Tiene la misma sintaxis que para el comando `SELECT` . Consulte Sección 13.2.7, “Sintaxis de `SELECT`”.

`HANDLER ... CLOSE` cierra una tabla que se abrió con `HANDLER ... OPEN`.

Nota: Para emplear la interfaz `HANDLER` para referirse a una tabla `PRIMARY KEY`, use el identificador ``PRIMARY`` entrecomillado:

      HANDLER tbl_name READ `PRIMARY` > (...);

`HANDLER` es un comando de bajo nivel. Por ejemplo, no proporciona consistencia. Esto es, `HANDLER ... OPEN` no toma una muestra de la tabla, y no bloquea la tabla. Esto significa que tras un comando `HANDLER ... OPEN` realizado, los datos de la tabla pueden ser modificados (por este o por otro flujo) y estas modificaciones pueden aparecer sólo parcialmente en escaneos `HANDLER ... NEXT` o `HANDLER ... PREV` .

Hay varias razones para usar la interfaz `HANDLER` en lugar de comandos `SELECT` normales:

- `HANDLER` es más rápido que `SELECT`:

  - Un objeto de tratamiento de motor de almacenamiento designado se reserva para `HANDLER ... OPEN`. El objeto se reúsa para posteriores comandos `HANDLER` para esa tabla; no necesita reinicializarse para cada una.

  - Hay menos parseo.

  - No hay sobrecarga del chequeo de consultas ni optimizador.

  - La tabla no tiene que estar bloqueada entre peticiones.

  - La interície del handler no tiene que propocionar una vista de los datos consistente (por ejemplo, se permiten dirty reads), así que el motor puede usar optimización que `SELECT` no permite.

- `HANDLER` hace mucho más fácil portar aplicaciones que usen una interfaz tipo `ISAM` a MySQL.

- `HANDLER` le permite consultar una base de datos de forma difícil o imposible de realizar con `SELECT`. La interfície de `HANDLER` es una forma más natural de consultar los datos cuando se trabaja con aplicaciones que proporcionan una interfaz de usuario interactiva a la base de datos.

### 13.2.4. Sintaxis de `INSERT`

    INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

O:

    INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

O:

    INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

`INSERT` inserta nuevos registros en una tabla existente. Las formas `INSERT ... VALUES` y `INSERT ... SET` del comando insertan registros basados en valores explícitamente especificados. La forma `INSERT ... SELECT` inserta registros seleccionados de otra tabla o tablas. `INSERT ... SELECT` se discute en Sección 13.2.4.1, “Sintaxis de `INSERT ... SELECT`”.

`tbl_name` es la tabla en que los registros deben insertarse. Las columnas para las que el comando proporciona valores pueden especificarse como sigue:

- La lista de nombres de columna o la cláusula `SET` indican las columnas explícitamente.

- Si no especifica la lista de columnas para `INSERT ... VALUES` o `INSERT ... SELECT`, los valores para cada columna en la tabla deben proporcionarse en la lista `VALUES` o por el `SELECT`. Si no sabe el orden de las columnas en la tabla, use `DESCRIBE `tbl_name`` para encontrarlo.

Los valores de columna pueden darse de distintos modos:

- Si no está ejecutando el modo estricto, cualquier columna que no tenga un valor asignado explícitamente recibe su valor por defecto (explícito o implícito). Por ejemplo, si especifica una lista de columnas que no nombra todas las columnas en la tabla, las no nombradas reciben sus valores por defecto. Los valores por defecto asignados se describen en Sección 13.1.5, “Sintaxis de `CREATE TABLE`”. Consulte Sección 1.7.6.2, “Restricciones (constraints) sobre datos inválidos”.

  Si quiere que un comando `INSERT` genere un error a no ser que especifique explícitamente valores para todas las columnas que no tienen un valor por defecto, debe usar modo `STRICT` . Consulte Sección 5.3.2, “El modo SQL del servidor”.

- Use `DEFAULT` para asignar a una columna explícitamente su valor por defecto. Esto hace más fácil escribir comandos `INSERT` que asignan valores a todas las columnas excepto unas pocoas, ya que le permite evitar la escritura de una lista de valores `VALUES` incompleta. De otro modo, tendría que escribir la lista de los nombres de columna correspondientes a cada valor en la lista `VALUES` .

  En MySQL 5.0, puede usar `DEFAULT(`col_name`)` como forma más general que puede usarse en expresiones para producir un valor por defecto de una columna.

- Si la lista de columnas y la lista `VALUES` están vacías, `INSERT` crea un registro con cada conjunto de columnas con sus valores por defecto:

      mysql> INSERT INTO tbl_name () VALUES();

  En modo `STRICT` obtendrá un error si una columna no tiene un valor por defecto. De otro modo, MySQL usará el valor implícito para cualquier columna sin un valor explícito por defecto definido.

- Puede especificar una expresión `expr` para proporcionar un valor de columna. Esto puede involucar convesión de tipos si el tipo de la expresión no coincide con el tipo de la columna, y la conversión de un valor dado puede resultar en distintos valores insertados dependiendo del tipo de columna. Por ejmplo, insertar la cadena `'1999.0e-2'` en una columna `INT`, `FLOAT`, `DECIMAL(10,6)`, o `YEAR` resulta en los valores `1999`, `19.9921`, `19.992100`, y `1999` insertados, respectivamente. La razón de que el valor almacenado en las columnas `INT` y `YEAR` sea `1999` es que la conversión cadena-a-entero consulta sólo el trozo de la parte inicial de la cadena que se puede considerar como un entero válido o año. Para las columnas de coma flotante o punto fijo, la conversión cadena-a-coma-flotante considera la cadena entera un valor válido.

  Una expresión `expr` puede referirse a cualquier columna que se haya asignado antes en una lista de valores. Por ejemplo, puede hacer esto porque el valor para `col2` se refiere a `col1`, que se ha asignado préviamente:

      mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

  Pero lo siguiente no es legal, ya que el valor para `col1` se refiere a `col2`, que se asigna tras `col1`:

      mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);

  Una excepción involucra a columnas que contienen valores `AUTO_INCREMENT` . Como el valor `AUTO_INCREMENT` se genera tras otras asignaciones de valores, cualquier referencia a una columna `AUTO_INCREMENT` en la asignación retorna un 0.

El comando `INSERT` soporta los siguientes modificadores:

- Si usa la palabra `DELAYED`, el servidor pone el registro o registros a ser insertados en un búffer, y el cliente realizando el comando `INSERT DELAYED` puede continuar. Si la tabla está en uso, el servidor trata los registros. Cuando la tabla se libera, el servidor comienza a insertar registros, chequeando periódicamente para ver si hay alguna petición de lectura para la tabla. Si la hay, la cola de registros retardados se suspende hasta que la tabla se libera de nuevo. Consulte Sección 13.2.4.2, “Sintaxis de `INSERT DELAYED`”.

- Si usa la palabra `LOW_PRIORITY` , la ejecución de `INSERT` se retrasa hasta que no hay otros clientes leyendo de la tabla. Esto incluye a otros clientes que comiencen a leer mientras que los clientes existentes están leyendo, y meintras el comando `INSERT LOW_PRIORITY` está en espera. Es posible, por lo tanto, para un cliente que realice un comando `INSERT LOW_PRIORITY` esperar durante mucho tiempo (o incluso para siempre) en un entorno de muchas lecturas. (Esto es un contraste de `INSERT DELAYED`, que deja al cliente continuar. Consulte Sección 13.2.4.2, “Sintaxis de `INSERT DELAYED`”.) Tenga en cuenta que `LOW_PRIORITY` no debe usarse normalmente con tablas `MyISAM` y que hacerlo deshabilita inserciones concurrentes. Consulte Sección 14.1, “El motor de almacenamiento `MyISAM`”.

- Si especifica `HIGH_PRIORITY`, deshabilita el efecto de la opción `--low-priority-updates` si el servidor se arrancó con esa opción. Hace que las insecionces concurrentes no se usen.

- Los valores afectados por un `INSERT` pueden usarse usando la función `mysql_affected_rows()` de la API de C. Consulte Sección 24.3.3.1, “`mysql_affected_rows()`”.

- Si usa la palabra `IGNORE` en un comando `INSERT` , los errores que ocurren mientras se ejecuta el comando se tratan como advertencias. Por ejemplo, sin `IGNORE`, un registro que duplique un índice `UNIQUE` existente o valor `PRIMARY KEY` en la tabla hace que un error de clave duplicada en el comando se aborte. Con `IGNORE`, el registro todavía no se inserta, pero no se muestra error. Las conversionse de datos dispararían errores y abortarían el comando si no se sepecificara `IGNORE` . Con `IGNORE`, los valores inválidaos se ajustan al valor más cercano y se insertan; las advertencias se producen pero el comando no se aborta. Puede determinar con la función `mysql_info()` de la API de C cuántos registros se insertan realmente en la tabla.

Si especifica `ON DUPLICATE KEY UPDATE`, y un registro se inerta que haría que un valor duplicado en un índice `UNIQUE` o `PRIMARY KEY`, se realiza un `UPDATE` del antiguo registro. Por ejemplo, si la columna `a` se declara como `UNIQUE` y contiene el valor `1`, los siguientes dos comandos tienen efectos idénticos:

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
    -> ON DUPLICATE KEY UPDATE c=c+1;

    mysql> UPDATE table SET c=c+1 WHERE a=1;

El valor de registros afectados es 1 si el registros se inserta como un nuevo registro y 2 si un valor existente se actualiza.

Nota: Si la columna `b` es única, el `INSERT` sería equivalente a este comando `UPDATE` :

    mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

Si `a=1 OR b=2` se cumple para varios registros, sólo un registro se actualiza. En general, debería intentar evitar usar una cláusula `ON DUPLICATE KEY` en tablas con claves únicas múltiples.

MySQL 5.0 permite el uso de la función `VALUES(col_name)` en la cláusula `UPDATE` que se refiere a los valores de columna de la porción `INSERT` del comando `INSERT ... UPDATE` . En otras palabras, `VALUES(col_name)` en la cláusula `UPDATE` se refiere al valor de `col_name` que se insertarían, no ocurre conflicto de clave duplicada. Esta función es especialmente útil en inserciones de múltiples registros. La función `VALUES()` tiene sentido sólo en comandos `INSERT ... UPDATE` y retorna `NULL` de otro modo.

Ejemplo:

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
    -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

Este comando es idéntico a los siguientes dos comandos:

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
    -> ON DUPLICATE KEY UPDATE c=3;
    mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
    -> ON DUPLICATE KEY UPDATE c=9;

Cuando usa `ON DUPLICATE KEY UPDATE`, la opción `DELAYED` se ignora.

Puede encontrar el valor usado para una columna `AUTO_INCREMENT` usando la función SQL `LAST_INSERT_ID()` . Desde la API C, use la función `mysql_insert_id()` . Sin embargo, debe tener en cuenta que las dos funciones no siempre se comportan idénticamente. El comportamiento de comandos `INSERT` respecto a columnas `AUTO_INCREMENT` se discute en Sección 12.9.3, “Funciones de información” y Sección 24.3.3.34, “`mysql_insert_id()`”.

Si usa un comando `INSERT ... VALUES` con listas de múltiples valores o `INSERT ... SELECT`, el comando retorna una cadena de información en este formato:

    Records: 100 Duplicates: 0 Warnings: 0

`Records` indica el número de registros procesados por el comando. (Este no es necesariamente el número de registros realmente insertados, ya que `Duplicates` puede ser distinto a cero.) `Duplicates` indica el número de registros que no pueden insertarse ya que duplicarían algunos valores de índice únicos existentes `Warnings` indicata el número de intentos para insertar valores de columna que fueron problemáticos por algo. Las advertencias pueden ocurrir bajo cualquiera de las siguientes condiciones:

- Insertar `NULL` en una columna que se ha declarado `NOT NULL`. Para comandos `INSERT` de múltiples columnas o comandos `INSERT INTO... SELECT`, la columna se asigna con el valor por defecto para el tipo de datos de la columna. Este es `0` para tipos numéricos, la cadena vacía (`''`) para tipos de cadenas, y el valor “cero” para tipos de fecha y hora. Los comandos `INSERT INTO ... SELECT` se tratan del mismo modo que inserciones de múltiples registros porque el servidor no examina el resultado del `SELECT` para ver si retorna o no un único registro. (para un único registro `INSERT`, no hay ninguna advertencia cuando `NULL` se inserta en una columna `NOT NULL` . En lugar de eso, el comando falla con un error.)

- Poner en una columna numérica un valor fuera del rango de la columna. El valor se redondea al punto final del rango más cercano.

- Asigne un valor tal como `'10.34 a'` a una columna numérica. El texto final se elimina y la parte numérica se inserta. Si el valor de cadena no tiene parte inicial numérica, la columna se pone a `0`.

- Insertar una cadena en una columna de cadena (`CHAR`, `VARCHAR`, `TEXT`, o `BLOB`) que excede la maxima longitud de la columna. El valor se trunca a la máxima longitud de la columna.

- Insertar un valor en una columna de fecha u hora que es ilegal para el tipo de la columna. La columna se asigna con el valor cero apropiado para el tipo.

Si usa la API de C, la cadena de información puede obtenerse invocando la función `mysql_info()` Consulte Sección 24.3.3.32, “`mysql_info()`”.

#### 13.2.4.1. Sintaxis de `INSERT ... SELECT`

    INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

Con `INSERT ... SELECT`, puede insertar rápidamente varios registros en un atabla desde una o varias tablas.

Por ejemplo:

    INSERT INTO tbl_temp2 (fld_id)
    SELECT tbl_temp1.fld_order_id
    FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;

La siguiente condición sirve para un comando `INSERT ... SELECT` :

- En MySQL 5.0, especifique `IGNORE` explícitamente para ignorar registros que causarían violaciones de clave duplicada.

- No use `DELAYED` con `INSERT ... SELECT`.

- En MySQL 5.0, la tabla objetivo del comando `INSERT` puede aparecer en la cláusula `FROM` de la parte `SELECT` de la consulta. (Esto no era posible en algunas versiones antiguas de MySQL.)

- Las columnas `AUTO_INCREMENT` funcionan normalmente.

- Para asegurar que el log binario puede usarse para recrear las tablas originales, MySQL no permite inserciones concurrentes durante `INSERT ... SELECT`.

- Actualmente, no puede insertar en una tabla y seleccionar de la misma tabla en una subconsulta.

En las partes de valores de `ON DUPLICATE KEY UPDATE` puede referirse a una columna en otras tablas, mientras no use `GROUP BY` en la parte `SELECT` . Un efecto lateral es que debe calificar los nombres de columna no únicos en la parte de valores.

Puede usar `REPLACE` en lugar de `INSERT` para sobreescribir registros antiguos `REPLACE` es la contraparte de `INSERT IGNORE` en el tratamiento de nuevos registros que contienen valores de clave única que duplican registros antiguos: Los nuevos registros se usan para reemplazar los antiguos registros en lugar de descartarlos.

#### 13.2.4.2. Sintaxis de `INSERT DELAYED`

             INSERT DELAYED ...

La opción `DELAYED` para el comando `INSERT` es una extensión de MySQL del estándar SQL muy útil si tiene clientes que no pueden esperar a que se complete el `INSERT` . Este es un problema común cuando usa MySQL para loguear y periódicamente ejecuta comandos `SELECT` y `UPDATE` que tardan mucho tiempo en completarse.

Cuando un cliente usa `INSERT DELAYED`, obtiene un ok del servidor una vez, y el registro se encola para insertarse cuando la tabla no está en uso por otro flujo.

Otro beneficio de usar `INSERT DELAYED` es que las inserciones desde varios clientes se tratan juntas y se escriben en un bloque. Esto es mucho más rápido que realizar inserciones separadas.

Hay algunas restricciones al uso de `DELAYED`:

- En MySQL 5.0, `INSERT DELAYED` funciona sólo con tablas `MyISAM` y `MEMORY` . Para tablas `MyISAM` , si no hay bloques libres en medio del fichero de datos, se soportan comandos `SELECT` y `INSERT` concurrentes. Bajo estas circunstáncias, muy raramente necesitará usar `INSERT DELAYED` con `MyISAM`. Consulte Sección 14.1, “El motor de almacenamiento `MyISAM`” y Sección 14.3, “El motor de almacenamiento `MEMORY` (`HEAP`)”.

- En MySQL 5.0, `INSERT DELAYED` debe usarse sólo para comandos `INSERT` que especifiquen una lista de valores. El servidor ignora `DELAYED` para comandos `INSERT DELAYED ... SELECT` .

- El servidor ignora `DELAYED` para comandos `INSERT DELAYED ... ON DUPLICATE UPDATE`.

- Debido a que el comando retorna inmediatamente antes que los registros se inserten, no puede usar `LAST_INSERT_ID()` para obtener el valor `AUTO_INCREMENT` que el comando genera.

- Los registros `DELAYED` no son visibles por los comandos `SELECT` hasta que se hayan insertado realmente.

- `DELAYED` se ignora en la replicación de esclavos porque puede causar que el esclavo tenga distintos datos que el maestro.

Tenga en cuenta que los registros encolados se tratan sólo en memoria hasta que se insertan en la tabla. Esto significa que si termina mysqld forzadamente (por ejemplo, con `kill -9`) o si mysqld muere inesperadamente, cualquier registro encolado que no se escriba en disco se pierde.

A continuación se describe en detalle qué ocurre cuando usa la opción `DELAYED` con `INSERT` o `REPLACE`. En esta descriión, el “flujo” es el flujo que recibe un comando `INSERT DELAYED` y “handler” es el flujo que trata todos los comandos `INSERT DELAYED` para una tabla particular.

- Cuando un flujo ejecuta un comando `DELAYED` para una tabla, un flujo handler se crea para procesar todos los comandos `DELAYED` para la tabla, si tal handler no existía préviamente.

- El flujo chequea si el handler ha adquirido préviamente un bloqueo `DELAYED` ; si no, le dice al flujo handler que lo haga. El bloqueo `DELAYED` puede obtenerse incluso si otros flujos tienen el bloqueo `READ` o `WRITE` en la tabla. Sin embargo, el handler espera a todos los bloqueos `ALTER TABLE` o `FLUSH TABLES` para asegurar que la estructura de tabla está actualizada.

- El flujo ejecuta el comando `INSERT`, pero en lugar de escribir el registro en la tabla, pone una copia del registro final en una cola administrada por el flujo handler. Cualquier error de sintaxis es detectado por el flujo y se reporta al programa cliente.

- El cliente no puede obtener del servidor el número de registros duplicados o el valor `AUTO_INCREMENT` del registro resultante, ya que `INSERT` retorna antes que se complete la operación de inserción. (Si usa la API C, la función `mysql_info()` no retorna nada inteligible por la misma razón.)

- El log binario se actualiza por parte del flujo handler cuando el registro se inserta en la tabla. En caso de inserciones de múltiples registros, el log binario se actualiza cuando el primer registro se inserta.

- Tras cada `delayed_insert_limit` los registros se escriben, el handler chequea si algún comando `SELECT` todavía está pendiente. Si es así, les permite ejecutarse antes de continuar.

- Cuando el handler no tiene más registros en su cola, la tabla se desbloquea. Si no se reciben nuevos comandos `INSERT DELAYED` en `delayed_insert_timeout` segundos, el handler termina.

- Si más de `delayed_queue_size` registros están pendientes en una cola de handler específica, el flujo que pida el `INSERT DELAYED` espera hasta que haya espacio en la cola. Esto se hace para asegurar que mysqld no usa toda la memoria para la cola de memoria retrasada.

- El flujo handler se muestra en l lista de procesos MySQL con `delayed_insert` en la columna `Command` . Si muere si ejecuta un comando `FLUSH TABLES` o puede matarlo con `KILL thread_id`. Sin embargo, antes de salir, primero almacena todos los registros encolados en la tabla. Durante esta operación no acepta ningún nuevo comando `INSERT` de otros flujos. Si ejecuta un comando `INSERT DELAYED` a continuación, se crea un nuevo flujo handler.

  Tenga en cuenta que esto significa que comandos `INSERT DELAYED` tienen mayor prioridad que comandos `INSERT` normales si hay un handler `INSERT DELAYED` en ejecución. Otros comandos de actualización tienen que esperar hast que la cola `INSERT DELAYED` está vacía, alguien termine el flujo handler (con `KILL thread_id`), o alguien ejecute un `FLUSH TABLES`.

- Las siguientes variables de estado proporcionan información acerca de comandos `INSERT DELAYED` :

  Variable de estado | Significado
  `Delayed_insert_threads` | Número de flujos handler
  `Delayed_writes` | Número de registros escritos con `INSERT DELAYED`
  `Not_flushed_delayed_rows` | Número de registros esperando a ser escritos

  Puede ver estas variables ejecutando un comando `SHOW STATUS` o mysqladmin extended-status.

Tenga en cuenta que `INSERT DELAYED` es más lento que un `INSERT` normal si la tabla no está en uso. También hay una sobrecarga adicional para el servidor debido a que tiene que tratar un flujo separado para cada tabla en que haya registros retardados. Esto significa que debe usar `INSERT DELAYED` sólo cuando esté realmente seguro que lo necesita.

### 13.2.5. Sintaxis de `LOAD DATA INFILE`

    LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
        [REPLACE | IGNORE]
        INTO TABLE tbl_name
        [FIELDS
            [TERMINATED BY 'string']
            [[OPTIONALLY] ENCLOSED BY 'char']
            [ESCAPED BY 'char' ]
        ]
        [LINES
            [STARTING BY 'string']
            [TERMINATED BY 'string']
        ]
        [IGNORE number LINES]
        [(col_name_or_user_var,...)]
        [SET col_name = expr,...)]

El comando `LOAD DATA INFILE` lee registros desde un fichero de texto a una tabla a muy alta velocidad. El nombre de fichero debe darse como una cadena literal.

Para más información acerca de la eficiencia de `INSERT` contra `LOAD DATA INFILE` y acelerar `LOAD DATA INFILE`, consulte Sección 7.2.14, “Velocidad de la sentencia `INSERT`”.

En MySQL 5.0, el conjunto de carácteres indicado por la variable de sistema `character_set_database` se usa para interpretar la información en el fichero. `SET NAMES` y el valor de `character_set_client` no afecta la interpretación de la entrada.

Puede cargar ficheros de datos usando la utilidad mysqlimport ; opera enviando un comando `LOAD DATA INFILE` al servidor. La opción `--local` hace que mysqlimport lea ficheros de datos desde el equipo cliente. Puede especificar la opción `--compress` para obtener un mejor rendimiento en redes lentas si el cliente y el servidor soportan el protocolo comprimido. Consulte Sección 8.9, “El programa para importar datos mysqlimport”.

Si usa `LOW_PRIORITY`, la ejecución del comando `LOAD DATA` se retarda hasta que no haya más clientes leyendo de la tabla.

Si especifica `CONCURRENT` con una tabla `MyISAM` que satisfaga la condición para inserciones concurrentes (esto es, no contiene bloques libres en medio), entonces otros flujos pueden recibir datos desde la tabla mientras se ejecuta `LOAD DATA` . Usar esta opción afecta al rendimiento de `LOAD DATA` ligeramente, incluso si no hay otro flujo usando la tabla al mismo tiempo.

Si se especifica `LOCAL`, se interpreta respecto al cliente final de la conexión:

- Si se especifica `LOCAL`, el fichero se lee por parte del programa cliente en el equipo cliente y se envía al servidor. El fichero puede darse como una ruta completa para especificar su localización exacta. Si se da como ruta relativa, el nombre se interpreta relativo al directorio en que el cliente se inició.

- Si no se especifica `LOCAL` , el fichero no debe localizarse en el equipo sevidor y se lee directamente por el servidor.

Al localizar ficheros en el equipo servidor, el servidor usa las siguientes reglas:

- Si se da una ruta absoluta, el servidor usa la ruta como tal.

- Si se da una ruta relativa con uno o más componentes el servidor busca este fichero relativo al directorio de datos del servidor.

- Si se da un nombre de fichero sin componentes, el servidor busca el fichero en el directorio de base de datos de la base de datos por defecto.

Tenga en cuenta que estas reglas significan que un fichero llamado `./myfile.txt` se lee del directorio de datos del servidor, mientras que el mismo fichero llamado como `myfile.txt` se lee desde el directorio de base de datos de la base de datos por defecto. Por ejemplo, el siguiente comando `LOAD DATA` lee el fichero `data.txt` del directorio de la base de datos para `db1` porque `db1` es la base de datos actual, incluso si el comando carga explícitamente el fichero en una tabla en la base de datos `db2`:

    mysql> USE db1;
    mysql> LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;

Tenga en cuenta que las rutas de windows se especifican usando barras en lugar de antibarras. Si usa barras, debe doblarlas.

Por razones de seguridad, al leer ficheros de texto localizados en el servidor, los ficheros deben residir en el directorio de la base de datos o ser leíbles por todo el mundo. Además, para usar `LOAD DATA INFILE` en ficheros del servidor, debe tener el permiso `FILE` .

Consulte Sección 5.6.3, “Privilegios de los que provee MySQL”.

Usar `LOCAL` es un poco más lento que dejar al servidor acceder al fichero directamente, porque el contenido del fichero debe enviarse por la conexión desde el cliente al servidor . Por otra parte, no necesita el permiso `FILE` para cargar ficheros locales.

En MySQL 5.0, `LOCAL` funciona sólo si su servidor y su cliente lo tienen activado. Por ejemplo, si mysqld se arranca con `--local-infile=0`, entonces `LOCAL` no funciona. Consulte Sección 5.5.4, “Cuestiones relacionadas con la seguridad y `LOAD DATA LOCAL`”.

Si necesita `LOAD DATA` para leer desde un pipe, puede usar la siguiente técnica (aquí cargamos el listado del directorio `/` en una tabla):

    mkfifo /mysql/db/x/x
    chmod 666 /mysql/db/x/x
    find / -ls > /mysql/db/x/x
    mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

Las palabaras `REPLACE` y `IGNORE` controlan el tratamiento de registros de entrada que duplican registros existentes en claves únicas.

Si especifica `REPLACE`, los registros de entrada reemplazan registros existentes (en otras palabras, los registros que tienen el mismo valor para una clave primaria o única que un registro existente). Consulte Sección 13.2.6, “Sintaxis de `REPLACE`”.

Si especifica `IGNORE`, los registros de entrada que dupliquen un registro existente en una clave única se ignoran. Si no especifica ninguna opción, el comportamiento depende de si la palabra `LOCAL` se ha especificado o no. Sin `LOCAL`, ocurre un error cuando se encuentra un valor de clave duplicado, y el resto del fichero de texto se ignora. Con `LOCAL`, el comportamiento por defecto es el mismo que si se especifica `IGNORE`, esto es porque el servidor no tiene forma de parar la transmisión del fichero en medio de la operación.

Si quiere ignorar restricciones de clave foránea durante la operación de carga, puede realizar un comando `SET FOREIGN_KEY_CHECKS=0` antes de ejecutar `LOAD DATA`.

Si usa `LOAD DATA INFILE` en una tabla vacía `MyISAM` , todos los índices no únicos se crean en batch separados (como para `REPAIR TABLE`). Esto hace `LOAD DATA INFILE` mucho más rápido cuando tiene varios índices. Normalmente esto es muy rápido, pero en algunos casos extromos, puede crear los índices incluso más rápido desactivándolos con `ALTER TABLE ... DISABLE KEYS` antes de cargar el fichero en la tabla y usar `ALTER TABLE ... ENABLE KEYS` para recrear los índices tras cargar el fichero. Consulte Sección 7.2.14, “Velocidad de la sentencia `INSERT`”.

`LOAD DATA INFILE` es el complemento de `SELECT ... INTO OUTFILE`. (Consulte Sección 13.2.7, “Sintaxis de `SELECT`”.) Para escribir datos de una tabla en un fichero use `SELECT ... INTO OUTFILE`. Para leer el fichero de nuevo en una tabla, use `LOAD DATA INFILE`. La sintaxis de las cláusulas `FIELDS` y `LINES` es la misma para ambos. Ambas son opcionales, pero `FIELDS` debe preceder a `LINES` si se especifican ambas.

Si especifica una cláusula `FIELDS` , cada una de sus subcláusulas (`TERMINATED BY`, `[OPTIONALLY] ENCLOSED BY`, y `ESCAPED BY`) también es opcional, excepto que debe especificar al menos una de ellas.

Si no especifica una cláusula `FIELDS`, por defecto es como si hubiera escrito esto:

           FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

Si no especifica una cláusula `LINES`, por defecto es como si hubiera escrito esto:

           LINES TERMINATED BY '\n' STARTING BY ''

En otras palabras, por defecto `LOAD DATA INFILE` actúa como sigue al leer la entrada:

- Busca delimitadores de línea como nuevas líneas.

- No ignora ningún prefijo de línea.

- Rompe las líneas en campos con los tabuladores.

- No espera campos entrecomillados dentro de ningún carácter delimitador.

- Interpreta las ocurrencias de tabuladores, nuevas líneas o '`\`' precedidas por '`\`' como carácteres literales que son parte de valores de campos.

Por defecto `SELECT ... INTO OUTFILE` actúa como sigue al escribir la salida:

- Escribe tabuladores entre campos.

- No entrecomilla los campos.

- Usa '`\`' para escapar las instancias de tabuladores, nuevas líneas o '`\`' que ocurren entre valores de campos.

- Escribe nuevas líneas al final de las líneas.

Tenga en cuenta que para escribir `FIELDS ESCAPED BY '\\'`, debe escribir dos antibarras para que se interprete como una única antibarra.

Nota: Si ha generado el fichero de texto en un sistema Windows , puede tener que usar `LINES TERMINATED BY '\r\n'` para leer correctamente el fichero, ya que los programas de Windows típicamente usan dos carácteres como terminadores de línea . Algunos programas como WordPad, pueden usar `\r` como terminador de línea al escribir ficheros. Para leer tales ficheros, use `LINES TERMINATED BY '\r'`.

Si todas las líneas que quiere leer tienen un prefijo común que quiere ignorar, puede usar `LINES STARTING BY '`prefix_string`'` para ignorar el prefijo (y cualquier cosa antes del mismo). Si una línea no incluye el prefijo, la línea entera se ignora. Nota `prefix_string` puede ocurrir en medio de una línea.

Ejemplo:

    mysql> LOAD DATA INFILE '/tmp/test.txt'
    -> INTO TABLE test LINES STARTING BY "xxx";

Con esto puede leer en un fichero que contenga algo como:

    xxx"row",1
    something xxx"row",2

Y obtener los datos `("row",1)` y `("row",2)`.

La opción `IGNORE `number` LINES` puede usarse para ignorar líneas al inicio del fichero. Por ejemplo, puede usar `IGNORE 1 LINES` para ignorar una cabecera inicial que contenga los nombres de las columnas:

    mysql> LOAD DATA INFILE '/tmp/test.txt'
    -> INTO TABLE test IGNORE 1 LINES;

Cuando usa `SELECT ... INTO OUTFILE` junto con `LOAD DATA INFILE` para escribir datos desde una base de datos en un fichero y luego lee datos del fichero de nuevo en la base de datos, las opciones de tratamiento de fichero y de línea para ambos comandos deben coincidir. De otro modo, `LOAD DATA INFILE` no interpreta los contenidos del fichero correctamente. Suponga que usa `SELECT ... INTO OUTFILE` para escribir un fichero con campos delimitados por comas:

    mysql> SELECT * INTO OUTFILE 'data.txt'
    ->          FIELDS TERMINATED BY ','
    ->          FROM table2;

Para leer el fichero delimitado por comas, el comando correcto sería:

    mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY ',';

Si en lugar de esto trata de leer en el fichero con el comando mostrado aquí, no funcionaría porque le dice a `LOAD DATA INFILE` que busque tabuladores entre campos:

    mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
    ->           FIELDS TERMINATED BY '\t';

El resultado esperado es que cada línea de entrada se interprete como un único campo.

`LOAD DATA INFILE` puede usarse para leer ficheros obtenidos de fuentes externas. Por ejemplo, un fichero en formato dBASE tiene campos separados por comas y entrecomillados por comillas dobles. Si las líneas en el fichero se terminan con nuevas líneas, el comando mostrado aquí ilustra las opciones de campo y línea que debería usar para cargar el fichero:

    mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
    ->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    ->           LINES TERMINATED BY '\n';

Cualquiera de las opciones de tratamiento de campo o línea pueden especificarse como una cadena vacía (`''`). Si no está vacía, los valores `FIELDS [OPTIONALLY] ENCLOSED BY` y `FIELDS ESCAPED BY` deben ser un único carácter. Los valores `FIELDS TERMINATED BY`, `LINES STARTING BY`, y `LINES TERMINATED BY` pueden tener más de un carácter . Por ejemplo, para escribir líneas terminadas por parejas de retorno de carro y nueva línea, o para leer un fichero conteniendo tales líneas, especifique una cláusula `LINES TERMINATED BY '\r\n'` .

Para leer un fichero que contenga bromas separadas por líneas consistentes de `%%`, puede hacer lo siguiente

    mysql> CREATE TABLE jokes
    ->     (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->     joke TEXT NOT NULL);
    mysql> LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
    ->     FIELDS TERMINATED BY ''
    ->     LINES TERMINATED BY '\n%%\n' (joke);

`FIELDS [OPTIONALLY] ENCLOSED BY` controla el entrecomillado de los campos. Para la salida (`SELECT ... INTO OUTFILE`), si omite la palabra `OPTIONALLY`, todos los campos se delimitan por el carácter `ENCLOSED BY`. Un ejemplo de tal salida (usando coma como el delimitador de campo) se muestra aquí:

    "1","a string","100.20"
    "2","a string containing a , comma","102.20"
    "3","a string containing a \" quote","102.20"
    "4","a string containing a \", quote and comma","102.20"

Si especifica `OPTIONALLY`, el carácter `ENCLOSED BY` se usa sólo para delimitar valores en columnas que tienen datos de cadenas (tales como `CHAR`, `BINARY`, `TEXT`, o `ENUM`):

    1,"a string",100.20
    2,"a string containing a , comma",102.20
    3,"a string containing a \" quote",102.20
    4,"a string containing a \", quote and comma",102.20

Tenga en cuenta que la ocurrencias del carácter `ENCLOSED BY` dentro de un campo se escapan mediante un prefijo del carácter `ESCAPED BY`. También tenta en cuenta que si especifica un valor `ESCAPED BY` vacío, es posible generar salida que no puede leerse correctamente con `LOAD DATA INFILE`. Por ejemplo, la salida precedente tendría la siguiente apariencia si el carácter de escape estuviera vacío. Observe que el segundo campo en la cuarta línea contiene una coma siguiendo la delimitación, que (erróneamente) parece que termine el campo:

    1,"a string",100.20
    2,"a string containing a , comma",102.20
    3,"a string containing a " quote",102.20
    4,"a string containing a ", quote and comma",102.20

Para entrada, el carácter `ENCLOSED BY` , si está presente, se elimina del final de los valores de campos . (Esto es cierto se especifique `OPTIONALLY` o no; `OPTIONALLY` no tiene efecto en la interpretación de la entrada.) Las ocurrencias del carácter `ENCLOSED BY` prececdidas por el carater `ESCAPED BY` se interpretan como parte del campo actual.

Si el campo comienza con el carácter `ENCLOSED BY` , las instancias del mismo se reorganizan como terminadores del campo sólo si van seguidas por el campo o la secuencia `TERMINATED BY` . Para evitar ambigüedad, las ocurrencias del carácter `ENCLOSED BY` dentro de un campo se pueden doblar y se interpretan como una única instancia del carácter. Por ejemplo, si se especifica `ENCLOSED BY '"'` , la delimitación se trata como se muestra aquí:

    "The ""BIG"" boss"  -> The "BIG" boss
    The "BIG" boss      -> The "BIG" boss
    The ""BIG"" boss    -> The ""BIG"" boss

`FIELDS ESCAPED BY` controla cómo escribir o leer carácteres especiales. Si el carácter `FIELDS ESCAPED BY` no está vacío, se usa como prefijo para los siguientes carácteres de salida:

- El carácter `FIELDS ESCAPED BY`

- El carácter `FIELDS [OPTIONALLY] ENCLOSED BY`

- El primer carácter de los valores `FIELDS TERMINATED BY` y `LINES TERMINATED BY`

- ASCII `0` (lo que realmente se escribe a continuación del carácter de escape es '`0`' en ASCCI, no un byte con valor cero)

Si el carácter `FIELDS ESCAPED BY` está vacío, no se escapan carácteres y `NULL` se muestra como `NULL`, no `\N`. Probablemente no es una buena idea especificar un carácter de escape vacío, particularmente si los valores de campos en sus datos contienen cualquiera de los carácteres en la lista dada.

Para entrada, si el carácter `FIELDS ESCAPED BY` no está vacío, las ocurrencias del mismo se eliminan y el siguiente carácter se toma literalmente como parte del campo. Las excepciones son un '`0`' escapado o '`N`' (por ejemplo, `\0` o `\N` si el carácter de escape es '`\`'). Estas secuencias se interpretan como ASCII NUL (un byte con valor cero) y `NULL`. Las reglas para tratamiento de `NULL` se describen posteriormente.

Para más infomación de la sintaxis de escape '`\`' consulte Sección 9.1, “Valores literales”.

En ciertos casos, las opciones de tratamiento de campos y línea interactúan:

- Si `LINES TERMINATED BY` es una cadena vacío y `FIELDS TERMINATED BY` no está vacío, las líneas se terminan con `FIELDS TERMINATED BY`.

- Si los valores `FIELDS TERMINATED BY` y `FIELDS ENCLOSED BY` están vacíois (`''`), se usa un formato fijo de registro (no delimitado). Con este formato, no se usan delimitadores entre campos (pero puede tener un terminador de línea). En su lugar, los valores de columna se escriben y leen usando los anchos de muestra de las columnas. Por ejemplo, si una columna se declara como `INT(7)`, los valores para la columna se escriben usando campos de siete carácteres. En la entrada, los valores para la columna se obtienen leyendo siete carácteres.

  `LINES TERMINATED BY` se usa para separar líneas. Si una línea no contiene todos los campos, el resto de columnas se asignan con sus valores por defecto. Si no tiene un terminador de línea, debe asignarlo a `''`. En este caso, el fichero de texto debe contener todos los campos para cada registro.

  El formato fijo de registro también afecta al tratamiento de valores `NULL`, como se describe posteriormente. Tenga en cuenta que el formato de tamaño fijo no funciona si está usando un conjunto de carácteres multi byte.

El tratamiento de valores `NULL` varía en función de las opciones `FIELDS` y `LINES` en uso:

- Para los valores `FIELDS` y `LINES` por defecto, `NULL` se escribe como `\N` para la salida, y `\N` para la entrada se lee como `NULL` (considerando que el carácter `ESCAPED BY` es '`\`').

- Si `FIELDS ENCLOSED BY` no está vacílo, un campo que contenga el literal `NULL` como valor se lee como el valor `NULL` . Esto difiere de la palabra `NULL` delimitada por carácteres `FIELDS ENCLOSED BY` , que se lee como la cadena `'NULL'`.

- Si `FIELDS ESCAPED BY` está vacío, `NULL` se escribe como la palabra `NULL`.

- Con formato fijo de registro (lo que ocurre cuando `FIELDS TERMINATED BY` y `FIELDS ENCLOSED BY` están vacíos), `NULL` se escribe como una cadena vacía. Teng en cuenta que esto hace que ambos valores `NULL` y cadenas vacías en la tabla sean indistinguibles cuando se escriben en el fichero ya que ambos se escriben como cadenas vacías. Si necesita distinguir entre ambos al leer del fichero, no debe usar el formato de registro fijo.

Algunos casos no son soportados por `LOAD DATA INFILE`:

- Registros de tamaño fijo (`FIELDS TERMINATED BY` y `FIELDS ENCLOSED BY` ambos vacíos) y columnas `BLOB` o `TEXT` .

- Si especifica un separador que es igual o prefijo de otro, `LOAD DATA INFILE` no será capaz de interpretar la entrada correctamente. Por ejemplo, la siguiente cláusula `FIELDS` causaría problemas:

        FIELDS TERMINATED BY '"' ENCLOSED BY '"'

- Si `FIELDS ESCAPED BY` está vacío, un valor que contenga una ocurrencia de `FIELDS ENCLOSED BY` o `LINES TERMINATED BY` seguido por el valor `FIELDS TERMINATED BY` causa que `LOAD DATA INFILE` pare de leer un campo o línea demasiado rápido. Esto ocurre porque `LOAD DATA INFILE` no puede determinar apropiadamente dónde acaba el campo o línea.

El siguiente ejemplo carga todas las columnas de la tabla `persondata` :

    mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Por defecto, cuando no se proporciona una lista al final de un comando `LOAD DATA INFILE`, las líneas de entrada se espera que contengan un campo para cada columna de la tabla. Si quiere cargar sólo algunas columnas de una tabla, especifique una lista de columnas:

    mysql> LOAD DATA INFILE 'persondata.txt'
    ->           INTO TABLE persondata (col1,col2,...);

Debe especificar una lista de columnas si el orden de los campos del fichero de entrada difiere del orden de las columnas en la tabla. De otro modo, MySQL no puede decir cómo hacer coincidir los campos de entrada con las columnas de la tabla.

Antes de MySQL 5.0.3, la lista de columnas debe contener sólo nombres de columnas en la tabla que se carga, y la cláusula `SET` no se soporta. Desde MySQL 5.0.3, la lista de columnas puede contener nombres de columna o variables y la cláusula `SET` se soporta. Esto le permite asignar valores de entrada a variables de usuario, y luego realizar transformaciones on estos valores antes de asignar los resultados a las columnas.

Las variables de usuario en la cláusula `SET` puede usarse de distintos modos. El siguiente ejemplo usa la primera columna en el fichero de datos directamente para el valor de `t1.column1`, y asigna la segunda columna a una variable de usuario que está sujeta a una operación de división antes de ser usada por el valor de `t2.column2`:

    LOAD DATA INFILE 'file.txt'
      INTO TABLE t1
      (column1, @var1)
      SET column2 = @var1/100;

La cláusula `SET` puede usarse para proporcionar valores no derivados del fichero de entrada. Los siguientes comandos actualizan `column3` con la fecha y hora actuales:

    LOAD DATA INFILE 'file.txt'
      INTO TABLE t1
      (column1, column2)
      SET column3 = CURRENT_TIMESTAMP;

También puede descartar un valor de entrada asignándolo a una variable de usuario y no asignando la variable a una columna de tabla:

    LOAD DATA INFILE 'file.txt'
      INTO TABLE t1
      (column1, @dummy, column2, @dummy, column3);

El uso de la lista de columnas/variables y la cláusula `SET` está sujeto a las siguientes restricciones:

- Las asignaciones en la cláusula `SET` deben tener sólo nombres de columna en el lado izquierdo del operador de asignación.

- Puede usar subconsultas en la parte derecha de la asignación de `SET`. Una subconsulta que retorne un valor a ser asignado a otra coluimna sólo puede ser una subconsulta escalar. Además, no puede usar una subconsulta para seleccionar desde la tabla que se está cargando.

- Las líneas ignoradas por un cláusula `IGNORE` no se procesan por parta de la lista de columnas/variables o por la cláusula `SET` .

- Las variables de usuario no pueden usarse al cargar datos con formato de registo ya que las variables de usuario no tienen un ancho de muestra.

Al procesar una línea de entrada, `LOAD DATA` la divide en campos y usa los valores según la lista de columnas/ variables y la cláusula `SET` , si están presentes. A continuación se inserta el registro resultante en la tabla. Si hay disparadores `BEFORE INSERT` o `AFTER INSERT` para la tabla, se activan antes o después de insertar el registro, respectivamente.

Si una línea de entrada tiene demasiados campos, los campos extra se ignoran y el número de advertencias se incrementa.

Si una línea de entrada no tiene suficientes campos, las columnas de la tabla que no tienen entrada adquieren su valor por defecto. Los valores por defecto se describen en Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

Un valor de campo vacío se interpreta de forma distinta que si el valor no está presente:

- Para tipos de cadenas, la columna adquiere la cadena vacía.

- Para tipos numéricos, la columna recibe el valor `0`.

- Para tipos de fecha y hora, la columna obtiene el valor “cero” apropiado para el tipo. Consulte Sección 11.3, “Tipos de fecha y hora”.

Estos son los mismos valores que resultan si asigna una cadena vacía explícitamente a un tipo de cadena de carácteres, numérico o de fecha u hora en un comando `INSERT` o `UPDATE` statement.

Las columnas `TIMESTAMP` obtienen la fecha y hora actuales sólo si hay un valor `NULL` para la columna (esto es, `\N`), o (para la primera columna `TIMESTAMP` únicamente) si se omite `TIMESTAMP` de la lista de campos cuando se especifica una.

`LOAD DATA INFILE` trata todas las entradas como cadenas, asi que no puede usar valores numéricos para columnas `ENUM` o `SET` del modo en que puede hacerlo con comandos `INSERT` . Todos los valores `ENUM` y `SET` deben especificarse como cadenas.

Cuando acaba el comando `LOAD DATA INFILE`, retorna una cadena de información con el siguiente formato:

    Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Si usa la API de C, puede obtener información acerca del comando mediante la función `mysql_info()`. Consulte Sección 24.3.3.32, “`mysql_info()`”.

Las advertencias se producen bajo las mismas circunstancias que cuando los valores se insertan mediante el comando `INSERT` (consulte Sección 13.2.4, “Sintaxis de `INSERT`”), excepto que `LOAD DATA INFILE` también genera advertencias cuando hay muy pocos o demasiados campos en el registro de entrada. Las advertencias no se almacenan en ningún lugar; el número de las mismas puede usarse sólo como indicación de si todo ha ido bien.

En MySQL 5.0, puede usar `SHOW WARNINGS` para obtener una lista de las primeras `max_error_count` advertencias como información acerca de qué ha fallado. Consulte Sección 13.5.4.22, “Sintaxis de `SHOW WARNINGS`”.

### 13.2.6. Sintaxis de `REPLACE`

    REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...

O:

    REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...

O:

    REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...

`REPLACE` funciona exactamente como `INSERT`, excepto que si un valor de la tabla tiene el mismo valor que un nuevo registro para un índice `PRIMARY KEY` o `UNIQUE` , el antiguo registro se borra antes de insertar el nuevo. Consulte Sección 13.2.4, “Sintaxis de `INSERT`”.

Tenga en cuenta que a menos que la tabla tenga un índice `PRIMARY KEY`, o `UNIQUE` usar un comando `REPLACE` no tiene sentido. Es equivalente a `INSERT`, ya que no hay índice para determinar si un nuevo registro duplica otro.

Los valores para todas las columnas se toman de los valores especificados en el comando `REPLACE`. Cualquier columna no presente adquiere su valor por defecto, como ocurre con `INSERT`. No puede referirse a valores del registro actual y usarlos en el nuevo registro. Si usa un comando tal como `SET `col_name` = `col_name` + 1`, la referencia al nombre de columna en la parte derecha se trata como `DEFAULT(`col_name`)`, así que es equivalente a `SET `col_name` = DEFAULT(`col_name`) + 1`.

Para ser capaz de usar `REPLACE`, debe tener los permisos `INSERT` y `DELETE` para la tabla.

El comando `REPLACE` retorna un contador con el número de registros afectados. Esta es la suma de registros borrados e insertados. Si el contador es 1 para `REPLACE` de un único registro, se inserta un registro y no se borra ninguno. Si el contador es mayor que 1, uno o más registros se borraron antes de insertar el nuevo. Es posible para un único registro reemplazar más de un registro antiguo si la tabla contiene múltiples índices únicos y el nuevo registro duplica valores para distintos registros antiguos en distintos índices únicos.

El contador de registros afectados hace fácil determinar si `REPLACE` sólo añadió un registro o si también reemplazo alguno: Compruebe si el contador es 1 (añadido) o mayor (reemplazados).

Si usa la API de C, el contador de registros afectados puede obtenerse usando la función `mysql_affected_rows()`.

Actualmente, no puede reemplzar en una tabla y seleccionar de la misma en una subconsulta.

Aquí sigue en más detalle el algoritmo usado (también se usa con `LOAD DATA ... REPLACE`):

1. Intenta insertar el nuevo registro en la tabla

2. Mientras falle la inserción debido a error de clave duplicada por clave única o primaria:

   1. Borra de la tabla el registro conflictivo que tiene el valor de clave duplicada

   2. Intenta insertar de nuevo el registro en la tabla

### 13.2.7. Sintaxis de `SELECT`

    SELECT
    [ALL | DISTINCT | DISTINCTROW ]
    [HIGH_PRIORITY]
    [STRAIGHT_JOIN]
    [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
    [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [INTO OUTFILE 'file_name' export_options
    | INTO DUMPFILE 'file_name']
    [FROM table_references
    [WHERE where_definition]
    [GROUP BY {col_name | expr | position}
    [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_definition]
    [ORDER BY {col_name | expr | position}
    [ASC | DESC] , ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [FOR UPDATE | LOCK IN SHARE MODE]]

`SELECT` se usa para recibir registros seleccionados desde una o más tablas. MySQL 5.0 incluye soporte para comandos `UNION` y subconsultas. Consulte Sección 13.2.7.2, “Sintaxis de `UNION`” y Sección 13.2.8, “Sintaxis de subconsultas”.

- Cada `select_expr` indicata una columna que quiere recibir.

- `table_references` indicata la tabla o tablas desde la que recibir registros. Su sintaxis se describe en Sección 13.2.7.1, “Sintaxis de `JOIN`”.

- `where_definition` consiste en la palabra clave `WHERE` seguida por una expresión que indica la condición o condiciones que deben satisfacer los registros para ser seleccionados.

`SELECT` también puede usarse para recuperar registros computados sin referencia a ninguna tabla.

Por ejemplo:

    mysql> SELECT 1 + 1;
    -> 2

Todas las cláusulas usadas deben darse exactamente en el orden mostrado en la descripción de la sintaxis. Por ejemplo, una cláusula `HAVING` debe ir tras cualquier cláusula `GROUP BY` y antes de cualquier cláusula `ORDER BY` .

- Una `select_expr` puede tener un alias usando `AS alias_name`. El alias se usa como el nombre de columna de la expresión y puede usarse en cláusulas `GROUP BY`, `ORDER BY`, o `HAVING` . Por ejemplo:

      mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
      -> FROM mytable ORDER BY full_name;

  La palabra clave `AS` es opcional cuando se usa un alias para `select_expr`. El ejemplo precedente podría haberse escrito como:

      mysql> SELECT CONCAT(last_name,', ',first_name) full_name
      -> FROM mytable ORDER BY full_name;

  Como `AS` es opcional, puede ocurrir un sutil problema si olvida la coma entre dos expresiones `select_expr` : MySQL interpreta el segundo como un nombre de alias. Por ejemplo, en el siguiente comando, `columnb` se tata como un nombre de alias:

      mysql> SELECT columna columnb FROM mytable;

  Por esta razón, es una buena práctica poner los alias de columnas usando `AS`.

- No se permite usar un alias de columna en una cláusula `WHERE`, ya que el valor de columna puede no estar determinado cuando se ejecuta la cláusula `WHERE` . Consulte Sección A.5.4, “Problemas con alias de columnas”.

- La cláusula `FROM `table_references`` indica la tabla desde la que recibir registros. Si nombra más de una tabla, está realizando un join, Para información sobre la sintaxis de join, consulte Sección 13.2.7.1, “Sintaxis de `JOIN`”. Para cada tabla especificada, puede opcionalmente especificar un alias.

      tbl_name [[AS] alias]
      [[USE INDEX (key_list)]
      | [IGNORE INDEX (key_list)]
      | [FORCE INDEX (key_list)]]

  El uso de `USE INDEX`, `IGNORE INDEX`, `FORCE INDEX` para dar al optimizador pistas acerca de cómo escoger los indices se describe en Sección 13.2.7.1, “Sintaxis de `JOIN`”.

  En MySQL 5.0, puede usar `SET max_seeks_for_key=`value`` como alternativa para forzar a MySQL a que realice escaneos de claves en lugar de escaneos de tabla.

- Puede referirse a una tabla dentro de la base de datos actual como `tbl_name` (dentro de la base de datos actual) , o como `db_name.tbl_name` para referirse a una base de datos explícitamente. Puede referirse a una columna como `col_name`, `tbl_name.col_name`, o `db_name.tbl_name.col_name`. No necesita especificar un prefijo `tbl_name` o `db_name.tbl_name` para una referencia de columna a no ser que la referencia fuese ambígua. Consulte Sección 9.2, “Nombres de bases de datos, tablas, índices, columnas y alias” para ejemplos de ambigüedad que requieran las formas de referencia de columna más explícitas.

- En MySQL 5.0, puede especificar `DUAL` como nombre de tabla falso en siguaciones donde no se referencian tablas:

      mysql> SELECT 1 + 1 FROM DUAL;
      -> 2

  `DUAL` es una característica puramente de compatibilidad. Otros servidores requieren esta sintaxis.

- Una referencia de tabla puede tener un alias usando ``tbl_name` AS `alias_name`` o `tbl_name alias_name`:

      mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      ->     WHERE t1.name = t2.name;
      mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
      ->     WHERE t1.name = t2.name;

- En la cláusula `WHERE` , puede usar cualquiera de las funciones que soporta MySQL, escepto para funciones agregadas (resumen). Consulte Capítulo 12, Funciones y operadores.

- Las columnas seleccionadas para la salida pueden ser referidas en cláusulas `ORDER BY` y `GROUP BY` usando nombres de columnas, alias, o posiciones. Las posiciones de columnas son enteros y comienzan con 1:

      mysql> SELECT college, region, seed FROM tournament
      ->     ORDER BY region, seed;
      mysql> SELECT college, region AS r, seed AS s FROM tournament
      ->     ORDER BY r, s;
      mysql> SELECT college, region, seed FROM tournament
      ->     ORDER BY 2, 3;

  Para ordenar en orden inverso, añada la palabra clave `DESC` (descendiente) al nombre de la columna en la cláusula `ORDER BY` por la que está ordenando. Por defecto es orden ascendente; puede especificarse explícitamente usando la palabra clave `ASC`.

  El uso de posiciones de columna está obsoleto ya que la sintaxis se ha eliminado del estándar SQL.

- Si usa `GROUP BY`, los registros de salida se ordenan según las columnas `GROUP BY` como si tuviera un `ORDER BY` para las mismas columnas. MySQL 5.0 extiende la cláusula `GROUP BY` para que pueda especificar `ASC` y `DESC` tras las columnas nombradas en la cláusula:

      SELECT a, COUNT(b) FROM test_table GROUP BY a DESC

- MySQL extiende el uso de `GROUP BY` para permitir seleccionar campos que no se mencionan en la cláusula `GROUP BY` . Si no obtiene los resultados que espera de la consulta, por favor lea la descripción de `GROUP BY` en Sección 12.10, “Funciones y modificadores para cláusulas `GROUP BY`”.

- En MySQL 5.0, `GROUP BY` permite un modificador `WITH ROLLUP` . Consulte Sección 12.10.2, “Modificadores de `GROUP BY`”.

- La cláusula `HAVING` se aplica casi al final, justo antes de que los elementos se envíen al cliente, sin optimización. (`LIMIT` se aplica tras `HAVING`.)

  Antes de MySQL 5.0.2, una cláusula `HAVING` podía referirse a cualquier columna o alias nombrado en una `select_expr` en la lista `SELECT` o en subconsultas externas, y para funciones agregadas. Sin embargo, el estándar SQL requiere que `HAVING` debe referirse sólo a columnas en la cláusula `GROUP BY` o columnas usadas en funciones agregadas. Para acomodar ambos estándars SQL y el comportamiento específico de MySQL en que es capaz de referirse a columans en la lista `SELECT` , MySQL 5.0.2 y posteior permite a `HAVING` referirse a columnas en la lista `SELECT` , en la cláusula `GROUP BY` , en subconsultas externas y en funciones agregadas.

  Por ejemplo, el siguiente comando funciona en MySQL 5.0.2 pero produce un error en versiones aneriores:

      mysql> SELECT COUNT(*) FROM t GROUP BY col1 HAVING col1 = 2;

  Si la cláusula `HAVING` se refiere a una columna ambígua, se muestra una advertencia. En el siguiente comando, `col2` es ambíguo porque se usa tanto para un alias como para un nombre de columna:

      mysql> SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;

  Se da preferencia al comportamiento SQL estándar, así que si un nombre de columna `HAVING` se usa en un `GROUP BY` y como alias de columna en la lista de columnas de salida, se da preferencia a la columna en `GROUP BY` .

- No use `HAVING` para elementos que deban estar en la cláusula `WHERE` . Por ejemplo, no escriba lo siguiente:

      mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;

  Escriba esto en su lugar:

      mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;

- La cláusula `HAVING` puede referirse a funciones de agregación, algo que no puede hacer la cláusula `WHERE`:

      mysql> SELECT user, MAX(salary) FROM users
      ->     GROUP BY user HAVING MAX(salary)>10;

  (Esto no funciona en versiones antiguas de MySQL.)

- La cláusula `LIMIT` puede usarse para restringir el número de registros retornados por el comando `SELECT`. `LIMIT` tiene uno o dos argumentos numéricos, que deben ser enteros positivos (incluyendo cero).

  Con dos argumentos, el primer argumento especifica el desplazamiento del primer registro a retornar. El desplazamiento del registro inicial es 0 (no 1):

      mysql> SELECT * FROM table LIMIT 5,10;  # Retrieve rows 6-15

  Por compatibilidad con PostgreSQL, MySQL también soporta la sintaxis `LIMIT `row_count` OFFSET `offset``.

  Para recibir todos los registros de un desplazamiento hasta el final del conjunto de resultados, puede usar algún número grande para el segundo parámetro. Ete comando recibe todos los registros desde el 96th hasta el último:

      mysql> SELECT * FROM table LIMIT 95,18446744073709551615;

  Con un argumento, el valor especifica el número de registros a retornar desde el comienzo del conjunto de resultados:

      mysql> SELECT * FROM table LIMIT 5;     # Retrieve first 5 rows

  En otras palabras, `LIMIT n` es equivalente a `LIMIT 0,n`.

- La forma `SELECT ... INTO OUTFILE 'file_name'` de `SELECT` escribe los registros seleccionados en un fichero. El fichero se crea en el equipo servidor, así que debe tener el permiso `FILE` para usar esta sintaxis. El fichero no puede existir, que entre otras cosas evita destruir ficheros cruciales tales como `/etc/passwd` y tablas de la base de datos.

  El comando `SELECT ... INTO OUTFILE` existe principalmente para dejarle volcar una tabla rápidamente en la máquina servidor. Si quiere crear el fichero resultante en un equipo cliente distinto al equipo servidor, no puede usar `SELECT ... INTO OUTFILE`. En tal caso, debería usar algún comando como `mysql -e "SELECT ..." > file_name` en el equipo cliente para generar el fichero.

  `SELECT ... INTO OUTFILE` es el complemento de `LOAD DATA INFILE`; la sintaxis para la parte `export_options` del comando consiste en las mismas cláusulas `FIELDS` y `LINES` usadas con el comando `LOAD DATA INFILE` . Consulte Sección 13.2.5, “Sintaxis de `LOAD DATA INFILE`”.

  `FIELDS ESCAPED BY` controla cómo escribir carácteres especiales. Si el carácter `FIELDS ESCAPED BY` no está vacío, se usa como prefijo para los siguientes carácteres en la salida:

  - El carácter `FIELDS ESCAPED BY`

  - El carácter `FIELDS [OPTIONALLY] ENCLOSED BY`

  - El primer carácter de `FIELDS TERMINATED BY` y `LINES TERMINATED BY`

  - ASCII `0` (que se escribe siguiendo el carácter de escape ASCII '`0`', no un byte con valor cero)

  Si el carácter `FIELDS ESCAPED BY` está vacío, no hay ningún carácter de escape y `NULL` se muestra por salida como `NULL`, no `\N`. Probablemente no es buena idea especificar un carácter de escape vacío, particularmente si los valores de los campos de sus datos contienen cualqiuera de los carácteres en la lista dada.

  La razón de lo anterior es que debe escapar cualquier carácter `FIELDS TERMINATED BY`, `ENCLOSED BY`, `ESCAPED BY`, o `LINES TERMINATED BY` para ser capaz de volver a leer el fichero correctamente. ASCII `NUL` se escapa para hacer más fácil visualizarlo con algunos visores.

  El fichero resultante no tiene que estar conforme a la sintaxis SQL, así que nada más debe escaparse.

  Este es un ejemplo que produce un fichero en formato de valores separados por comas usado por varios programas:

      SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
      FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
      LINES TERMINATED BY '\n'
      FROM test_table;

- Si usa `INTO DUMPFILE` en lugar de `INTO OUTFILE`, MySQL escribe sólo un registro en el fichero, sin ninguna terminación de línea o columna y sin realizar ningún proceso de escape. Esto es útil si quiere almacenar un valor `BLOB` en un fichero.

- Nota: Cualquier fichero creado por `INTO OUTFILE` o `INTO DUMPFILE` es modificable por todos los usuarios en el equipo servidor. La razón es que el servidor MySQL no puede crear un fichero con un propietario distinto al usuario que está en ejecución (nunca debe ejecutar mysqld como `root` por esta y otras razones). El fichero debe ser modificable por todo el mundo para que pueda maminpular sus contenidos.

- Una cláusula `PROCEDURE` nombra a un procedimiento que debe procesar los datos en el conjunto de resultados. Para un ejemplo, consulte Sección 27.3.1, “Procedimiento Analyse”.

- Si usa `FOR UPDATE` en un motor de almacenamiento que usa bloqueo de páginas o registros, los registros examinados por la consulta se bloquean para escritura hasta el final de la transacción actual. Usar `LOCK IN SHARE MODE` crea un bloqueo compartido que evita a otras transacciones actualizar o borrar los registros examinados. Consulte Sección 15.10.5, “Bloquear lecturas `SELECT ... FOR UPDATE` y `SELECT ... LOCK IN SHARE MODE`”.

Tras la palabra clave `SELECT` , puede usar un número de opciones que afectan la operación del comando.

Las opciones `ALL`, `DISTINCT`, and `DISTINCTROW` especifican si deben retornarse los registros duplicados. Si no se da ninguna de estas opciones, por defecto es `ALL` (se retornan todos los registros coincidentes). `DISTINCT` y `DISTINCTROW` son sinónimos y especifican que los registros duplicados en el conjunto de resultados deben borrarse.

`HIGH_PRIORITY`, `STRAIGHT_JOIN`, y opciones que comiencen con `SQL_` son extensiones de MySQL al estándar SQL.

- `HIGH_PRIORITY` da a `SELECT` prioridad más alta que un comando que actualice una tabla. Debe usar esto sólo para consultas que son muy rápidas y deben realizarse una vez. Una consulta `SELECT HIGH_PRIORITY` que se realiza mientras la tabla está bloqueada para lectura se ejectua incluso si hay un comando de actualización esperando a que se libere la tabla.

  `HIGH_PRIORITY` no puede usarse con comandos `SELECT` que sean parte de una `UNION`.

- `STRAIGHT_JOIN` fuerza al optimizador a hacer un join de las tablas en el orden en que se listan en la cláusula `FROM` . Puede usarlo para acelerar una consulta si el optimizador hace un join con las tablas en orden no óptimo. Consulte Sección 7.2.1, “Sintaxis de `EXPLAIN` (Obtener información acerca de un `SELECT`)”. `STRAIGHT_JOIN` también puede usarse en la lista `table_references` . Consulte Sección 13.2.7.1, “Sintaxis de `JOIN`”.

- `SQL_BIG_RESULT` puede usarse con `GROUP BY` o `DISTINCT` para decir al optimizador que el conjunto de resultados tiene muchos registros. En este caso, MySQL usa directamente tablas temporales en disco si son necesarias con una clave en los elementos `GROUP BY` .

- `SQL_BUFFER_RESULT` fuerza a que el resultado se ponga en una tabla temporal . Esto ayuda a MySQL a liberar los bloqueos de tabla rápidamente y ayuda en casos en que tarda mucho tiempo en enviar el resultado al cliente.

- `SQL_SMALL_RESULT` puede usarse con `GROUP BY` o `DISTINCT` para decir al optimizador que el conjunto de resultados es pequeño. En este caso, MySQL usa tablas temporales rápidas para almacenar la tabla resultante en lugar de usar ordenación. En MySQL 5.0, esto no hará falta normalmente.

- `SQL_CALC_FOUND_ROWS` le dice a MySQL que calcule cuántos registros habrán en el conjunto de resultados, sin tener en cuenta ninguna cláusula `LIMIT`. El número de registros pueden encontrarse con `SELECT FOUND_ROWS()`. Consulte Sección 12.9.3, “Funciones de información”.

- `SQL_CACHE` le dice a MySQL que almacene el resultado de la consulta en la caché de consultas si está usando un valor de `query_cache_type` de `2` o `DEMAND`. Para una consulta que use `UNION` o subconsultas, esta opción afecta a cualquier `SELECT` en la consulta. Consulte Sección 5.12, “La caché de consultas de MySQL”.

- `SQL_NO_CACHE` le dice a MySQL que no almacene los resultados de consulta en la caché de consultas. Consulte Sección 5.12, “La caché de consultas de MySQL”. Para una consulta que use `UNION` o subconsultas esta opción afecta a cualquier `SELECT` en la consulta.

#### 13.2.7.1. Sintaxis de `JOIN`

MySQL soporta las siguientes sintaxis de `JOIN` para la parte `table_references` de comandos `SELECT` y `DELETE` y `UPDATE` de múltiples tablas:

    table_reference, table_reference
    table_reference [INNER | CROSS] JOIN table_reference [join_condition]
    table_reference STRAIGHT_JOIN table_reference
    table_reference LEFT [OUTER] JOIN table_reference join_condition
    table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
    { ON table_reference LEFT OUTER JOIN table_reference
    ON conditional_expr }
    table_reference RIGHT [OUTER] JOIN table_reference join_condition
    table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

`table_reference` se define como:

      tbl_name [[AS] alias]
      [[USE INDEX (key_list)]
      | [IGNORE INDEX (key_list)]
      | [FORCE INDEX (key_list)]]

`join_condition` se define como:

    ON conditional_expr | USING (column_list)

Generalmente no debería tener ninguna condición en la parte `ON` que se usa para restringir qué registros desea en el conjunto de resultados, pero en su lugar especificar esas condiciones en la cláusula `WHERE` . Hay excepciones a esta regla.

La sintaxis `{ OJ ... LEFT OUTER JOIN ...}` mostrada en la lista precedente existe sólo por compatibilidad con ODBC.

- Puede oner un alias en una referencia de tabla usando ``tbl_name` AS `alias_name`` o `tbl_name alias_name`:

      mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      ->        WHERE t1.name = t2.name;
      mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
      ->        WHERE t1.name = t2.name;

- El condicional `ON` es cualquier expresión condicional de la forma que puede usarse en una cláusula `WHERE` .

- Si no hay ningún registro coincidiente para la tabla de la derecha en la parte `ON` o `USING` en un `LEFT JOIN`, se usa un registro con todos las columnas a `NULL` para la tabla de la derecha. Puede usar este hecho para encontrar registros en una tabla que no tengan contraparte en otra tabla:

      mysql> SELECT table1.* FROM table1
      ->        LEFT JOIN table2 ON table1.id=table2.id
      ->        WHERE table2.id IS NULL;

  Este ejemplo encuentra todos los registros en `table1` con un valor `id` no presente en `table2` (esto es, todos los registros en `table1` sin registro correspondiente en `table2`). Esto asume que `table2.id` se declara `NOT NULL`. Consulte Sección 7.2.9, “Cómo optimiza MySQL los `LEFT JOIN` y `RIGHT JOIN`”.

- La cláusula `USING (`column_list`)` muestra una lista de columnas que deben existir en ambas tablas. Las siguientes dos cláusulas son semánticamente idénticas:

      a LEFT JOIN b USING (c1,c2,c3)
      a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3

- El `NATURAL [LEFT] JOIN` de dos tablas se define semánticamente equivalente a un `INNER JOIN` o `LEFT JOIN` con una cláusula `USING` que nombra todas las columnas que existen en ambas tablas.

- `INNER JOIN` y `,` (coma) son semánticamente equivalentes en la ausencia de una condicicón de join: ambos producen un producto Cartesiano entre las tablas especificadas (esto es, cada registro en la primera tabla se junta con cada registro en la segunda tabla).

- `RIGHT JOIN` funciona análogamente a `LEFT JOIN`. Para mantener el código portable entre bases de datos, se recomienda que use `LEFT JOIN` en lugar de `RIGHT JOIN`.

- `STRAIGHT_JOIN` es idéntico a `JOIN`, excepto que la tabla de la izquierda se lee siempre antes que la de la derecha. Esto puede usarse para aquéllos casos (escasos) en que el optimizador de join pone las tablas en orden incorrecto.

Puede proporcionar pistas de qué índice debe usar MySQL cuando recibe información de una tabla. Especificando `USE INDEX (key_list)`, puede decirle a MySQL que use sólo uno de los posibles índices para encontrar registros en la tabla. La sintaxis alternativa `IGNORE INDEX (key_list)` puede usarse para decir a MySQL que no use algún índice particular. Estos trucos son útiles si `EXPLAIN` muestra que MySQL está usando el índice incorrecto de la lista de posibles índices.

También puede usar `FORCE INDEX`, que actúa como `USE INDEX (`key_list`)` pero con la adición que un escaneo de tabla se asume como operación muy cara. En otras palabras, un escaneo de tabla se usa sólo si no hay forma de usar uno de los índices dados para encontrar registros en la tabla.

`USE KEY`, `IGNORE KEY`, y `FORCE KEY` son sinónimos de `USE INDEX`, `IGNORE INDEX`, y `FORCE INDEX`.

Nota: `USE INDEX`, `IGNORE INDEX`, y `FORCE INDEX` sólo afecta los índices usados cuando MySQL decide cómo encontrar registros en la tabla y cómo hacer el join. No afecta si un índice está en uso cuando se resuelve un`ORDER BY` o `GROUP BY`.

Algunos ejemplos de join:

    mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id;
    mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
    mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id);
    mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
    ->          LEFT JOIN table3 ON table2.id=table3.id;
    mysql> SELECT * FROM table1 USE INDEX (key1,key2)
    ->          WHERE key1=1 AND key2=2 AND key3=3;
    mysql> SELECT * FROM table1 IGNORE INDEX (key3)
    ->          WHERE key1=1 AND key2=2 AND key3=3;

Consulte Sección 7.2.9, “Cómo optimiza MySQL los `LEFT JOIN` y `RIGHT JOIN`”.

#### 13.2.7.2. Sintaxis de `UNION`

    SELECT ...
    UNION [ALL | DISTINCT]
    SELECT ...
    [UNION [ALL | DISTINCT]
    SELECT ...]

`UNION` se usa para combinar el resultado de un número de comandos `SELECT` en un conjunto de resultados.

Las columnas seleccionadas lisatadas en posiciones correspondientes de cada comando `SELECT` deben tener el mismo tipo. (Por ejemplo, la primera columna seleccionada por el primer comando debe tener el mismo tipo que la primer columna seleccionada por otros comandos.) Los nombres de columna usados por el primer comando `SELECT` se usan como nombres de columna para los resultados retornados.

Los comandos `SELECT` son comandos select normales, pero con las siguientes restricciones:

- Sólo el último comando `SELECT` puede usar `INTO OUTFILE`.

- `HIGH_PRIORITY` no puede usarse con comandos `SELECT` que sean parte de una `UNION`. Si lo especifica para el primer `SELECT`, no tiene efecto. Si lo especifica para cualquier `SELECT` posterior, aparece un error de sintaxis.

Si no usa la palabra clave `ALL` para `UNION`, todos los registros retornados son únicos, como si hubiera hecho un `DISTINCT` para el conjunto de resultados total. Si especifica `ALL`, obtiene todos los registros coincidentes de todos los comandos `SELECT` usados.

La palabra clave `DISTINCT` es una palabra opcional que no tiene efecto, pero se permite en la sintaxis como requiere el estándar SQL . (En MySQL, `DISTINCT` representa el comportamiento por defecto de una union.)

En MySQL 5.0, puede mezclar `UNION ALL` y `UNION DISTINCT` en la misma consulta. Tipos de `UNION` mezclados se tratan de forma que una unión `DISTINCT` sobreescribe cualquier unión `ALL` a su izquierda. Una unión `DISTINCT` puede producirse explícitamente usando `UNION DISTINCT` o implícitamente usando `UNION` sin palabra clave `DISTINCT` o `ALL` a continuación.

Si quiere usar una cláusula `ORDER BY` o `LIMIT` para ordenar o limitar el resultado `UNION` entero, ponga entre paréntesis los comandos `SELECT` individuales y ponga el `ORDER BY` o `LIMIT` tras el último. El siguiente ejemplo usa ambas cláusulas:

    (SELECT a FROM tbl_name WHERE a=10 AND B=1)
    UNION
    (SELECT a FROM tbl_name WHERE a=11 AND B=2)
    ORDER BY a LIMIT 10;

Este tipo de `ORDER BY` no puede usar referencias de columnas que incluyan un nombre de columna (esto es, nombres en formato `tbl_name.col_name` ). En su lugar, proporcione un alias de columna al primer comando `SELECT` y refiérase al alias en el `ORDER BY`, o a la columna en el `ORDER BY` usando su posición de columna. (Un alias es preferible porque el uso de la posición de la columna está obsoleto.)

Para aplicar `ORDER BY` o `LIMIT` a un `SELECT` individual, ponga la cláusula dentro de los paréntesis alrededor del `SELECT`:

    (SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
    UNION
    (SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

Los `ORDER BY` para comandos `SELECT` individuales entre paréntesis tienen efecto sólo al combinarlos con `LIMIT`. De otro modo, el `ORDER BY` se optimiza a parte.

En MySQL 5.0, los tipos y longitudes de las columnas en el conjunto de resultados de una `UNION` tienen en cuenta los valores recibidos por todos los comandos `SELECT`. Por ejemplo, considere lo siguiente:

    mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
    +---------------+
    | REPEAT('a',1) |
    +---------------+
    | a             |
    | bbbbbbbbbb    |
    +---------------+

(En alguna versión anterior de MySQL, el segundo registro se habría truncado a una longitud de 1.)

### 13.2.8. Sintaxis de subconsultas

Una subconsulta es un comando `SELECT` dentro de otro comando.

MySQL 5.0 soporta todas las formas de subconsultas y operaciones que requiere el estándar SQL, así como algunas características específicas de MySQL.

Aquí hay un ejemplo de subconsulta:

    SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

En este ejemplo, `SELECT * FROM t1 ...` es la consulta externa (o comando externo), y `(SELECT column1 FROM t2)` es la subconsulta. Decimos que la subconsulta está anidada dentro de la consulta exterior, y de hecho, es posible anidar subconsultas dentro de otras subconsultas hasta una profundidad considerable. Una subconsulta debe siempre aparecer entre paréntesis.

Las principales ventajas de subconsultas son:

- Permiten consultas estructuradas de forma que es posible aislar cada parte de un comando.

- Proporcionan un modo alternativo de realizar operaciones que de otro modo necesitarían joins y uniones complejos.

- Son, en la opinión de mucha gente, leíbles. De hecho, fue la innovación de las subconsultas lo que dio a la gente la idea original de llamar a SQL “Structured Query Language.”

Aquí hay un comando de ejemplo que muestra los puntos principales de la sintaxis de subconsultas como especifica el estándar SQL y soporta MySQL:

    DELETE FROM t1
    WHERE s11 > ANY
    (SELECT COUNT(*) /* no hint */ FROM t2
    WHERE NOT EXISTS
    (SELECT * FROM t3
    WHERE ROW(5*t2.s1,77)=
    (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
    (SELECT * FROM t5) AS t5)));

Una subconsulta puede retornar un escalar (un valor único), un registro, una columna o una tabla (uno o más registros de una o más columnas). Éstas se llaman consultas de escalar, columna, registro y tabla. Las subconsultas que retornan una clase particular de resultado a menudo pueden usarse sólo en ciertos contextos, como se describe en las siguientes secciones.

Hay pocas restricciones sobre los tipos de comandos en que pueden usarse las subconsultas. Una subconsulta puede contener cualquiera de las palabras claves o cláusulas que puede contener un `SELECT` ordinario: `DISTINCT`, `GROUP BY`, `ORDER BY`, `LIMIT`, joins, trucos de índices, constructores `UNION` , comentarios, funciones, y así.

Una restricción es que el comando exterior de una subconsulta debe ser: `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `SET`, o `DO`. Otra restricción es que actualmente no puede modificar una tabla y seleccionar de la misma tabla en la subconsulta. Esto se aplica a comandos tales como `DELETE`, `INSERT`, `REPLACE`, y `UPDATE`. Una discusión más comprensible de las restricciones en las subconsultas se da en Apéndice H, Restricciones en características de MySQL.

#### 13.2.8.1. La subconsulta, como un operador sobre valores escalares

En su forma más sencilla, una subconsulta es una subconsulta escalar que retorna un único valor. Una subconsulta escalar es un operando simple, y puede usarlo prácticamente en cualquier sitio en que un valor de columna o literal sea legal, y puede esperar que tenga las características que tienen todos los operandos: un tipo de datos, una longitud, una indicación de si puede ser `NULL`, etcétera. Por ejemplo:

    CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
    INSERT INTO t1 VALUES(100, 'abcde');
    SELECT (SELECT s2 FROM t1);

La subconsulta en este `SELECT` retorna un valor único (`'abcde'`) que tiene un tipo de datos `CHAR`, una longitud de 5, un conjunto de carácteres y una colación iguales a la que había por defecto cuando se realizó el `CREATE TABLE` , y una indicación que el valor en la columna puede ser `NULL`. De hecho, casi todas las consultas pueden ser `NULL`. Si la tabla usada en este ejemplo estuviese vacía, la tabla de la subconsulta sería `NULL`.

Hay algunos contextos en que una subconsulta escalar no se puede usar. Si un comando permite sólo un valor literal, no puede usar una subconsulta. Por ejemplo, `LIMIT` necesita argumentos enteros, y `LOAD DATA` necesita una cadena con un nombre de fichero. No puede usar subconsultas para proporcionar estos valores.

Cuando vea los ejemplos en las siguientes secciones que contengan el constructor `(SELECT column1 FROM t1)`, imagine que su própio código contiene construcciones mucho más diversas y complejas.

Por ejemplo, suponga que hacemos dos tablas:

    CREATE TABLE t1 (s1 INT);
    INSERT INTO t1 VALUES (1);
    CREATE TABLE t2 (s1 INT);
    INSERT INTO t2 VALUES (2);

Luego realice `SELECT`:

    SELECT (SELECT s1 FROM t2) FROM t1;

El resultado es `2` ya que hay un registro en `t2` que contiene una columna `s1` con un valor de `2`.

Una subconsulta escalar puede ser parte de una expresión. No olvide los paréntesis, incluso si la subconsulta es un operando que proporciona un argumento para una función. Por ejemplo:

    SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

#### 13.2.8.2. Uso de subconsultas en subconsultas

El uso más común de una subconsulta es de la forma:

    non_subquery_operand comparison_operator (subquery)

Donde `comparison_operator` es uno de estos operadores:

    =  >  <  >=  <=  <>

Por ejemplo:

      ... 'a' = (SELECT column1 FROM t1)

Hace tiempo el único sitio legal para una subconsulta fue en la parte derecha de la comparación, y puede encontrar algunos SGBDs que insistan en ello.

Aquí hay un ejemplo de una comparación común de subconsultas que no puede hacer mediante un join. Encuentra todos los valores en la tabla `t1` que son iguales a un valor máximo en la tabla `t2`:

    SELECT column1 FROM t1
    WHERE column1 = (SELECT MAX(column2) FROM t2);

Aquí hay otro ejemplo, que de nuevo es imposible de hacer con un join ya que involucra agregación para una de las tablas. Encuentra todos los registros en la tabla `t1` que contengan un valor que ocurre dos veces en una columna dada:

    SELECT * FROM t1 AS t
    WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);

Para una comparación realizada con uno de estos operadores, la subconsulta debe retornar un escalar, con la excepción que `=` puede usarse con subconsultas de registro. Consulte Sección 13.2.8.5, “Subconsultas de registro”.

#### 13.2.8.3. Subconsultas con `ANY`, `IN` y `SOME`

Sintaxis:

    operand comparison_operator ANY (subquery)
    operand IN (subquery)
    operand comparison_operator SOME (subquery)

La palabra clave `ANY` , que debe seguir a un operador de comparación, significa “return `TRUE` si la comparación es `TRUE` para `ANY` (cualquiera) de los valores en la columna que retorna la subconsulta.” Por ejemplo:

    SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

Suponga que hay un registro en una tabla `t1` que contiene `(10)`. La expresión es `TRUE` si la tabla `t2` contiene `(21,14,7)` ya que hay un valor `7` en `t2` que es menor que `10`. La expresión es `FALSE` si la tabla `t2` contiene `(20,10)`, o si la tabla `t2` está vacía. La expresión es `UNKNOWN` si la tabla `t2` contiene `(NULL,NULL,NULL)`.

La palabra `IN` es un alias para `= ANY`. Por lo tanto, estos dos comandos son lo mismo:

    SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
    SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

Sin embargo, `NOT IN` no es un alias para `<> ANY`, sino para `<> ALL`. Consulte Sección 13.2.8.4, “Subconsultas con `ALL`”.

La palabra `SOME` es un alias para `ANY`. Por lo tanto, estos dos comandos son el mismo:

    SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
    SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

El uso de la palabra `SOME` es raro, pero este ejemplo muestra cómo puede ser útil. Para la mayoría de gente, la frase en inglés “a is not equal to any b” significa “there is no b which is equal to a,” pero eso no es lo que quiere decir la sintaxis SQL. La sintaxis significa “there is some b to which a is not equal.” Usando `<> SOME` en su lugar ayuda a asegurar que todo el mundo entiende el significado de la consulta.

#### 13.2.8.4. Subconsultas con `ALL`

Sintaxis:

    operand comparison_operator ALL (subquery)

La palabra `ALL`, que debe seguir a un operador de comparación, significa “return `TRUE` si la comparación es `TRUE` para `ALL` todos los valores en la columna que retorna la subconsulta.” Por ejemplo:

    SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

Suponga que hay un registro en la tabla `t1` que contiene `(10)`. La expresión es `TRUE` si la tabla `t2` contiene `(-5,0,+5)` ya que `10` es mayor que los otros tres valores en `t2`. La expresión es `FALSE` si la tabla `t2` contiene `(12,6,NULL,-100)` ya que hay un único valor `12` en la tabla `t2` mayor que `10`. La expresión es `UNKNOWN` si la tabla `t2` contiene `(0,NULL,1)`.

Finalmente, si la tabla `t2` está vacía, el resultado es `TRUE`. Puede pensar que el resultado debería ser `UNKNOWN`, pero lo sentimos, es `TRUE`. Así, aunque extraño, el siguiente comando es `TRUE` cuando la tabla `t2` está vacía:

    SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

Pero este comando es `UNKNOWN` cuando la tabla `t2` está vacía:

    SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

Además, el siguiente comando es `UNKNOWN` cuando la tabla `t2` está vacía:

    SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

En general, las tablas con valores `NULL` y las tablas vacías son casos extremos. Al escribir código para subconsultas, siempre considere si ha tenido en cuenta estas dos posibilidades.

`NOT IN` es un alias para `<> ALL`. Por lo tanto, estos dos comandos son equivalentes:

    SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2);
    SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);

#### 13.2.8.5. Subconsultas de registro

La discusión en este punto ha sido entre subconsultas escalares o de columnas, esto es, subcolumnas que retornan un único valor o una columna de valores. Una subconsulta de registro es una variante de subconsulta que retorna un único registro y por lo tanto retorna más de un valor de columna. Aquí hay dos ejemplos:

    SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
    SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

Las consultas aquí son ambas `TRUE` si la tabla `t2` tiene un registro en que `column1 = 1` y `column2 = 2`.

Las expresiones `(1,2)` y `ROW(1,2)` a veces se llaman constructores de registros. Ambos son equivalentes. También son legales en otros contextos. Por ejemplo, los siguientes dos comandos son semánticamente equivalentes (aunque actualmente sólo puede optimizarse el segundo):

      SELECT * FROM t1 WHERE (column1,column2) = (1,1);
      SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

El uso normal de constructores de registros, sin embargo, es para comparaciones con subconsultas que retornan dos o más columnas. Por ejemplo, la siguiente consulta responde a la petición, “encuentra todos los registros en la tabla `t1` que también existen en la tabla `t2`”:

    SELECT column1,column2,column3
    FROM t1
    WHERE (column1,column2,column3) IN
    (SELECT column1,column2,column3 FROM t2);

#### 13.2.8.6. `EXISTS` y `NOT EXISTS`

Si una subconsulta no retorna ningún registro, entonces `EXISTS `subquery`` es `TRUE`, y `NOT EXISTS `subquery`` es `FALSE`. Por ejemplo:

    SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

Tradicionalmente, una subconsulta `EXISTS` comienza con `SELECT *`, pero puede comenzar con `SELECT 5` o `SELECT col1` o nada. MySQL ignora la lista `SELECT` en tales subconsultas, así que no hace distinción.

Para el ejemplo precedente, si `t2` contiene algún registro, incluso registros sólo con valores `NULL` entonces la condición `EXISTS` es `TRUE`. Este es un ejemplo poco probable, ya que prácticamente siempre una subconsulta `[NOT] EXISTS` contiene correlaciones. Aquí hay algunos ejemplos más realistas:

- ¿Qué clase de tienda hay en una o más ciudades?

      SELECT DISTINCT store_type FROM Stores
      WHERE EXISTS (SELECT * FROM Cities_Stores
      WHERE Cities_Stores.store_type = Stores.store_type);

- ¿Qué clase de tienda no hay en ninguna ciudad?

      SELECT DISTINCT store_type FROM Stores
      WHERE NOT EXISTS (SELECT * FROM Cities_Stores
      WHERE Cities_Stores.store_type = Stores.store_type);

- ¿Qué clase de tienda hay en todas las ciudades?

      SELECT DISTINCT store_type FROM Stores S1
      WHERE NOT EXISTS (
      SELECT * FROM Cities WHERE NOT EXISTS (
      SELECT * FROM Cities_Stores
      WHERE Cities_Stores.city = Cities.city
      AND Cities_Stores.store_type = Stores.store_type));

El último ejemplo es un doblemente anidado `NOT EXISTS` . Esto es, tiene una cláusula `NOT EXISTS` dentro de otra `NOT EXISTS`. Formalmente, responde a la pregunta “¿existe una ciudad con una tienda que no esté en `Stores`?” Sin embargo, es más fácil decir que un `NOT EXISTS` responde a la pregunta “¿es x `TRUE` para todo y?”

#### 13.2.8.7. Subconsultas correlacionadas

Una subconsulta correlacionada es una subconsulta que contiene una referencia a una tabla que también aparece en la consulta exterior. Por ejemplo:

    SELECT * FROM t1 WHERE column1 = ANY
    (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

Tenga en cuenta que la subconsulta contiene una referencia a una columna de `t1`, incluso aunque la cláusula `FROM` de la subconsulta no menciona una tabla `t1`. Por lo tanto, MySQL busca fuera de la subconsulta y encuentra `t1` en la consulta externa.

Suponga que la tabla `t1` contiene un registro en que `column1 = 5` y `column2 = 6`; mientras, la tabla `t2` contiene un registro en que `column1 = 5` y `column2 = 7`. La expresión `... WHERE column1 = ANY (SELECT column1 FROM t2)` sería `TRUE`, pero en este ejemplo, la cláusula `WHERE` dentro de la subconsulta es `FALSE` (ya que `(5,6)` no es igual a `(5,7)`), así que la subconsulta como un todo es `FALSE`.

Regla de visibilidad: MySQL evalúa desde dentro hacia fuera. Por ejemplo:

    SELECT column1 FROM t1 AS x
    WHERE x.column1 = (SELECT column1 FROM t2 AS x
    WHERE x.column1 = (SELECT column1 FROM t3
    WHERE x.column2 = t3.column1));

En este comando, `x.column2` debe ser una columna en la tabla `t2` ya que `SELECT column1 FROM t2 AS x ...` renombra `t2`. No hay una columna en la tabla `t1` porque `SELECT column1 FROM t1 ...` es una consulta externa que está demasiado fuera.

Para subconsultas en cláusulas `HAVING` o `ORDER BY` , MySQL busca nombres de columna en la lista de selección exterior.

Para ciertos casos, una subconsulta correlacionada es óptima. Por ejemplo:

    val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

De otro modo, son ineficientes y lentas. Reescribir la consulta como un join puede mejorar el rendimiento.

Las subconsultas correlatadas no pueden referirse a los resultados de funciones agregadas de la consulta exterior.

#### 13.2.8.8. Subconsultas en la cláusula `FROM`

Las subconsultas son legales en la cláusula `FROM` de un comando `SELECT`. La sintaxis que vería es:

    SELECT ... FROM (subquery) [AS] name ...

La cláusula `[AS] `name`` es obligatoria, ya que cada tabla en la cláusula `FROM` debe tener un nombre. Cualquier columna en la lista selecta de la `subquery` debe tener nombre único. Puede encontrar esta sintaxis descrita en este manual, dónde se usa el término “tablas derivadas.”

Asuma que tiene la tabla:

    CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

Aquí se muestra cómo usar una subconsulta en la cláusula `FROM` usando la tabla de ejemplo:

    INSERT INTO t1 VALUES (1,'1',1.0);
    INSERT INTO t1 VALUES (2,'2',2.0);
    SELECT sb1,sb2,sb3
    FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
    WHERE sb1 > 1;

Resultado: `2, '2', 4.0`.

Aquí hay otro ejemplo: suponga que quiere conocer la media de un conjunto de sumas para una tabla agrupada. Esto no funcionaría:

    SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

Sin embargo, esta consulta proporciona la información deseada:

    SELECT AVG(sum_column1)
    FROM (SELECT SUM(column1) AS sum_column1
    FROM t1 GROUP BY column1) AS t1;

Tenga en cuenta que el nombre de columna usado dentro de la subconsultas `(sum_column1)` se reconoce en la consulta exterior.

Las subconsultas en la cláusula `FROM` pueden retornar un escalar, columna, registro o tabla. De momento, las subconsultas en la cláusula `FROM` no pueden ser subconsultas correladas.

Las subconsultas en la cláusula `FROM` se ejecutan incluso para el comando `EXPLAIN` (esto es, se construyen las tablas temporales derivadas). Esto ocurre porque las consultas de niveles superiores necesitan información acerca de todas las tablas durante la fase de optimización.

#### 13.2.8.9. Errores en subconsultas

Hay algunos retornos de error nuevos que se aplican sólo a subconsultas. Esta sección los agrupa ya que revisarlos ayuda a recordar algunos puntos importantes.

- Número incorrecto de columnas de la subconsulta:

      ERROR 1241 (ER_OPERAND_COL)
      SQLSTATE = 21000
      Message = "Operand should contain 1 column(s)"

  Este error ocurre en casos como este:

      SELECT (SELECT column1, column2 FROM t2) FROM t1;

  Se permite usar una subconsulta que retorne múltiples columnas, si el propósito es la comparación. Consulte Sección 13.2.8.5, “Subconsultas de registro”. Sin embargo, en otros contextos, la subconsulta debe ser un operando escalar.

- Número incorrecto de registros de la subconsulta:

      ERROR 1242 (ER_SUBSELECT_NO_1_ROW)
      SQLSTATE = 21000
      Message = "Subquery returns more than 1 row"

  Este error ocurre de comandos en que la subconsulta retorna más de un registro. Considere el siguiente ejemplo:

      SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

  Si `SELECT column1 FROM t2` retorna sólo un registro la consulta anterior funcionará. Si la subconsulta retorna más de un registro, ocurre el error 1242 . En ese caso, la consulta debe reescribirse como:

      SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);

- Tabla usada incorrectamente en la subconsulta:

      Error 1093 (ER_UPDATE_TABLE_USED)
      SQLSTATE = HY000
      Message = "You can't specify target table 'x'
      for update in FROM clause"

  Este error ocurre en casos como el siguiente:

      UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);

  Puede usar una subconsulta para asignaciones dentro del comando `UPDATE`, ya que las subconsultas son legales en los comandos `UPDATE` y `DELETE` así como en los `SELECT`. Sin embargo, no puede usar la misma tabla (en este caso la tabla `t1`) para la cláusula `FROM` de la subconsulta y el objetivo a actualizar.

Para motores transaccionales, el fallo de una subconsulta provoca que falle el comando entero. Para motores no transaccionales, las modificaciones de datos hechas antes de encontrar el error se preservan.

#### 13.2.8.10. Optimizar subconsultas

El desarrollo está en marcha, por lo que no hay trucos de optimización fiables a largo plazo. Algunos trucos interesantes que puede usar son:

- Use cláusulas de subconsulta que afecten al número u orden de los registros en la subconsulta. Por ejemplo:

      SELECT * FROM t1 WHERE t1.column1 IN
      (SELECT column1 FROM t2 ORDER BY column1);
      SELECT * FROM t1 WHERE t1.column1 IN
      (SELECT DISTINCT column1 FROM t2);
      SELECT * FROM t1 WHERE EXISTS
      (SELECT * FROM t2 LIMIT 1);

- Reemplace un join con una subconsulta. Por ejemplo, pruebe:

      SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
      SELECT column1 FROM t2);

  En lugar de:

      SELECT DISTINCT t1.column1 FROM t1, t2
      WHERE t1.column1 = t2.column1;

- Algunas subconsultas pueden transformarse en joins por compatibilidad con versiones anteriores de MySQL que no soportan subconsultas. Sin embargo, en algunos casos, incluso en MySQL 5.0, convertir una subconsulta en un join puede mejorar el rendimiento. Consulte Sección 13.2.8.11, “Re-escribir subconsultas como joins en versiones de MySQL anteriores”.

- Mueva las cláusulas desde fuera hacia dentro en la subconsulta. Por ejemplo , use esta consulta:

      SELECT * FROM t1
      WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);

  En lugar de:

      SELECT * FROM t1
      WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

  Otro ejemplo. Use esta consulta:

      SELECT (SELECT column1 + 5 FROM t1) FROM t2;

  En lugar de:

      SELECT (SELECT column1 FROM t1) + 5 FROM t2;

- Use una subconsulta de registro en lugar de una subconsulta correlacionada . Por ejemplo, use:

      SELECT * FROM t1
      WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);

  En lugar de:

      SELECT * FROM t1
      WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
      AND t2.column2=t1.column2);

- Use `NOT (a = ANY (...))` en lugar de `a <> ALL (...)`.

- Use `x = ANY (table containing (1,2))` en lugar de `x=1 OR x=2`.

- Use `= ANY` en lugar de `EXISTS`.

- Para subconsultas no correlacionadas que siempre retornan un registro, `IN` siempre es más lento que `=`. Por ejemplo, use esta consulta:

      SELECT * FROM t1 WHERE t1.col_name
      = (SELECT a FROM t2 WHERE b = some_const);

  En lugar de:

      SELECT * FROM t1 WHERE t1.col_name
      IN (SELECT a FROM t2 WHERE b = some_const);

Estos trucos pueden hacer que los programas vayan más rápidos o lentos. Usar recursos MySQL como la función `BENCHMARK()` es una buena idea para ver cuáles funcionan.

Algunas optimizaciones que realiza MySQL son:

- MySQL ejecuta subconsultas no correlacionadas sólo una vez. Use `EXPLAIN` para asegurar que una subconsulta dada realmente no está correlacionada.

- MySQL reescribe subconsultas `IN`, `ALL`, `ANY`, y `SOME` para aprovechar que las columnas de la lista de select de la subconsulta está indexada.

- MySQL reemplaza subconsultas de la siguiente forma con una función de búsqueda de índice, que `EXPLAIN` describe como tipo especial de join (`unique_subquery` o `index_subquery`):

      ... IN (SELECT indexed_column FROM single_table ...)

- MySQL mejora expresiones de la siguiente forma con una expresión que involucre `MIN()` o `MAX()`, a no ser que hayan involucrados valores `NULL` o conjuntos vacíos:

      value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)

  Por ejemplo, esta cláusula `WHERE`:

      WHERE 5 > ALL (SELECT x FROM t)

  puede tratarse por el optimizador como:

      WHERE 5 > (SELECT MAX(x) FROM t)

Hay un capítulo titulado “Cómo transforma las subconsultas MySQL” en el manual MySQL Internals Manual. Puede obtener este documento descargando el paquete fuente MySQL y buscando un fichero llamado `internals.texi` en el directorio `Docs` .

#### 13.2.8.11. Re-escribir subconsultas como joins en versiones de MySQL anteriores

En versiones prévias de MySQL (anteriores a la MySQL 4.1), sólo se soportaban consultas anidadas de la forma `INSERT ... SELECT ...` y `REPLACE ... SELECT ...`. Este no es el caso en MySQL 5.0, pero es cierto que hay a veces otras formas de testear la pertenencia a un grupo de valores. También es cierto que en algunas ocasiones, no es sólo posible reescribir una consulta sin una subconsulta, sino que puede ser más eficiente hacerlo que usar subconsultas. Una de las técnicas disponibles es usar el constructor `IN()` :

Por ejemplo, esta consulta:

    SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

Puede reescribirse como:

    SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;

Las consultas:

    SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
    SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

Pueden reescribirse usando `IN()`:

    SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
    WHERE table2.id IS NULL;

Un `LEFT [OUTER] JOIN` puede ser más rápido que la subconsulta equivalente ya que el servidor puede ser capaz de optimizarlo mejor — este es un hecho no específico de MySQL Server . Antes de SQL-92, los outer joins no existían, así que las subconsultas eran el único modo de hacer ciertas cosas. Hoy, MySQL Server y otros sistemas de bases de datos ofrecen un ámplio rango de tipos de outer join.

MySQL Server soporta comandos `DELETE` para múltiples tablas que pueden usarse para borrar registros basándose en la información de una tabla o de varias al mismo tiempo. Los comandos `UPDATE` para múltiples tablas también se soportan en MySQL 5.0.

### 13.2.9. Sintaxis de `TRUNCATE`

    TRUNCATE TABLE tbl_name

`TRUNCATE TABLE` vacía una tabla completamente. Lógicamente, esto es equivalente a un comando `DELETE` que borre todos los registros, pero hay diferencias prácticas bajo ciertas circunstáncias.

Para `InnoDB` antes de la versión 5.0.3, `TRUNCATE TABLE` se mapea a `DELETE`, así que no hay diferencia. A partir de MySQL/InnoDB-5.0.3, está disponible `TRUNCATE TABLE` muy rápido. La operación se mapea a `DELETE` si hay restricciones de clave foránea que referencien la tabla.

Para otros motores, `TRUNCATE TABLE` difiere de `DELETE FROM` en los siguientes puntos en MySQL 5.0:

- Las operaciones de truncado destruyen y recrean la tabla, que es mucho más rápido que borrar registros uno a uno.

- Las operaciones de truncado no son transaccionales; ocurre un error al intentar un truncado durante una transacción o un bloqueo de tabla.

- No se retorna el número de registros borrados.

- Mientras el fichero de definición de la tabla ``tbl_name`.frm` sea válido, la tabla puede recrearse como una vacía con `TRUNCATE TABLE`, incluso si los ficheros de datos o de índice se han corrompido.

- El tratador de tablas no recuerda el último valor `AUTO_INCREMENT` usado, pero empieza a contar desde el principio. Esto es cierto incluso para `MyISAM` y `InnoDB`, que normalmente no reúsan valores de secuencia.

`TRUNCATE TABLE` es una extensión de Oracle SQL adoptada en MySQL.

### 13.2.10. Sintaxis de `UPDATE`

Sintaxis para una tabla:

    UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT row_count]

Sintaxis para múltiples tablas:

    UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

El comando `UPDATE` actualiza columnas en registros de tabla existentes con nuevos valores. La cláusula `SET` indica qué columna modificar y los valores que puede recibir. La cláusula `WHERE` , si se da, especifica qué registros deben actualizarse. De otro modo, se actualizan todos los registros. Si la cláusula `ORDER BY` se especifica, los registros se actualizan en el orden que se especifica. La cláusula `LIMIT` es el límite de registros a actualizar.

El comando `UPDATE` soporta los siguientes modificadores:

- Si usa la palabra clave `LOW_PRIORITY` , la ejecución de `UPDATE` se retrasa hasta que no haya otros clientes leyendo de la tabla.

- Si usa la palabra clave `IGNORE`, el comando de actualización no aborta incluso si ocurren errores durante la actualización. Los registros que presenten conflictos de clave duplicada no se actualizan. Los registros cuyas columnas se actualizan a valores que provocarían errores de conversión de datos se actualizan al valor válido más próximo.

Si accede a una columna de `tbl_name` en una expresión, `UPDATE` usa el valora ctual de la columna. Por ejemplo, el siguiente comando pone la columna `age` a uno más que su valor actual:

    mysql> UPDATE persondata SET age=age+1;

Las asignaciones `UPDATE` se avalúna de izquierda a derecha. Por ejemplo, el siguiente comando dobla la columna `age` y luego la incrementa:

    mysql> UPDATE persondata SET age=age*2, age=age+1;

Si pone en una columna el valor que tiene actualmente, MySQL se da cuenta y no la actualiza.

Si actualiza una columna declarada como `NOT NULL` con un valor `NULL`, la columna recibe el valor por defecto apropiado para el tipo de la columna y se incrementa el contador de advertencias. El valor por defecto es `0` para tipos numéricos, la cadena vacía (`''`) para tipos de cadena, y el valor “cero” para valores de fecha y hora.

`UPDATE` retorna el número de registros que se cambian. En MySQL 5.0, la función `mysql_info()` de la API de C retorna el número de registros coincidentes actualizados y el número de advertencias que ocurren durante el `UPDATE`.

Puede usar `LIMIT `row_count`` para restringir el alcance del `UPDATE`. Una cláusula `LIMIT` es una restricción de registros coincidentes. El comando para en cuanto encuentra `row_count` registos que satisfagan la cláusula `WHERE` , tanto si han sido cambiados como si no.

Si un comando `UPDATE` incluye una cláusula `ORDER BY`, los registros se actualizan en el orden especificado por la cláusula.

Puede realizar operaciones `UPDATE` que cubran varias tablas. La parte `table_references` lista las tablas involucradas en el join. Su sintaxis se describe ámpliamente en Sección 13.2.7.1, “Sintaxis de `JOIN`”. Aquí hay un ejemplo:

    UPDATE items,month SET items.price=month.price
    WHERE items.id=month.id;

Este ejemplo muestra un inner join usando el operador coma, pero los comandos `UPDATE` de múltiples tablas pueden usar cualquier tipo de join permitido en comandos `SELECT` tales como `LEFT JOIN`.

Nota: No puede usar `ORDER BY` o `LIMIT` con un `UPDATE` de múltiples tablas.

En MySQL 5.0, necesita el permiso `UPDATE` sólo para columnas referenciadas en un `UPDATE` de múltiples tablas que se actualizan realmente. Necesita sólo el permiso `SELECT` para algunas columnas que se leen pero no se modifican.

Si usa un comando `UPDATE` de múltiples tablas que involucren tablas `InnoDB` con restricciones de claves foráneas, el optimizador de MySQL puede procesar tablas en un orden distinto al de la relación padre/hijo. En este caso, el comando fall y hace un roll back. En su lugar, actualice una única tabla y confíen en las capacidades de `ON UPDATE` que proporciona `InnoDB` para que el resto de tablas se modifiquen acórdemente. Consulte Sección 15.6.4, “Restricciones (constraints) `FOREIGN KEY`”.

Actualmente, no puede actualizar una tabla y seleccionar de la misma en una subconsulta.

## 13.3. Sentencias útiles de MySQL

### 13.3.1. Sintaxis de `DESCRIBE` (Información acerca de las columnas)

    {DESCRIBE | DESC} tbl_name [col_name | wild]

`DESCRIBE` proporciona información acerca de columnas en una tabla. Es una abreviación de `SHOW COLUMNS FROM`. Desde MySQL 5.0.1, estos comandos también muestra información para vistas.

Consulte Sección 13.5.4.3, “Sintaxis de `SHOW COLUMNS`”.

`col_name` puede ser un nombre de columna, o una cadena con los carácteres de SQL '`%`' y '`_`' para obtener salida sólo para las columnas con nombres que coincidan con la cadena. No hay necesidad de delimitar la cadena con comillas a no ser que contenga espacios u otros carácteres especiales.

    mysql> DESCRIBE city;
    +------------+----------+------+-----+---------+----------------+
    | Field      | Type     | Null | Key | Default | Extra          |
    +------------+----------+------+-----+---------+----------------+
    | Id         | int(11)  |      | PRI | NULL    | auto_increment |
    | Name       | char(35) |      |     |         |                |
    | Country    | char(3)  |      | UNI |         |                |
    | District   | char(20) | YES  | MUL |         |                |
    | Population | int(11)  |      |     | 0       |                |
    +------------+----------+------+-----+---------+----------------+
    5 rows in set (0.00 sec)

La columna `Null` indica si pueden almacenarse los valores `NULL` , mostrando `YES` cuando se permiten valores `NULL`.

La columna `Key` indica si el campo está indexado. Un valor de `PRI` indica que el campo es parte de una clave primaria de tabla. `UNI` indica que el campo es parte de un índice `UNIQUE`. El valor `MUL` indica que se permiten múltiples ocurrencias de un valor dado dentro del campo.

Un campo puede designarse como `MUL` incluso si se usa un índice `UNIQUE` si se permiten valores `NULL` , ya que múltiples registros en un índice `UNIQUE` pueden tener un valor `NULL` si la columna no se declara `NOT NULL`. Otra causa para `MUL` en un índice `UNIQUE` es cuando dos columnas de un índice `UNIQUE` compuesto; mientras la combinación de las columnas sea única, cada columna puede tener múltiples ocurrencias de un valor dado. Tenga en cuenta que en un índice compuesto sólo el campo de más a la izquierda del índice tiene una entrada en la columna `Key` .

La columna `Default` indica el valor por defecto asignado al campo.

La columna `Extra` contiene cualquier información adicional disponible acerca de un campo dado. En nuestro ejemplo la columna `Extra` indica que la columna `Id` se creó con la palabra clave `AUTO_INCREMENT` .

Si los tipos de columna son distintos a los esperados según el comando `CREATE TABLE` , tenga en cuenta que a veces MySQL cambia los tipos de columa. Consulte Sección 13.1.5.1, “Cambios tácitos en la especificación de columnas”.

El comando `DESCRIBE` se proporciona por compatibilidad con Oracle.

Los comandos `SHOW CREATE TABLE` y `SHOW TABLE STATUS` proporcionan información acerca de tablas . Consulte Sección 13.5.4, “Sintaxis de `SHOW`”.

### 13.3.2. Sintaxis de `USE`

    USE db_name

El comando `USE `db_name`` le dice a MySQL que use la base de datos `db_name` como la base de datos por defecto para los comandos siguientes. Sigue siendo la base de datos por defecto hasta el final de la sesión o hasta que se realiza otro comando `USE` :

    mysql> USE db1;
    mysql> SELECT COUNT(*) FROM mytable;   # selects from db1.mytable
    mysql> USE db2;
    mysql> SELECT COUNT(*) FROM mytable;   # selects from db2.mytable

Hacer una base de datos particular la actual signfica que el comando `USE` no le imposibilita a acceder a tablas en otras bases de datos. El siguiente ejemplo accede a la tabla `author` desde la base de datos `db1` y a la tabla `editor` desde la base de datos `db2`:

    mysql> USE db1;
    mysql> SELECT author_name,editor_name FROM author,db2.editor
        ->        WHERE author.editor_id = db2.editor.editor_id;

El comando `USE` se proporciona por compatibilidad con Sybase.

## 13.4. Comandos transaccionales y de bloqueo de MySQL

### 13.4.1. Sintaxis de `START TRANSACTION`, `COMMIT` y `ROLLBACK`

Por defecto, MySQL se ejecuta con el modo autocommit activado. Esto significa que en cuanto ejecute un comando que actualice (modifique) una tabla, MySQL almacena la actualización en disco.

Si usa tablas transaccionales (como `InnoDB` o `BDB`), puede desactivar el modo autocommit con el siguiente comando:

    SET AUTOCOMMIT=0;

Tras deshabilitar el modo autocommit poniendo la variable `AUTOCOMMIT` a cero, debe usar `COMMIT` para almacenar los cambios en disco o `ROLLBACK` si quiere ignorar los cambios hechos desde el comienzo de la transacción.

Si quiere deshabilitar el modo autocommit para una serie única de comandos, puede usar el comando `START TRANSACTION`:

    START TRANSACTION;
    SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
    UPDATE table2 SET summary=@A WHERE type=1;
    COMMIT;

Con `START TRANSACTION`, autocommit permanece deshabilitado hasta el final de la transacción con `COMMIT` o `ROLLBACK`. El modo autocommit vuelve a su estado prévio.

`BEGIN` y `BEGIN WORK` se soportan como alias para `START TRANSACTION` para iniciar una transacción. `START TRANSACTION` es sintaxis SQL estándar y es la forma recomendada para iniciar una transacción ad-hoc . El comando `BEGIN` difiere del uso de la palabra clave `BEGIN` que comienza un comando compuesto `BEGIN ... END`. El último no comienza una transacción. Consulte Sección 19.2.7, “Sentencia compuesta `BEGIN ... END`”.

Puede comenzar una transacción así:

    START TRANSACTION WITH CONSISTENT SNAPSHOT;

La cláusula `WITH CONSISTENT SNAPSHOT` comienza una lectura consistente para motores de almacenamiento capaces de ello. Actualmente, esto se aplica sólo a `InnoDB`. El efecto es el mismo que realizar un `START TRANSACTION` seguido por un `SELECT` desde cualquier tabla `InnoDB` . Consulte Sección 15.10.4, “Lecturas consistentes que no bloquean”.

Comenzar una transacción provoca que se realice un `UNLOCK TABLES` implícito.

Tenga en cuenta que si no usa tablas transaccionales, cualquier cambio se almacena de golpe, a pesar del estado del modo autocommit .

Si realiza un comando `ROLLBACK` tras actualizar una tabla no transaccional dentro de una transacción, ocurre una advertencia `ER_WARNING_NOT_COMPLETE_ROLLBACK`. Los cambios en tablas transaccionales se deshacen, pero no los cambios en tablas no transaccionales.

Cada transacción se almacena en el log binario en un trozo, hasta `COMMIT`. Las transacciones que se deshacen no se loguean. (Exceción: Las modificaciones a tablas no transaccionales no pueden deshacerse. Si una transacción que se deshace incluye modificaciones a tablas no transaccionales, la transacción entera se loguea con un comando `ROLLBACK` al final para asegurar que las modificaciones a estas tablas se replican.) Consulte Sección 5.10.3, “El registro binario (Binary Log)”.

Puede cambiar el nivel de aislamiento para transacciones con `SET TRANSACTION ISOLATION LEVEL`. Consulte Sección 13.4.6, “Sintaxis de `SET TRANSACTION`”.

Deshacer puede ser una operación lenta que puede ocurrir sin que el usuario lo haya pedido explícitamente (por ejemplo, cuando ocurre un error). Debido a ello, `SHOW PROCESSLIST` en MySQL 5.0 muestra `Rolling back` en la columna `State`para la conexión durante rollbacks implícitos y explícitos (comando SQL `ROLLBACK`).

### 13.4.2. Sentencias que no se pueden deshacer

Algunos comandos no pueden deshacerse. En general, esto incluye comandos del lenguaje de definición de datos (DDL), tales como los que crean y borran bases de datos, los que crean, borran o alteran tablas o rutinas almacenadas.

Debe designar que sus transacciones no incluyan tales comandos. Si realiza un comando pronto en una transacción que no puede deshacerse, y luego un comando posterior falla, el efecto global de la transacción no puede deshacerse mediante un comando `ROLLBACK` .

### 13.4.3. Sentencias que causan una ejecución (commit) implícita

Cada uno de los comandos siguientes (y cualquier sinónimo de los mismos) terminan una transacción implícitamente, como si hubiera realizado un `COMMIT` antes de ejecutar el comando:

`ALTER TABLE` | `BEGIN` | `CREATE INDEX`
`CREATE TABLE` | `` | `CREATE DATABASE`
`DROP DATABASE` | `DROP INDEX` | `DROP TABLE`
`LOAD MASTER DATA` | `LOCK TABLES` | `RENAME TABLE`
`SET AUTOCOMMIT=1` | `START TRANSACTION` | `TRUNCATE TABLE`

`UNLOCK TABLES` también realiza un commit de una transacción si hay cualquier tabla bloqueada.

Las transacciones no pueden anidarse. Esto es una consecuencia del `COMMIT` implícito realizado por cualquier transacción actual cuando realiza un comando `START TRANSACTION` o uno de sus sinónimos.

### 13.4.4. Sintaxis de `SAVEPOINT` y `ROLLBACK TO SAVEPOINT`

    SAVEPOINT identifier
    ROLLBACK TO SAVEPOINT identifier

En MySQL 5.0, `InnoDB` soporta los comandos SQL `SAVEPOINT` y `ROLLBACK TO SAVEPOINT`.

El comando `SAVEPOINT` crea un punto dentro de una transacción con un nombre `identifier`. Si la transacción actual tiene un punto con el mismo nombre, el antiguo se borra y se crea el nuevo.

El comando `ROLLBACK TO SAVEPOINT` deshace una transacción hasta el punto nombrado. Las modificaciones que la transacción actual hace al registro tras el punto se deshacen en el rollback, pero `InnoDB` no libera los bloqueos de registro que se almacenaron en memoria tras el punto . (Tenga en cuenta que para un nuevo registro insertado, la información de bloqueo se realiza a partir del ID de transacción almacenado en el registro; el bloqueo no se almacena separadamente en memoria. En este caso, el bloqueo de registro se libera al deshacerse todo.) Los puntos creados tras el punto nombrado se borran.

Si un comando retorna el siguiente error, significa que no existe ningún punto con el nombre especificado:

    ERROR 1181: Got error 153 during ROLLBACK

Todos los puntos de la transacción actual se borran si ejecuta un `COMMIT`, o un `ROLLBACK` que no nombre ningún punto.

### 13.4.5. Sintaxis de `LOCK TABLES` y `UNLOCK TABLES`

    LOCK TABLES
        tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
        [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
    UNLOCK TABLES

`LOCK TABLES` bloquea tablas para el flujo actual. Si alguna de las tablas la bloquea otro flujo, bloquea hasta que pueden adquirirse todos los bloqueos. `UNLOCK TABLES` libera cualquier bloqueo realizado por el flujo actual. Todas las tablas bloqueadas por el flujo actual se liberan implícitamente cuando el flujo reliza otro `LOCK TABLES`, o cuando la conexión con el servidor se cierra.

Un bloqueo de tabla protege sólo contra lecturtas inapropoadas o escrituras de otros clientes. El cliente que tenga el bloqueo, incluso un bloqueo de lectura, puede realizar operaciones a nivel de tabla tales como `DROP TABLE`.

Tenga en cuenta lo siguiente a pesar del uso de `LOCK TABLES` con tablas transaccionales:

- `LOCK TABLES` no es una operación transaccional y hace un commit implícito de cualquier transacción activa antes de tratar de bloquear las tablas. También, comenzar una transacción (por ejemplo, con `START TRANSACTION`) realiza un `UNLOCK TABLES` implícito. (Consulte Sección 13.4.3, “Sentencias que causan una ejecución (commit) implícita”.)

- La forma correcta de usar `LOCK TABLES` con tablas transaccionales,como `InnoDB`, es poner `AUTOCOMMIT = 0` y no llamar a `UNLOCK TABLES` hasta que hace un commit de la transacción explícitamente. Cuando llama a `LOCK TABLES`, `InnoDB` internamente realiza su propio bloqueo de tabla, y MySQL realiza su propio bloqueo de tabla. `InnoDB` libera su bloqueo de tabla en el siguiente commit, pero para que MySQL libere su bloqueo de tabla, debe llamar a `UNLOCK TABLES`. No debe tener `AUTOCOMMIT = 1`, porque entonces `InnoDB` libera su bloqueo de tabla inmediatamente tras la llamada de `LOCK TABLES`, y los deadlocks pueden ocurrir fácilmente. (Tenga en cuenta que en MySQL 5.0, no adquirimos el bloqueo de tabla `InnoDB` en absoluto si `AUTOCOMMIT=1`, para ayudar a aplicaciones antiguas a envitar deadlocks.)

- `ROLLBACK` no libera bloqueos de tablas no transaccionales de MySQL.

Para usar `LOCK TABLES` en MySQL 5.0, debe tener el permiso `LOCK TABLES` y el permiso `SELECT` para las tablas involucradas.

La razón principal para usar `LOCK TABLES` es para emular transacciones o para obtener más velocidad al actualizar tablas. Esto se explica con más detalle posteriormente.

Si un flujo obtiene un bloqueo `READ` en una tabla, ese flujo (y todos los otros) sólo pueden leer de la tabla. Si un flujo obtiene un bloqueo `WRITE` en una tabla, sólo el flujo con el bloqueo puede escribir a la tabla. El resto de flujos se bloquean hasta que se libera el bloqueo.

La diferencia entre `READ LOCAL` y `READ` es que `READ LOCAL` permite comandos `INSERT` no conflictivos (inserciones concurrentes) se ejecuten mientras se mantiene el bloqueo. Sin embargo, esto no puede usarse si va a manipular los ficheros de base de datos fuera de MySQL mientras mantiene el bloqueo. Para tablas `InnoDB` , `READ LOCAL` esencialmente no hace nada: No bloquea la tabla. Para tablas `InnoDB` , el uso de `READ LOCAL` está obsoleto ya que una `SELECT` consistente hace lo mismo, y no se necesitan bloqueos.

Cuando usa `LOCK TABLES`, debe bloquear todas las tablas que va a usar en sus consultas. Mientras los bloqueos obtenidos con un comando `LOCK TABLES` están en efecto, no puede acceder a ninguna tabla que no estuviera bloqueada por el comando. Además, no puede usar una tabla bloqueada varias veces en una consulta --- use alias para ello. Tenga en cuenta que en este caso, debe tener un bloqueo separado para cada alias.

    mysql> LOCK TABLE t WRITE, t AS t1 WRITE;
    mysql> INSERT INTO t SELECT * FROM t;
    ERROR 1100: Table 't' was not locked with LOCK TABLES
    mysql> INSERT INTO t SELECT * FROM t AS t1;

Si sus consultas se refieren a una tabla que use un alias, debe bloquear la tabla que usa el mismo alias. No funciona bloquear la tabla sin especificar el alias:

    mysql> LOCK TABLE t READ;
    mysql> SELECT * FROM t AS myalias;
    ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

Si bloquea una tabla usando un alias, debe referirse a ella en sus consultas usando este alias:

    mysql> LOCK TABLE t AS myalias READ;
    mysql> SELECT * FROM t;
    ERROR 1100: Table 't' was not locked with LOCK TABLES
    mysql> SELECT * FROM t AS myalias;

`WRITE` bloquea normalmente teniendo una prioridad superior que `READ` al bloquear para asegurar que las actualizaciones se procesan en cuanto se puede. Esto significa que si un flujo obtiene un bloqueo `READ` y luego otro flujo pide un bloqueo `WRITE` , las peticiones de bloqueo `READ` posteriores esperan hasta que el flujo `WRITE` quita el bloqueo. Puede usar bloqueos `LOW_PRIORITY WRITE` para permitir a otros flujos que obtengan bloqueos `READ` mientras el flujo está en espera para el bloqueo `WRITE`. Debe usar bloqueos `LOW_PRIORITY WRITE` sólo si está seguro que habrá un momento sin flujos con bloqueos `READ` .

`LOCK TABLES` funciona como sigue:

1. Ordena todas las tablas a ser bloqueadas en un orden definido internamente. Desde el punto de vista del usuario, este orden es indefinido.

2. Si una tabla se bloquea con bloqueo de escritura y lecutra, pon el bloqueo de lectura antes del de escritura.

3. Bloquea una tabla cada vez hasta que el flujo obtiene todos los bloqueos.

Esta política asegura un bloqueo de tablas libre de deadlocks. Sin embargo hay otros puntos que debe tener en cuenta respecto a esta política:

Si está usando un bloqueo `LOW_PRIORITY WRITE` para una tabla, sólo significa que MySQL espera para este bloqueo particular hasta que no hay flujos que quieren un bloqueo `READ` . Cuando el flujo ha obtenido el bloqueo `WRITE` y está esperando para obtener un bloqueo para la siguiente tabla en la lista, todos los otros flujos esperan hasta que el bloqueo `WRITE` se libera. Si esto es un problema con su aplicación, debe considerar convertir algunas de sus tablas a transaccionales.

Puede usar `KILL` para terminar un flujo que está esperando para un bloqueo de tabla. Consulte Sección 13.5.5.3, “Sintaxis de `KILL`”.

Tenga en cuenta que no debe bloquear ninguna tabla que esté usando con `INSERT DELAYED` ya que en tal caso el `INSERT` lo realiza un flujo separado.

Normalmente, no tiene que bloquear tablas, ya que todos los comandos `UPDATE` son atómicos, ningún otro flujo puede interferir con ningún otro que está ejecutando comandos SQL . Hay algunos casos en que no debe bloquear tablas de ningún modo:

- Si va a ejecutar varias operaciones en un conjunto de tablas `MyISAM` , es mucho más rápido bloquear las tablas que va a usar. Bloquear tablas `MyISAM` acelera la inserción, las actualizaciones, y los borrados. Por contra, ningún flujo puede actualizar una tabla con un bloqueo `READ` (incluyendo el que tiene el bloqueo) y ningún flujo puede acceder a una tabla con un bloqueo `WRITE` distinto al que tiene el bloqueo.

  La razón que algunas operaciones `MyISAM` sean más rápidas bajo `LOCK TABLES` es que MySQL no vuelca la caché de claves para la tabla bloqueada hasta que se llama a `UNLOCK TABLES`. Normalmente, la caché de claves se vuelca tras cada comando SQL.

- Si usa un motor de almacenamiento en MySQL que no soporta transacciones, debe usar `LOCK TABLES` si quiere asegurarse que ningún otro flujo se ejecute entre un `SELECT` y un `UPDATE`. El ejemplo mostrado necesita `LOCK TABLES` para ejecutarse sin problemas:

      mysql> LOCK TABLES trans READ, customer WRITE;
      mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
      mysql> UPDATE customer
          ->     SET total_value=sum_from_previous_statement
          ->     WHERE customer_id=some_id;
      mysql> UNLOCK TABLES;

  Sin `LOCK TABLES`, es posible que otro flujo pueda insertar un nuevo registro en la tabla `trans` entre la ejecución del comando `SELECT` y `UPDATE`.

Puede evitar usar `LOCK TABLES` en varios casos usando actualizaciones relativas (`UPDATE customer SET `value`=`value`+`new_value``) o la función `LAST_INSERT_ID()` , Consulte Sección 1.7.5.3, “Transacciones y operaciones atómicas”.

Puede evitar bloquear tablas en algunos casos usando las funciones de bloqueo de nivel de usuario `GET_LOCK()` y `RELEASE_LOCK()`. Estos bloqueos se guardan en una tabla hash en el servidor e implementa `pthread_mutex_lock()` y `pthread_mutex_unlock()` para alta velocidad. Consulte Sección 12.9.4, “Funciones varias”.

Consulte Sección 7.3.1, “Métodos de bloqueo”, para más información acerca de la política de bloqueo.

Puede bloquear todas las tablas en todas las bases de datos con bloqueos de lectura con el comando `FLUSH TABLES WITH READ LOCK` . Consulte Sección 13.5.5.2, “Sintaxis de `FLUSH`”. Esta es una forma muy conveniente para obtener copias de seguridad si tiene un sistema de ficheros como Veritas que puede obtener el estado en un punto temporal.

Nota: Si usa `ALTER TABLE` en una tabla bloqueada, puede desbloquearse. Consulte Sección A.7.1, “Problemas con `ALTER TABLE`”.

### 13.4.6. Sintaxis de `SET TRANSACTION`

    SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

Este comando prepara el nivel de aislamiento de transacción para la siguiente transacción, globalmente, o para la sesión actual.

El comportamiento por defecto de `SET TRANSACTION` es poner el nivel de aislammiento para la siguiente transacción (que no ha empezado todavía). Si usa lka palabra clave `GLOBAL` el comando pone el nivel de aislamiento de transacción por defecto globalmente para todas las transacciones creadas desde ese momento. Las conexiones existentes no se ven afectadas. Necesita el permiso `SUPER` para hacerlo. Usar la palabra clave `SESSION` determina el nivel de transacción para todas las transacciones futuras realizadas en la conexión actual.

Para descripciones del nivel de aislamiento de cada transacción `InnoDB`, consulte Sección 15.10.3, “`InnoDB` y `TRANSACTION ISOLATION LEVEL`”. `InnoDB` soporta cada uno de estos niveles en MySQL 5.0. El nivel por defecto es `REPEATABLE READ`.

Puede inicializar el nivel de aislamiento global por defecto para mysqld con la opción `--transaction-isolation` . Consulte Sección 5.3.1, “Opciones del comando mysqld”.

## 13.5. Sentencias de administración de base de datos

### 13.5.1. Sentencias para la gestión de cuentas

#### 13.5.1.1. Sintaxis de `CREATE USER`

    CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...

El comando `CREATE USER` se añadió en MySQL 5.0.2. Este comando crea nuevas cuentas MySQL. Para usarlas, debe tener el permiso global `CREATE USER` o el permiso `INSERT` para la base de datos `mysql` . Para cada cuenta, `CREATE USER` crea un nuevo registro en la tabla `mysql.user` que no tiene permisos. Un error ocurre si la cuenta ya existe.

La cuenta puede tener una contraseña con la cláusula opcional `IDENTIFIED BY`. El valor `user` y la contraseña se dan del mismo modo que para el comando `GRANT`. En particular, para especificar la contraseña en texto plano, omita la palabra clave `PASSWORD`. Para especificar la contraseña como el valor hasheado retornado por la función `PASSWORD()` , incluya la palabra clave `PASSWORD`. Consulte Sección 13.5.1.3, “Sintaxis de `GRANT` y `REVOKE`”.

#### 13.5.1.2. Sintaxis de `DROP USER`

    DROP USER user [, user] ...

El comando `DROP USER` borra una o más cuentas MySQL . Para usarlo, debe tener el permiso global `CREATE USER` o el permiso `DELETE` para la base de datos `mysql` . Cada cuenta se nombra usando el mismo formato que para `GRANT` o `REVOKE`; por ejemplo, `'jeffrey'@'localhost'`. Las partes de usuario y equipo del nombre de cuenta se corresponden a las columnas `User` y `Host` del registro de la tabla `user` para la cuenta.

`DROP USER` como está en MySQL 5.0.0 borra sólo cuentas que no tienen permisos. En MySQL 5.0.2, se modificó para eliminar permisos de cuenta también. Esto significa que el procedimiento para borrar una cuenta depende en su versión de MySQL.

Desde MySQL 5.0.2, puede borrar una cuenta y sus permisos como sigue:

    DROP USER user;

El comando borra registros de permisos para la cuenta de todas las tablas de permisos.

En MySQL 5.0.0 y 5.0.1, `DROP USER` borra sólo cuentas MySQL que no tienen permisos. En estas versiones MySQL sólo sirve para borrar cada registro de cuenta de la tabla `user` . Para borrar una cuenta MySQL completamente (incluyendo todos sus permisos), debe usar el siguiente procedimiento, realizando estos pasos en el orden mostrado:

1. Use `SHOW GRANTS` para determinar los permisos que tiene la cuenta. Consulte Sección 13.5.4.10, “Sintaxis de `SHOW GRANTS`”.

2. Use `REVOKE` para revocar los permisos mostrados por `SHOW GRANTS`. Esto borra registros para la cuenta de todas las tablas de permisos excepto la tabla `user` , y revoca cualquier permiso global listado en la tabla `user` . Consulte Sección 13.5.1.3, “Sintaxis de `GRANT` y `REVOKE`”.

3. Borre la cuenta usando `DROP USER` para borrar el registro de la tabla `user` .

`DROP USER` no cierra automáticamente ninguna sesión de usuario. En lugar de ello, en el evento que un usuario con una sesión abierta se elimina, el comando no tiene efecto hasta que se cierra la sesión de usuario. Una vez se ha cerrado, el usuario se borra, y el próximo usuario de logueo del usuario fallará. Esto es por diseño.

#### 13.5.1.3. Sintaxis de `GRANT` y `REVOKE`

    GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
        ON [object_type] {tbl_name | * | *.* | db_name.*}
        TO user [IDENTIFIED BY [PASSWORD] 'password']
            [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
        [REQUIRE
            NONE |
            [{SSL| X509}]
            [CIPHER 'cipher' [AND]]
            [ISSUER 'issuer' [AND]]
            [SUBJECT 'subject']]
        [WITH with_option [with_option] ...]

    object_type =
        TABLE
      | FUNCTION
      | PROCEDURE

    with_option =
        GRANT OPTION
      | MAX_QUERIES_PER_HOUR count
      | MAX_UPDATES_PER_HOUR count
      | MAX_CONNECTIONS_PER_HOUR count
      | MAX_USER_CONNECTIONS count

    REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
        ON [object_type] {tbl_name | * | *.* | db_name.*}
        FROM user [, user] ...

    REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Los comandos `GRANT` y `REVOKE` permiten a los adminitradores de sistemas crear cuentas de usuario MySQL y darles permisos y quitarlos de las cuentas.

La información de cuenta de MySQL se almacena en las tablas de la base de datos `mysql` . Esta base de datos y el sistema de control de acceso se discuten extensivamente en Capítulo 5, Administración de bases de datos, que puede consultar para más detalles.

Si las tablas de permisos tienen registros de permisos que contienen nombres de tablas o bases de datos con mayúsculas y minúsculas y la variable de sistema `lower_case_table_names` está activa, `REVOKE` no puede usarse para quitar los permisos. Es necesario manipular las tablas de permisos directamente. (`GRANT` no creará estos registros cuando está activo `lower_case_table_names` , pero tales registros pueden haberse creado préviamente a activar la variable.)

Los permisos pueden darse en varios niveles:

- Nivel global

  Los permisos globales se aplican a todas las bases de datos de un servidor dado. Estos permisos se almacenan en la tabla `mysql.user`. `GRANT ALL ON *.*` y `REVOKE ALL ON *.*` otorgan y quitan sólo permisos globales.

- Nivel de base de datos

  Los permisos de base de datos se aplican a todos los objetos en una base de datos dada. Estos permisos se almacenan en las tablas `mysql.db` y `mysql.host` . `GRANT ALL ON `db_name`.*` y `REVOKE ALL ON `db_name`.*` otorgan y quitan sólo permisos de bases de datos.

- Nivel de tabla

  Los permisos de tabla se aplican a todas las columnas en una tabla dada. Estos permisos se almacenan en la tabla `mysql.tables_priv` . `GRANT ALL ON `db_name.tbl_name`` y `REVOKE ALL ON `db_name.tbl_name`` otorgan y quian permisos sólo de tabla.

- Nivel de columna

  Los permisos de columna se aplican a columnas en una tabla dada. Estos permisos se almacenan en la tabla `mysql.columns_priv` . Usando `REVOKE`, debe especificar las mismas columnas que se otorgaron los permisos.

- Nivel de rutina

  Los permisos `CREATE ROUTINE`, `ALTER ROUTINE`, `EXECUTE`, y `GRANT` se aplican a rutinas almacenadas. Pueden darse a niveles global y de base de datos. Además, excepto para `CREATE ROUTINE`, estos permisos pueden darse en nivel de rutinas para rutinas individuales y se almacenan en la tabla `mysql.procs_priv` .

La cláusula `object_type` se añadió en MySQL 5.0.6. Debe especificarse como `TABLE`, `FUNCTION`, o `PROCEDURE` cuando el siguiente objeto es una tabla, una función almacenada, o un procedimiento almacenado. Para usar esta cláusula cuando actualice de una versión anterior de MySQL a la 5.0.6, debe actualizar las tablas de permisos. Consulte Sección 2.10.2, “Aumentar la versión de las tablas de privilegios”.

Para usar `GRANT` o `REVOKE`, debe tener el permiso `GRANT OPTION` , y debe tener los permisos que está dando o quitando.

Para hacer fácil de quitar todos los permisos, MySQL 5.0 tiene la siguiente sintaxis, que borra todos los permisos globales, de nivel de base de datos y de nivel de tabla para los usuarios nombrados:

    REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Para usar esta sintaxis `REVOKE` , debe tener el permiso `CREATE USER` global o el permiso `UPDATE` para la base de datos `mysql` .

Para los comandos `GRANT` y `REVOKE` , `priv_type` pueden especificarse como cualquiera de los siguientes:

Permiso | Significado
`ALL [PRIVILEGES]` | Da todos los permisos simples excepto `GRANT OPTION`
`ALTER` | Permite el uso de `ALTER TABLE`
`ALTER ROUTINE` | Modifica o borra rutinas almacenadas
`CREATE` | Permite el uso de `CREATE TABLE`
`CREATE ROUTINE` | Crea rutinas almacenadas
`CREATE TEMPORARY TABLES` | Permite el uso de `CREATE TEMPORARY TABLE`
`CREATE USER` | Permite el uso de `CREATE USER`, `DROP USER`, `RENAME USER`, y `REVOKE ALL PRIVILEGES`.
`CREATE VIEW` | Permite el uso de `CREATE VIEW`
`DELETE` | Permite el uso de `DELETE`
`DROP` | Permite el uso de `DROP TABLE`
`EXECUTE` | Permite al usuario ejecutar rutinas almacenadas
`FILE` | Permite el uso de `SELECT ... INTO OUTFILE` y `LOAD DATA INFILE`
`INDEX` | Permite el uso de `CREATE INDEX` y `DROP INDEX`
`INSERT` | Permite el uso de `INSERT`
`LOCK TABLES` | Permite el uso de `LOCK TABLES` en tablas para las que tenga el permiso `SELECT`
`PROCESS` | Permite el uso de `SHOW FULL PROCESSLIST`
`REFERENCES` | No implementado
`RELOAD` | Permite el uso de `FLUSH`
`REPLICATION CLIENT` | Permite al usuario preguntar dónde están los servidores maestro o esclavo
`REPLICATION SLAVE` | Necesario para los esclavos de replicación (para leer eventos del log binario desde el maestro)
`SELECT` | Permite el uso de `SELECT`
`SHOW DATABASES` | `SHOW DATABASES` muestra todas las bases de datos
`SHOW VIEW` | Permite el uso de `SHOW CREATE VIEW`
`SHUTDOWN` | Permite el uso de mysqladmin shutdown
`SUPER` | Permite el uso de comandos `CHANGE MASTER`, `KILL`, `PURGE MASTER LOGS`, and `SET GLOBAL` , el comando mysqladmin debug le permite conectar (una vez) incluso si se llega a `max_connections`
`UPDATE` | Permite el uso de `UPDATE`
`USAGE` | Sinónimo de “no privileges”
`GRANT OPTION` | Permite dar permisos

El permiso `EXECUTE` no es operacional hasta MySQL 5.0.3. `CREATE VIEW` y `SHOW VIEW` se añadieron en MySQL 5.0.1. `CREATE USER`, `CREATE ROUTINE`, y `ALTER ROUTINE` se añadieron en MySQL 5.0.3. Para usar estos permisos al actualizar desde una versión anterior de MySQL que no los tenga, debe actualizar primero las tablas de permisos, como se describe en Sección 2.10.2, “Aumentar la versión de las tablas de privilegios”.

El permiso `REFERENCES` actualmente no se usa.

`USAGE` puede especificarse cuando quiere crear un usuario sin permisos.

Use `SHOW GRANTS` para determinar qué permisos tiene la cuenta. Consulte Sección 13.5.4.10, “Sintaxis de `SHOW GRANTS`”.

Puede asignar permisos globales usando sintaxis `ON *.*` o permisos a nivel de base de datos usando la sintaxis `ON `db_name`.*`. Si especifica `ON *` y tiene seleccionada una base de datos por defecto, los permisos se dan en esa base de datos. (Atención: Si especifica `ON *` y no ha seleccionado una base de datos por defecto, los permisos dados son globales.)

Los permisos `FILE`, `PROCESS`, `RELOAD`, `REPLICATION CLIENT`, `REPLICATION SLAVE`, `SHOW DATABASES`, `SHUTDOWN`, y `SUPER` son permisos administrativos que sólo pueden darse globalmente (usando sintaxis `ON *.*` ).

Otros permisos pueden darse globalmente o a niveles más específicos.

Los únicos valores `priv_type` que puede especificar para una tabla son `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `DROP`, `GRANT OPTION`, `INDEX`, y `ALTER`.

Los únicos valores `priv_type` que puede especificar para una columna (cuando usa la cláusula `column_list` ) son `SELECT`, `INSERT`, y `UPDATE`.

Los únicos valores `priv_type` que puede especificar a nivel de rutina son `ALTER ROUTINE`, `EXECUTE`, y `GRANT OPTION`. `CREATE ROUTINE` no es un permiso de nivel de rutina porque debe tener este permiso para ser capaz de crear una rutina en primer lugar.

Para los niveles global, base de datos, tabla y rutina, `GRANT ALL` asigna sólo los permisos que existen en el nivel que está otorgándolos. Por ejemplo, si usa `GRANT ALL ON `db_name`.*`, este es un comando de nivel de base de datos, así que ninguno de los permisos únicamente globales tales como `FILE` se otorgan.

MySQL le permite dar permisos incluso en objetos de bases de datos que no existen. En tales casos, los permisos a dar deben incluir el permiso `CREATE` . Este es el comportamiento diseñado, y se pretende permitir al administrador de la base de datos perparar cuentas de usuario y permisos para objetos de base de datos que se crearán posteriormente.

MySQL no elimina automáticamente nigún permiso si borra una tabla o base de datos . Si borra un rutina, se quita cualquier permiso dado a nivel de rutina para la misma.

Nota: los carácters comodín '`_`' y '`%`' se permiten al especificar nombres de base de datos en comandos `GRANT` que otorgan permisos a nivel global o de base de datos. Esto significa, por ejemplo, que si quiere usar un carácter '`_`' como parte de un nombre de base de datos, debe especificarlo como '`\_`' en el comando `GRANT` , para evitar que el usuario sea capaz de acceder a bases de datos adicionales que coincidan con el patrón de los comodines, por ejemplo `GRANT ... ON `foo\_bar`.* TO ...`.

Para acomodar los permisos a los usuarios de equipos arbitrários, MySQL soporta especificar el valor `user` con la forma ``user_name`@`host_name``. Si un valor `user_name` o `host_name` es legal como identificador sin poner entre comillas, no necesita hacerlo. Sin embargo, las comillas son necesarias para especificar una cadena `user_name` conteniendo carácteres especiales (tales como '`-`'), o una cadena `host_name` conteniendo carácteres especiales o comodín (tales como '`%`'); por ejemplo, `'test-user'@'test-hostname'`. Entrecomille el nombre de usuario y de equipo separadamente.

Puede especificar carácteres comodín en el nombre de equipo. Por ejemplo, ``user_name`@'%.loc.gov'` se aplica a `user_name` para cualquier equipo en el dominio `loc.gov` , y ``user_name`@'144.155.166.%'` se aplica a `user_name` para cualquier equipo en la clase subred clase C `144.155.166` .

La forma simple `user_name` es sinónimo de ``user_name`@'%'`.

MySQL no soporta comodines en el nombre de usuario. Los usuarios anónimos se definien insertando entradas con `User=''` en la tabla `mysql.user` o creando un usuario con un nombre vacío con el comando `GRANT` :

    mysql> GRANT ALL ON test.* TO ''@'localhost' ...

Al especificar valores delimitados, use comillas simples para delimitar los nombres de bases de datos, tabla, columna y de rutina ('```'). Para los nombres de equipo, nombres de usuario, y contraseñas como cadenas, use apóstrofes ('`'`').

Advertencia: Si permite conectar con el servidor a usuarios anónimos, debe dar permisos a todos los usuarios locales como ``user_name`@localhost`. De otro modo, la cuenta de usuario anónimo para `localhost` en la tabla `mysql.user` (creada durante la instalación de MySQL) se usa cuando los usuarioa con nombre intentan loguear con el servidor MySQL desde la máquina local.

Puede determinar si esto se aplica a su sistema ejecutando la siguiente consulta, que lista cualquier usuario anónimo:

    mysql> SELECT Host, User FROM mysql.user WHERE User='';

Si quiere borrar la cuenta anónima local para evitar el problema descrito, use estos comandos:

    mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
    mysql> FLUSH PRIVILEGES;

`GRANT` soporta nombres de equipo de hasta 60 carácteres. Los nombres de bases de datos, tablas, columnas y rutinas pueden tener hasta 64 carácteres. Los nombres de usuario pueden tener hasta 16 carácteres. Los nombres de usuario pueden tener hasta 16 carácteres. Estos límites están harcodeados en el software MySQL y no pueden cambiarse alterando las tablas de permisos .

Los permisos para una tabla o columna se forman de forma aditiva como una `OR` lógica de los permisos en cada uno de los cuatro niveles de permisos. Por ejemplo, si la tabla `mysql.user` especifica que un usuario tiene un permiso `SELECT` global, el permiso no puede denegarse mediante una entrada en el nivel de base de datos, tabla o columna.

Los permisos de una columna pueden calcularse como sigue:

    global privileges
    OR (database privileges AND host privileges)
    OR table privileges
    OR column privileges

En la mayoría de casos, puede dar derechoa a un usuario en sólo uno de los niveles de permisos, así que la vida normalmente no es tan complicada. Los detalles de este procedimiento de chequeo de permisos se presentan en Sección 5.6, “El sistema de privilegios de acceso de MySQL”.

Si otorga permisos para una combinación usuario/equipo que no existe en la tabla `mysql.user` se añade una entrada que permite allí hasta que se borra con un comando `DELETE`. En otras palabras, `GRANT` puede crear entradas `user` pero `REVOKE` no los borra; debe hacerlo explícitamente usando `DROP USER` o `DELETE`.

Si se crea un nuevo usuario o si tiene permisos globales para otorgar permisos, la contraseña de usuario se cambia con la contraseña especificada por la cláusula `IDENTIFIED BY` , si se da una. Si el usuario ya tiene una contraseña, esta se reemplaza por la nueva.

Atención: Si crea un nuevo usuario pero no especifica una cláusula `IDENTIFIED BY`, el usuario no tiene contraseña. Esto es muy poco seguro. Desde MySQL 5.0.2, puede activar el modo SQL `NO_AUTO_CREATE_USER` para evitar que `GRANT` cree un nuevo usuario si lo hiciese de otro modo, a no ser que `IDENTIFIED BY` se de para proporcionar la nueva contraseña de usuario.

Las contraseñas pueden ponerse con el comando `SET PASSWORD` . Consulte Sección 13.5.1.5, “Sintaxis de `SET PASSWORD`”.

En la cláusula `IDENTIFIED BY` , la contraseña debe darse como el valor de contraseña literal. No es necesario usar la función `PASSWORD()` como lo es para el comando `SET PASSWORD` . Por ejemplo:

    GRANT ... IDENTIFIED BY 'mypass';

Si no quiere enviar la contraseña en texto plano y conoce el valor haseado que `PASSWORD()` retornaría para la contraseña, puede especificar el valor hasheado precedido por la palabra clave `PASSWORD`:

    GRANT ...
    IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';

En un programa C , puede obtener el valor haseado usando la función `make_scrambled_password()` de la API de C.

Si da permisos para una base de datos, se crea una entrada en la tabla `mysql.db` si es necesario. Si todos los permisos para la base de datos se eliminan con `REVOKE`, esta entrada se borra.

Si un usuario no tiene permisos para una tabla, el nombre de tabla no se muestra cuando el usuario pide una lista de talbas (por ejemplo, con el comando `SHOW TABLES` ).

El permiso `SHOW DATABASES` le permite a la cuenta ver nombres de bases de datos realizando el comando `SHOW DATABASE` . Las cuentas que no tienen este permiso sólo ven las bases de datos para las que tienen algún permiso, y no pueden usar el comando para nada si el servidor se arranca con la opción `--skip-show-database`.

La cláusula `WITH GRANT OPTION` le da al usuario la habilidad para dar a otros usuarios cualquier permiso que tenga el usuario en el nivel de permiso especificado. Debe tener cuidado de a quién da el permiso `GRANT OPTION`, ya que dos usuarios con permisos distintos pueden ser capaces de juntar permisos!

No puede dar a otro usuario un permiso que no tenga usted mismo; el permiso `GRANT OPTION` le permite asignar sólo los permisos que tenga usted.

Tenga en cuenta que cuando le da a un usuario el permiso `GRANT OPTION` a un nivel de permisos particular, cualquier permiso que tenga el usuario (o que se de en el futuro!) a este nivel también son otorgables por este usuario. Suponga que le da a un usuario el permisos `INSERT` en una base de datos. Si otorga el permiso `SELECT` en la base de datos y especifica `WITH GRANT OPTION`, el usuario puede quitar no sólo el permiso `SELECT` sino también `INSERT`. Si luego otorga el permiso `UPDATE` al usuario en la base de datos, el usuario puede quitar `INSERT`, `SELECT`, y `UPDATE`.

No debe otorgar permisos `ALTER` a un usuario normal. Si lo hace, el usuario puede intentar engañar al sistema de permisos renombrando tablas!

Las opciones `MAX_QUERIES_PER_HOUR `count``, `MAX_UPDATES_PER_HOUR `count``, y `MAX_CONNECTIONS_PER_HOUR `count`` limitan el número de consultas, actualizaciones, y logueos que puede realizar un usuario durante cualquier perído de una hora. Si `count` es 0 (por defecto), esto significa que no hay limitación para ese usuario.

La `MAX_USER_CONNECTIONS `count`` opción, implementada en MySQL 5.0.3, limita el máximo número de conexiones simultáneas que la cuenta puede hacer. Si `count` es 0 (por defecto), la `max_user_connections` variable de sistema determina el número de conexiones simultáneas para la cuenta.

Nota: para especificar cualquiera de estas opciones de limitación de recursos para un usuario existente sin afectar a los permisos existentes, use `GRANT USAGE ON *.* ... WITH MAX_...`.

Consulte Sección 5.7.4, “Limitar recursos de cuentas”.

MySQL puede chequear atributos certificados X509 además que la autenticación usual que se basa en el nombre de usuario y contraseña. Para especificar opciones relacionadas con SSL para la cuenta MySQL, use la cláusula `REQUIRE` del comando `GRANT` . (Para información de transfondo sobre el uso de SSL con MySQL, consulte Sección 5.7.7, “Usar conexiones seguras”.)

Hay distintas posibilidades para limitar tipos de conexión para una cuenta:

- Si una cuenta no tiene requerimientos de SSL o X509, se permiten conexiones sin encriptar si la contraseña y nombre de usuario son válidos. Sin embargo, las conexiones no encriptadas pueden usarse en las opciones de cliente, si el cliente tiene los ficheros clave y de certificado apropiados.

- La opción `REQUIRE SSL` le dice al servidor que permita sólo conexiones SSL encriptadas para la cuenta. Tenga en cuenta que esta opción puede omitirse si hay algunos registros de control de acceso que permitan conexiones no SSL.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

- `REQUIRE X509` significa que el cliente debe tener un certificado válido pero que el certificador exacto y el asunto no importan. El único requerimiento que debe ser posible de verificar es la firma con uno de las AC certificadas.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret' REQUIRE X509;

- `REQUIRE ISSUER '`issuer`'` crea una restricción de intentos de conexión en que el cliente debe presentar un certificado X509 válido presentado por la AC `issuer`. Si el cliente presenta un certificado válido pero de otra AC, el servidor rehúsa la conexión. El uso de certificados X509 siempre implica encripción, por lo que la opción `SSL` no es necesaria.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
             O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';

  Tenga en cuenta que el valor `ISSUER` debe entrarse como una cadena única.

- `REQUIRE SUBJECT '`subject`'` crea la restricción en los intentos de conexión de que el cliente debe presentar un certificado X509 válido con el asunto `subject`. Si el cliente presenta un certificado válido pero con un asunto distinto, el servidor rehúsa la conexión.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
             O=MySQL demo client certificate/
             CN=Tonu Samuel/Email=tonu@example.com';

  Tenga en cuenta que el valor `SUBJECT` debe entrarse como una única cadena.

- `REQUIRE CIPHER '`cipher`'` se necesita para asegurar que se usan cifradores suficientemente fuertes y longitudes de claves acordes. SSL por sí mismo puede ser débil si se usan algoritmos antiguos con claves de encriptación cortas. Con esta opción, puede especificar el método de cifrado exacto para permitir una conexión.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

Las opciones `SUBJECT`, `ISSUER`, y `CIPHER` pueden combinarse en la cláusula `REQUIRE` así:

    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret'
        -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
           O=MySQL demo client certificate/
           CN=Tonu Samuel/Email=tonu@example.com'
        -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
           O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
        -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

Tenga en cuenta que los valores `SUBJECT` y `ISSUER` deben entrarse como una única cadena.

En MySQL 5.0, la palabra clave `AND` es opcional entre las opciones `REQUIRE` .

El orden de las opciones no importa, pero no puede especificarse ninguna opción dos veces.

Cuando mysqld arranca, todos los permisos se leen en memoria. Para más detalles, consulte Sección 5.6.7, “Cuándo tienen efecto los camios de privilegios”.

Tenga en cuenta que si usa permisos de tablas o de columnas para un usuario, el servidor examina los permisos de tablas y usuarios para todos los usuarios y esto ralentiza MySQL ligeramente. De forma similar, si limita el número de consultas, actualizaciones o conexiones para cualquier usuario, el servidor debe monitorizar estos valores.

Las mayores diferencias entre las versiones de `GRANT` de MySQL y SQL estándar son:

- En MySQL, los permisos se asocian con una combinación de nombre de usuario/equipo y no sólo con el usuario.

- SQL estándar no tienen permisos globales o a nivel de base de datos, ni soporta todos los tipos de permisos que soporta MySQL .

- MySQL no soporta los permisos de SQL estándar `TRIGGER` o `UNDER`.

- Los permisos de SQL estándar se estructuran de forma jerárquica. Si borra un usuario, todos los permisos que tuviera el usuario se eliminan. Esto es cierto a partir de MySQL 5.0.2 y si usa `DROP USER`. Antes de 5.0.2, los permisos otorgados no se eliminaban automáticamente; debía hacerlo a mano. Consulte Sección 13.5.1.2, “Sintaxis de `DROP USER`”.

- En SQL estándar, cuando borra una tabla, todos los permisos para la tabla se eliminan. Con SQL estándar, cuando quita un permiso, todos los permisos otorgados basados en ese permiso también se eliminaban. En MySQL, los permisos sólo pueden borrarse con comandos `REVOKE` explícitos o manipulando las tablas de permisos de MySQL.

- En MySQL, es posible tener el permiso `INSERT` sólo para algunas de las columnas en la tabla. En este caso, todavía puede ejecutar comandos `INSERT` en la tabla mientras omita esas columnas para las que no tiene el permiso `INSERT` . Las columnas omitidas obtienen su valor por defecto implícito si no está activado el modo SQL estricto. En modo estricto, el comando se rehúsa si algunas de las columnas omitidas no tienen valor por defecto. Sección 5.3.2, “El modo SQL del servidor” discute acerca del modo estricto. Sección 13.1.5, “Sintaxis de `CREATE TABLE`” disctue acerca de los valores por defecto implícitos.

  Las columnas para las que no tiene el permiso `INSERT` se ponen a su valor por defecto. SQL estándar requiere que tenga el permiso `INSERT` en todas las columnas.

  En MySQL, si tiene el permiso INSERT sólo en alguna de las columnas de la tabla, puede ejecutar comandos INSERT — mientras omita las columnas para las que no tiene el permiso de su comando INSERT; tales columnas obtendrán su valor por defecto. En modo estricto (cuando sql_mode="traditional"), si alguna de las columnas omitidas no tiene valor por defecto, el comando INSERT se rehúsa.

#### 13.5.1.4. Sintaxis de `RENAME USER`

    RENAME USER old_user TO new_user
        [, old_user TO new_user] ...

El comando `RENAME USER` renombra cuentas de usuario MySQL existentes. Para usarlo, debe tener el permiso `CREATE USER` global o el permiso `UPDATE` para la base de datos `mysql` . Ocurre un error si cualquier de las antiguas cuentas no existe o cualquiera de las nuevas ya existe. Los valores `old_user` y `new_user` se dan igual que para el comando `GRANT` .

El comando `RENAME USER` se añadió en MySQL 5.0.2.

#### 13.5.1.5. Sintaxis de `SET PASSWORD`

    SET PASSWORD = PASSWORD('some password')
    SET PASSWORD FOR user = PASSWORD('some password')

El comando `SET PASSWORD` asigna una contraseña a una cuenta de usuario MySQL existente.

La primera sintaxis asigna la contraseña para el usuario actual. Cualquier cliente que se conecte al servidor usando una cuenta no anónima puede cambiar la contraseña para la misma.

La segunda sintaxis asigna una contraseña para una cuenta específica en el servidor actual. Sólo los clientes con el permiso `UPDATE` para la base de datos `mysql` pueden hacerlo. El valor `user` debe darse en formato ``user_name`@`host_name`` donde `user_name` y `host_name` son exactamente los mismos que cuando se listan en las columnas `User` y `Host` de la tabla `mysql.user` . Por ejemplo, si tiene una entrada en las columnas `User` y `Host` con los valores `'bob'` y `'%.loc.gov'`, escribiría el comando así:

    mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');

Esto es equivalente al siguiente comando:

    mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
        -> WHERE User='bob' AND Host='%.loc.gov';
    mysql> FLUSH PRIVILEGES;

Nota: Si se está conectando a un servidor MySQL 4.1 o posterior usando programas clientes anteriores a la 4.1, no use los comandos `SET PASSWORD` o `UPDATE` precedentes sin leer Sección 5.6.9, “Hashing de contraseñas en MySQL 4.1” primero. El formato de contraseña cambió en MySQL 4.1, y bajo ciertas circunstáncias, puede que no sea capaz de conectar al servidor.

En MySQL 5.0, puede ver su entrada de autenticación `user@host` ejecutando `SELECT CURRENT_USER()`.

### 13.5.2. Sentencias para el mantenimiento de tablas

#### 13.5.2.1. Sintaxis de `ANALYZE TABLE`

    ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

Este comando analiza y almacena la distribución de clave para una tabla. Durante el análisis, la tabla se bloquea con un bloqueo de lectura. En MySQL 5.0, funciona en tablas `MyISAM`, `BDB`, y `InnoDB` . Para tablas `MyISAM` , este comando es equivalente a usar myisamchk -a.

MySQL usa la distribución de claves almacenada para decidir el orden en que las tablas deben hacer los joins cuando realiza uno en algo que no sea una constante.

El comando retorna una tabla con las siguientes columnas:

Columna | Valor
`Tabla` | Nombre de tabla
`Op` | Siempre `analyze`
`Msg_type` | Es `status`, `error`, `info`, o `warning`
`Msg_text` | Mensaje

Puede chequear la distribución de claves almacenada con el comando `SHOW INDEX` . Consulte Sección 13.5.4.11, “Sintaxis de `SHOW INDEX`”.

Si la tabla no ha cambiado desde el último comando `ANALYZE TABLE` , la tabla no se vuelve a analizar.

En MySQL 5.0, los comandos `ANALYZE TABLE` se escriben en el log binario a no ser que la palabra clave `NO_WRITE_TO_BINLOG` opcional (o su alias `LOCAL`) se use.

#### 13.5.2.2. Sintaxis de `BACKUP TABLE`

    BACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'

Nota: Este comando está obsoleto. Estamos trabajano en un mejor sustituto para este que proporcionará capacidades de copia de seguridad en línea. De momento, el script mysqlhotcopy puede usarse.

`BACKUP TABLE` copia al directorio de base de datos el mínimo número de ficheros de tablas necesarias para restaurar la tabla, tras volcar cualquier cambios almacenados en el buffer a disco. El comando funciona sólo para tablas `MyISAM` . Copia los ficheros de definición `.frm` y de datos `.MYD` . El fichero índice `.MYI` puede reconstruirse desde estos otros. El directorio debe especificarse con la ruta entera.

Antes de usar este comando consulte Sección 5.8.1, “Copias de seguridad de bases de datos”.

Durante la copia de seguridad, se realiza un bloqueo de lectura para cada tabla, uno cada vez, mientras se hace la copia. Si quier hacer una copia de seguridad de varias tablas como una muestra (evitando que ninguna de ellas se cambie durante la operación de la copia de seguridad), debe realizar un comando `LOCK TABLES` para obtener un bloqueo de lectura para cada tabla en el grupo.

El comando retorna una tabla con las siguientes columnas:

Columna | Valor
`Tabla` | Nombre de tabla
`Op` | Siempre `backup`
`Msg_type` | Es `status`, `error`, `info`, o `warning`
`Msg_text` | Mensaje

#### 13.5.2.3. Sintaxis de `CHECK TABLE`

    CHECK TABLE tbl_name [, tbl_name] ... [option] ...

    option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

Chequea una tabla o tablas para errores. `CHECK TABLE` funciona para tablas `MyISAM` y `InnoDB` . Para tablas `MyISAM` , la estadística de clave se actualiza.

Desde MySQL 5.0.2, `CHECK TABLE` puede chequear las vistas para problemas, tales como tablas que se referencian en la definición de la vista que ya no existe.

El comando `CHECK TABLE` retorna una tabla con las siguientes columnas:

Columna | Valor
`Tabla` | Nombre de tabla
`Op` | Siempre `check`
`Msg_type` | Es `status`, `error`, `info`, o `warning`
`Msg_text` | Mensaje

Tenga en cuenta que el comando puede producir varios registros para información de cada tabla chequeada. El último registro tiene un valor `Msg_type` de `status` y `Msg_text` normalmente debe ser `OK`. Si no obtiene `OK`, o `Table is already up to date` debe realizar una reparación de la tabla. Consulte Sección 5.8.3, “Mantenimiento de tablas y recuperación de un fallo catastrófico (crash)”. `Table is already up to date` significa que el motor de almacenamiento para la tabla indicada indica que no hay necesidad de chequear la tabla.

Las distintas opciones de chequeo que pueden darse se muestran en la siguiente tabla. Estas opciones se aplican sólo para tablas `MyISAM` y se ignoran en tablas `InnoDB` y vistas.

Tipo | Significado
`QUICK` | No escanea los registros para chequear enlaces incorrectos.
`FAST` | Sólo chequea tablas que no se han cerrado correctamente.
`CHANGED` | Sólo las tablas chequeadas que se han cambiado desde el úlitmo chequeo o no se han cerrado correctamente.
`MEDIUM` | Escanea registros para verificar que los enlaces borrados están bien. También calcula el checksum de la clave para los registros y lo verifica con el checksum calculado para las claves.
`EXTENDED` | Realiza una búsqueda completa para todas las claves para cada registro. Se asegura que la tabla es consistente 100%, pero tarda mucho tiempo!

Si ninguna de las opciones `QUICK`, `MEDIUM`, o `EXTENDED` se especifica, el tipo de chequeo por defecto para tablas de formato dinámico `MyISAM` es `MEDIUM`. Esto es lo mismo que ejecutar myisamchk --medium-check `tbl_name` en la tabla. El tipo de chequeo por defecto también es `MEDIUM` para tablas `MyISAM` de formato estático, a no ser que se especifique `CHANGED` o `FAST`. En tal caso, por defecto es `QUICK`. El escaneo de registro se evita para `CHANGED` y `FAST` porque los registros están corruptos muy raramente.

Puede combinar opciones de chequeo, como en el siguiente ejemplo, que realiza un chequeo rápido de la tabla para ver si se cerró correctamente:

    CHECK TABLE test_table FAST QUICK;

Nota: En algunos casos, `CHECK TABLE` cambia la tabla. Esto ocurre si la tabla se marca como “corrupted” o “not closed properly” pero `CHECK TABLE` no encuentra ningún problema en la tabla. En este caso, `CHECK TABLE` marca la tabla como correcta.

Si una tabla está corrupta, es más probable que el problema esté en el índice y no en la parte de datos. Todos los tipos de chequeo chequean los índices profundamente y deberían encontrar la mayoría de errores.

Si quiere chequear una tabla que asume como correcta, no debe usar opciones de chequeo o la opción `QUICK`. Ésta debe usarse cuando tiene prisa y puede permitirse el pequeño riesgo que `QUICK` no encuentre un error en el fichero de datos. (En la mayoría de casos, MySQL debería encontrar, bajo uso normal, cualquier error en el fichero de datos. Si esto ocurre, la tabla se marca como “corrupted” y no puede usarse hasta que se repare.)

`FAST` y `CHANGED` están pensados para usar desde un script (por ejemplo, para ejecutarse desde cron) si quiere chequear sus tablas de vez en cuando. En la mayoría de casos, `FAST` se prefiere en lugar de `CHANGED`. (El único caso en que no es el método preferido es cuando sospecha que ha encontrado un bug en el código `MyISAM` .)

`EXTENDED` debe usarse sólo después de ejecutar un chequeo normal pero todavía obtiene errores extraños de la tabla cuando MySQL intenta actualizar un registro o encuentra un registro mediante la clave. (Esto es muy improbable si un chequeo normal ha tenido éxito.)

Algunos problemas reportados por `CHECK TABLE` no pueden corregirse automáticamente:

- `Found row where the auto_increment column has the value 0`.

  Esto significa que tiene un registro en la tabla donde la columna `AUTO_INCREMENT` contiene un valor de índice de 0. (Es posible crear un registro donde la columna `AUTO_INCREMENT` es 0 poneindo la columna explícitamente a 0 con un comando `UPDATE` .)

  Esto no es un error por si mismo, pero puede causar problemas si decide volcar la tabla y restaurarla o realizar un `ALTER TABLE` en la tabla. En este caso, la columna `AUTO_INCREMENT` cambia los valores según las reglas de las columnas `AUTO_INCREMENT` , que pueden causar problemas tales como errores de clave duplicada.

  Para evitar las advertencias, símplemente ejecute un comando `UPDATE` para poner en la columna un valor distinto a 0.

#### 13.5.2.4. Sintaxis de `CHECKSUM TABLE`

    CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]

Reporta un checksum de tabla.

Si `QUICK` se especifica, el checksum de la tabla se reporta si está disponible, o `NULL` en otro caso. Esto es muy rápido. Un checksum en vivo está permitido especificando la opción de tabla `CHECKSUM=1` , actualmente sólo soportado por tablas `MyISAM` . Consulte Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

En modo `EXTENDED` la tabla completa se lee registro a registro y se calcula el checksum. Esto puede ser muy lento para tablas grandes.

Por defecto, si no se especifica ni `QUICK` ni `EXTENDED` , MySQL retorna un checksum en vivo si el motor de tabla lo soporta y escanea la tabla de otro modo.

`CHECKSUM TABLE` retorna `NULL` para tablas no existentes. Desde MySQL 5.0.3, se genera una advertencia para esta condición.

#### 13.5.2.5. Sintaxis de `OPTIMIZE TABLE`

    OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

`OPTIMIZE TABLE` debe usarse si ha borrado una gran parte de la tabla o si ha hecho varios cambios en una tabla con registros de longitud variable (tablas que tienen columnas `VARCHAR`, `BLOB`, o `TEXT` ). Los registros borrados se mantienen en una lista enlazada y operaciones `INSERT` posteriores reúsan posiciones de antiguos registros. Puede usar `OPTIMIZE TABLE` para reclamar el usuario no usado y para defragmentar el fichero de datos.

En la mayoría de inicializaciones, no necesita ejecutar `OPTIMIZE TABLE` para nada. Incluso si hace muchas actualizaciones a registros de longitud variables, no es probable que necesite hacerlo más de una vez a la semana o mes y sólo en ciertas tablas.

Actualmente, `OPTIMIZE TABLE` funciona sólo en tablas `MyISAM`, `BDB` y `InnoDB` .

Para tablas `MyISAM` , `OPTIMIZE TABLE` funciona como sigue:

1. Si la tabla ha borrado o dividido registros, repare la tabla.

2. Si las páginas índice no están ordenadas, ordénelas.

3. Si las estadísticas no están actualizadas (y la reparación no puede hacerse ordenando el índice), actualícelas.

Para tablas `BDB` , `OPTIMIZE TABLE` es mapea como `ANALYZE TABLE`. Para tablas `InnoDB` , se mapea con `ALTER TABLE`, que reconstruye la tabla. Reconstruye las estadísticas actualizadas de índice y libera espacio no usado en el índice clusterizado. Consulte Sección 13.5.2.1, “Sintaxis de `ANALYZE TABLE`”.

Puede hacer que `OPTIMIZE TABLE` funcione con otros tipos de tabla arrancando mysqld con la opción `--skip-new` o `--safe-mode` ; en este caso `OPTIMIZE TABLE` se mapea con `ALTER TABLE`.

Tenga en ceunta que MySQL bloquea la tabla mientras se ejecuta `OPTIMIZE TABLE` .

En MySQL 5.0, los comandos `OPTIMIZE TABLE` se escriben en el log binario a no ser que la palabra `NO_WRITE_TO_BINLOG` opcional(o su alias `LOCAL`) se use. Esto se hace para que los comandos `OPTIMIZE TABLE` se usen en MySQL server actuando como maestro de replicación se replique por defecto en el esclavo de replicación.

#### 13.5.2.6. Sintaxis de `REPAIR TABLE`

    REPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLE
        tbl_name [, tbl_name] ... [QUICK] [EXTENDED] [USE_FRM]

`REPAIR TABLE` repara una tabla posiblemente corrupta. Por defecto, tiene el mismo efecto que myisamchk --recover `tbl_name`. `REPAIR TABLE` funciona sólo en tablas `MyISAM`.

Normalmente nunca debe ejecutar este comando. Sin embargo, si hay un desastre, `REPAIR TABLE` puede recuperar todos los datos de una tabla `MyISAM` . Si sus tablas se corrompen a menudo, debe intentar encontrar la razón de lo que lo causa, para eliminar la necesidad de usar `REPAIR TABLE`. Consulte Sección A.4.2, “Qué hacer si MySQL sigue fallando (crashing)”. Consulte Sección 14.1.4, “Problemas en tablas `MyISAM`”.

El comando retorna una tabla con las siguientes columnas:

Columna | Valor
`Tabla` | Nombre de tabla
`Op` | Siempre es `repair`
`Msg_type` | Es `status`, `error`, `info`, o `warning`
`Msg_text` | Mensaje

El comando `REPAIR TABLE` puede producir muchos registros de información para cada tabla reparada. El último registro tiene un valor `Msg_type` de `status` y `Msg_test` normalmente debe ser `OK`. Si no obtiene `OK`, debe intentar reparar la tabla con myisamchk --safe-recover, ya que `REPAIR TABLE` no implementa todas las opciones de myisamchk. Plaenamos hacerlo más flexible en el futuro.

Si se da `QUICK` , `REPAIR TABLE` intenta reparar sólo el árbol índice. Este tipo de reparación es como lo que hace myisamchk --recover --quick.

Si usa `EXTENDED`, MySQL crea el índice registro a registro en lugar de crear un índice a la vez ordenando. Este tipo de reparación es como el hecho por myisamchk --safe-recover.

También hay un modo `USE_FRM` disponible en MySQL 5.0 para `REPAIR TABLE`. Use esto si el fichero índice `.MYI` no existe o su cabecera está corrupta. En este modo, MySQL recrea el fichero `.MYI` usando información desde el fichero `.frm` . Este tipo de reparación no puede hacerse con myisamchk. Nota: Use este modo sólo si no puede usar modos `REPAIR` normalmente. La cabecera `.MYI` contiene información importante de metadatos (en particular, los valores actuales `AUTO_INCREMENT` y `Delete link`) que se pierden en `REPAIR ... USE_FRM`. No use `USE_FRM` si la tabla está comprimida, ya que esta información se almacena en el fichero `.MYI` .

En MySQL 5.0, los comandos `REPAIR TABLE` se escriben en el log binario a no ser que la palabra opcional `NO_WRITE_TO_BINLOG` (o su alias `LOCAL`) se use.

Atención: Si el servidor muere durante una operación `REPAIR TABLE`, es esencial tras restaurarla que inmediatamente ejecute otro comando `REPAIR TABLE` para la tabla antes de realizar cualquier otra operación en ella. (Siempre es una buena idea empezar haciendo una copia de seguridad.) En el peor caso, puede tener un nuevo fichero índice limpio sin información acerca del fichero de datos, y luego la siguiente operación que realice puede sobreescribir el fichero de datos. Este es un escenario improbable pero posible.

#### 13.5.2.7. Sintaxis de `RESTORE TABLE`

    RESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'

Restaura la tabla o tablas de una copia de seguridad que se hizo con `BACKUP TABLE`. Las tablas existentes no se sobreescriben; si trata restaurar una tabla existente, obtiene un error. Pero como `BACKUP TABLE`, `RESTORE TABLE` actualmente funciona sólo para tablas `MyISAM` . El directorio debe especificarse como una ruta completa.

La copia de seguridad para cada tabla consiste en su fichero de formato `.frm` y fichero de datos `.MYD` . La operación de restauración restaura aquellos ficheros, luego los usa para reconstruir el fichero índice `.MYI`. La restauración tarda más tiempo que la copia de seguridad debido a la necesidad de reescribir los índices. Mientras más índices tenga la tabla, más tarda.

El comando retorna una tabla con las siguientes columnas:

Columna | Valor
`Tabla` | Nombre de tabla
`Op` | Siempre `restore`
`Msg_type` | Es `status`, `error`, `info`, o `warning`
`Msg_text` | Mensaje

### 13.5.3. Sintaxis de `SET`

    SET variable_assignment [, variable_assignment] ...

    variable_assignment:
          user_var_name = expr
        | [GLOBAL | SESSION] system_var_name = expr
        | @@[global. | session.]system_var_name = expr

`SET` inicializa distintos tipos de variables que afectan la operación del servidor o de su cliente. Puede usarse para asignar valores a las variables de usuario o de sistema.

El comando `SET PASSWORD` para asignar contraseñas de cuenta se describen en Sección 13.5.1.5, “Sintaxis de `SET PASSWORD`”.

La mayoría del sistema puede cambiarse en tiempo de ejecución. Las variables de sistema que pueden describirse dinámicamente se describen en Sección 5.3.3.1, “Variables de sistema dinámicas”.

Nota: Las versiones antiguas de MySQL empleaban `SET OPTION` para este comando, pero su uso está obsoleto en favor de `SET`.

El siguiente ejemplo muestra las distintas sintaxis que puede usar para cambiar las variables.

Una variable de usuario se escribe como `@`var_name`` y puede cambiarse como sigue:

    SET @var_name = expr;

Más información sobre variables de usuario se da en Sección 9.3, “Variables de usuario”.

Se puede referir a las variables de sistema en comandos `SET` como `var_name`. El nombre puede ir precedido opcionalmente por `GLOBAL` o `@@global.` para indicar explícitamente que la variable es global, o por `SESSION`, `@@session.`, o `@@` para indicar que es una variable de sesión. `LOCAL` y `@@local.` son sinónimos para `SESSION` y `@@session.`. Si no hay modificador presente, `SET` asigna un valor a la variable de sesión.

La sintaxis `@@`var_name`` para variables de sistema se soporta para hacer la sintaxis de MySQL compatible con otros sistemas de base de datos.

Si cambia varias variables de sistema en el mismo comando, la última opción `GLOBAL` o `SESSION` usada se usa para variables que no tienen modo especificado.

    SET sort_buffer_size=10000;
    SET @@local.sort_buffer_size=10000;
    SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
    SET @@sort_buffer_size=1000000;
    SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;

Si cambia una variable de sistema usando `SESSION` (por defecto), el valor queda en efecto hasta que la sesión actual finaliza o hasta que cambia la variable con un valor distinto. Si cambia la variable de sistema usando `GLOBAL`, que requiere el permiso `SUPER` , el valor se recuerda y se usa para nuevas conexiones hasta que el servidor se reinicia. Si quiere hacer un cambio de variable permanente, debe ponerlo en un fichero de opciones. Consulte Sección 4.3.2, “Usar ficheros de opciones”.

Para evitar uso incorrecto, MySQL produce un error si usa `SET GLOBAL` con una variable que sólo puede ser usada con `SET SESSION` o si no especifica `GLOBAL` (o `@@`) cuando cambie una variable global.

Si quiere cambiar una variable `SESSION` al valor `GLOBAL` o un valor `GLOBAL` al valor de compilación de MySQL por defecto, puede hacerlo con `DEFAULT`. Por ejemplo, los siguientes dos comandos son idénticos en cambiar los valores de sesión o `max_join_size` al valor global:

    SET max_join_size=DEFAULT;
    SET @@session.max_join_size=@@global.max_join_size;

Puede obtener una lista de la mayoría de variables de sistema con `SHOW VARIABLES`. (Consulte Sección 13.5.4.21, “Sintaxis de `SHOW VARIABLES`”.) Para obtener un nombre de variable específico, use una cláusula `LIKE` commo se muestra:

    SHOW VARIABLES LIKE 'max_join_size';
    SHOW GLOBAL VARIABLES LIKE 'max_join_size';

Para obtener una lista de variables cuyos nombres coinciden con un patrón, use el comodín '`%`':

    SHOW VARIABLES LIKE 'have%';
    SHOW GLOBAL VARIABLES LIKE 'have%';

El comodín puede usarse en cualquier posición dentro del patrón para coincidir.

Puede obtener el valor de un valor específico usando la sintaxis `@@[global.|local.]var_name` con `SELECT`:

    SELECT @@max_join_size, @@global.max_join_size;

Cuando recibe una variable con `SELECT @@var_name` (esto es,no especifica `global.`, `session.`, o `local.`), MySQL retorna el valor `SESSION` si existe y el valor `GLOBAL` en otro caso.

La siguiente lista describe variables que tienen sintaxis no estándar o que no se describe en la lista de variables de sistema que se encuentra en Sección 5.3.3, “Variables de sistema del servidor”. Aunque estas variables no se muestran con `SHOW VARIABLES`, puede obtener sus valores con `SELECT` (con la excepción de `CHARACTER SET` y `SET NAMES`). Por ejemplo:

    mysql> SELECT @@AUTOCOMMIT;
    +--------------+
    | @@autocommit |
    +--------------+
    |            1 |
    +--------------+

- `AUTOCOMMIT = {0 | 1}`

  Pone el modo autocommit . Con valor `1`, todos los cambios de una tabla toman efecto inmediatamente. Si se pone a `0`, debe usar `COMMIT` para aceptar una transacción o `ROLLBACK` para cancelarla. Si cambia el modo `AUTOCOMMIT` de `0` a `1`, MySQL realiza un `COMMIT` automático de cualquier transacción abierta . Otra forma de comenzar una transacción es usar un comando `START TRANSACTION` o `BEGIN`. Consulte Sección 13.4.1, “Sintaxis de `START TRANSACTION`, `COMMIT` y `ROLLBACK`”.

- `BIG_TABLES = {0 | 1}`

  Si se pone a `1`, todas las tablas temporales se almacenan en disco en lugar que en memoria. Esto es un poco lento, pero el error `The table `tbl_name` is full` no ocurre para operaciones `SELECT` que requieran una tabla temporal grande. El valor por defecto para una nueva conexión es `0` (use tablas temporales en memoria). Normalmente, nunca debería necesitar usar esta variable, ya que MySQL 5.0 convierte automáticamente tablas en memoria a tablas en disco como se requiere. (Nota: Esta variable se llamaba préviamente `SQL_BIG_TABLES`.)

- `CHARACTER SET {`charset_name` | DEFAULT}`

  Esto mapea todas las cadenas desde y hacia el cliente con el mapeo dado. Puede añadir nuevos mapeos editando `sql/convert.cc` en la distribución fuente MySQL. En MySQL 5.0, `SET CHARACTER SET` cambia tres variables de sistema `character_set_client` y `character_set_results` se actualizan con el conjunto de carácteres dado, y `character_set_connection` al valor de `character_set_database`.

  El mapeo por defecto puede restaurarse usando el valor `DEFAULT`.

  Tenga en cuenta que la sintaxis para `SET CHARACTER SET` difiere de la de la mayoría de otras opciones.

- `FOREIGN_KEY_CHECKS = {0 | 1}`

  Con valor de `1` (por defecto), las claves foráneas para tablas `InnoDB` se chequean. Si se pone a `0`, se ignoran. Deshabilitar el chequeo de clave foránea puede ser útil para recargar tablas `InnoDB` en un orden distinto que el requerido por sus relaciones padre/hijo, Consulte Sección 15.6.4, “Restricciones (constraints) `FOREIGN KEY`”.

- `IDENTITY = `value``

  La variable es un sinónimo para la variable `LAST_INSERT_ID` . Existe por compatibilidad con otras bases de datos. Puede leer su valor con `SELECT @@IDENTITY`, y cambiarlo mediante `SET IDENTITY`.

- `INSERT_ID = `value``

  Cambia el valor a ser usado por los comandos `INSERT` o `ALTER TABLE` al insertar un valor `AUTO_INCREMENT` . Esto se usa principalmente con el lob binario.

- `LAST_INSERT_ID = `value``

  Cambia el valor a ser retornado de `LAST_INSERT_ID()`. Esto se almacena en el log binario cuando usa `LAST_INSERT_ID()` en un comando que actualice una tabla. Cambiar esta variable no actualiza el valor retornado por la función de la `mysql_insert_id()` API de C.

- `NAMES {'`charset_name`' | DEFAULT}`

  `SET NAMES` cambia tres variables de sesión de sistema `character_set_client`, `character_set_connection`, y `character_set_results` al conjunto de carácteres dado. Cambiar `character_set_connection` a `charset_name` también cambia `collation_connection` a la colación por defecto para `charset_name`.

  El mapeo por defecto puede restaurarse usando un valor de `DEFAULT`.

  Tenga en cuenta que la sintaxis para `SET NAMES` difiere de la usada para la mayoría de otras opciones.

- `SQL_NOTES = {0 | 1}`

  Con el valor 1 (por defecto), advertencias del nivel `Note` se registran. Con valor 0, las advertencias `Note` se suprimen. mysqldump incluye la salida para cambiar esta variable a 0 así que recargar el fichero volcado no produce advertencias para eventos que no afectan a la integridad de la operación de recarga. `SQL_NOTES` se añadió en MySQL 5.0.3.

- `SQL_AUTO_IS_NULL = {0 | 1}`

  Con valor `1` (por defecto), puede encontrar el último registro insertado para una tabla que contiene una columna `AUTO_INCREMENT` usando el siguiente constructor:

      WHERE auto_increment_column IS NULL

  Este comportamiento lo usan algunos programas ODBC, como Access.

- `SQL_BIG_SELECTS = {0 | 1}`

  Con valor `0`, MySQL aborta los comandos `SELECT` que probablemente tardarán mucho tiempo (esto es, comandos para los que el optimizador estima que el número de registros examinados excede el valor de `max_join_size`). Esto es útil cuando un comando `WHERE` no aconsejable se ejecuta. El valor por defecto para una nueva conexión es `1`, que permite todos los comandos `SELECT` .

  Si cambia la variable de sistema `max_join_size` a un valor distinto a `DEFAULT`, `SQL_BIG_SELECTS` se pone a `0`.

- `SQL_BUFFER_RESULT = {0 | 1}`

  `SQL_BUFFER_RESULT` fuerza los resultados de los comandos `SELECT` a poner en tablas temporales. Esto ayuda a MySQL a liberar los bloqueos de tabla rápidamente y pueden ser beneficioso en caso que tarde un largo tiempo para enviar resultados al cliente.

- `SQL_LOG_BIN = {0 | 1}`

  Con valor `0`, no se realiza logueo en el log binario para el cliente. El cliente debe tener el permiso `SUPER` para cambiar esta opción.

- `SQL_LOG_OFF = {0 | 1}`

  Con valor `1`, no se realiza logueo en el log de consultas generales para el cliente. El cliente debe tener el permiso `SUPER` para cambiar esta opción.

- `SQL_LOG_UPDATE = {0 | 1}`

  Esta variable está obsoleta, y es mapea a `SQL_LOG_BIN`.

- `SQL_QUOTE_SHOW_CREATE = {0 | 1}`

  Con valor `1`, `SHOW CREATE TABLE` entrecomilla los nombres de tabla y columnas. Si se pone a `0`, se desactiva el entrecomillado. Esta opción está activada por defecto, así que la replicación funciona para tablas con nombres de tabla y columna que no lo requieren. Consulte Sección 13.5.4.5, “Sintaxis de `SHOW CREATE TABLE`”.

- `SQL_SAFE_UPDATES = {0 | 1}`

  Con valor `1`, MySQL aborta comandos `UPDATE` o `DELETE` que no usan una clave en la cláusula `WHERE` o `LIMIT` . Esto hace posible cazar los comandos `UPDATE` o `DELETE` donde las claves no se usan apropiadamente y que probablemente cambiarían o borrarían un gran número de registros.

- `SQL_SELECT_LIMIT = {`value` | DEFAULT}`

  El máximo número de registros a retornar desde comandos `SELECT` . El valor por defecto para una nueva conexión es “unlimited.” Si cambia este límite, el valor por defecto puede restaurarse usando un valor `SQL_SELECT_LIMIT` de `DEFAULT`.

  Si un `SELECT` tiene una cláusula `LIMIT` el `LIMIT` tiene preferencia sobre el valor de `SQL_SELECT_LIMIT`.

  `SQL_SELECT_LIMIT` no se aplica a comandos `SELECT` ejecutados en rutinas almacenadas. Tampoco se aplica a comandos `SELECT` que no producen un conjunto de resultados a ser retornado al cliente. Esto incluye comandos `SELECT` en subconsultas, `CREATE TABLE ... SELECT`, y `INSERT INTO ... SELECT`.

- `SQL_WARNINGS = {0 | 1}`

  Esta variable controla si comandos `INSERT` de un registro producen una cadena de información si hay una advertencia. Por defecto es 0. Cambie el valor a 1 para producir una cadena de información.

- `TIMESTAMP = {`timestamp_value` | DEFAULT}`

  Cambia la hora del cliente. Se usar para obtener la fecha y hora original si usa el log binario para restaurar registros. `timestamp_value` debe ser un Unix epoch timestamp, no un timestamp de MySQL.

- `UNIQUE_CHECKS = {0 | 1}`

  Con valor `1` (por defecto), se realizan chequeos en tablas `InnoDB` para índices secundarios. Con valor `0`, no se hacen chequeos de valores únicos para entradas de índices insertados en el búffer de inserción de InnoDB. Si sabe con certeza que sus datos no contienen violaciones de valores únicos, puede ponerlo a 0 para acelerar importaciones de tablas grandes a InnoDB.

### 13.5.4. Sintaxis de `SHOW`

`SHOW` tiene varias formas que proporcionan información acerca de bases de datos, tablas, columnas o información de estado acerca del servidor. Esta sección describe estos puntos:

    SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
    SHOW CREATE DATABASE db_name
    SHOW CREATE TABLE tbl_name
    SHOW DATABASES [LIKE 'pattern']
    SHOW ENGINE engine_name {LOGS | STATUS }
    SHOW [STORAGE] ENGINES
    SHOW ERRORS [LIMIT [offset,] row_count]
    SHOW GRANTS FOR user
    SHOW INDEX FROM tbl_name [FROM db_name]
    SHOW INNODB STATUS
    SHOW [BDB] LOGS
    SHOW PRIVILEGES
    SHOW [FULL] PROCESSLIST
    SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']
    SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
    SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
    SHOW TRIGGERS
    SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
    SHOW WARNINGS [LIMIT [offset,] row_count]

El comando `SHOW` también tiene formas que proporcionan información acerca de servidores de replicación maestros y esclavos y se describen en Sección 13.6, “Sentencias de replicación”:

    SHOW BINLOG EVENTS
    SHOW MASTER LOGS
    SHOW MASTER STATUS
    SHOW SLAVE HOSTS
    SHOW SLAVE STATUS

En la sintaxis para un comando `SHOW` dado incluye una parte `LIKE '`pattern`'` , `'`pattern`'` es una cadena que puede contener los carácteres de SQL '`%`' y '`_`' . El patrón es útil para restringir la salida del comando para valores coincidentes.

#### 13.5.4.1. Sintaxis de `SHOW CHARACTER SET`

    SHOW CHARACTER SET [LIKE 'pattern']

El comando `SHOW CHARACTER SET` muestra todos los conjuntos de carácteres disponibles. Esto tiene una cláusula `LIKE` opcional que indica qué nombres de conjuntos de carácteres hay coincidentes. Por ejemplo:

    mysql> SHOW CHARACTER SET LIKE 'latin%';
    +---------+-----------------------------+-------------------+--------+
    | Charset | Description                 | Default collation | Maxlen |
    +---------+-----------------------------+-------------------+--------+
    | latin1  | ISO 8859-1 West European    | latin1_swedish_ci |      1 |
    | latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
    | latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
    | latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
    +---------+-----------------------------+-------------------+--------+

La columna `Maxlen` muestra el máximo número de bytes usados para almacenar un carácter.

#### 13.5.4.2. Sintaxis de `SHOW COLLATION`

    SHOW COLLATION [LIKE 'pattern']

La salida de `SHOW COLLATION` incluye todos los conjuntos de carácteres disponibles. Tiene una cláusula `LIKE` opcional cuyo `pattern` indica qué nombres de colación coinciden. Por ejemplo:

    mysql> SHOW COLLATION LIKE 'latin1%';
    +-------------------+---------+----+---------+----------+---------+
    | Collation         | Charset | Id | Default | Compiled | Sortlen |
    +-------------------+---------+----+---------+----------+---------+
    | latin1_german1_ci | latin1  |  5 |         |          |       0 |
    | latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
    | latin1_danish_ci  | latin1  | 15 |         |          |       0 |
    | latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
    | latin1_bin        | latin1  | 47 |         | Yes      |       0 |
    | latin1_general_ci | latin1  | 48 |         |          |       0 |
    | latin1_general_cs | latin1  | 49 |         |          |       0 |
    | latin1_spanish_ci | latin1  | 94 |         |          |       0 |
    +-------------------+---------+----+---------+----------+---------+

La columna `Default` indica si una colación está por defecto para su conjunto de carácteres. `Compiled` indica si el conjunto de carácteres está compilado en el servidor. `Sortlen` está relacionado con la cantidad de memoria requerida para ordenar cadenas expresadas en el conjunto de carácteres.

#### 13.5.4.3. Sintaxis de `SHOW COLUMNS`

    SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']

`SHOW COLUMNS` muestra información acerca de las columnas en una tabla dada. También funciona para vistas desde MySQL 5.0.1.

Si los tipos de columnas difieren de los que espera basados en su comando `CREATE TABLE`, tenga en cuenta que MySQL a veces cambia tipos de columnas cuando crea o altera una tabla. Las condiciones en que esto ocurre se describen en Sección 13.1.5.1, “Cambios tácitos en la especificación de columnas”.

La palabra clave `FULL` hace que la salida incluya los permisos que tiene así como cualquier comentario por columna para cada columna.

Puede usar `db_name.tbl_name` como alternativa a la sintaxis ``tbl_name` FROM `db_name`` . En otras palabras, estos dos comandos son equivalentes:

    mysql> SHOW COLUMNS FROM mytable FROM mydb;
    mysql> SHOW COLUMNS FROM mydb.mytable;

`SHOW FIELDS` es un sinónimo para `SHOW COLUMNS`. Puede listar las columnas de una tabla con el comando mysqlshow `db_name` `tbl_name` .

El comando `DESCRIBE` proporciona información similar a `SHOW COLUMNS`. Consulte Sección 13.3.1, “Sintaxis de `DESCRIBE` (Información acerca de las columnas)”.

#### 13.5.4.4. Sintaxis de `SHOW CREATE DATABASE`

    SHOW CREATE {DATABASE | SCHEMA} db_name

Muestra un comando `CREATE DATABASE` que crea la base de datos dada. `SHOW CREATE SCHEMA` puede usarse desde MySQL 5.0.2.

    mysql> SHOW CREATE DATABASE test\G
    *************************** 1. row ***************************
           Database: test
    Create Database: CREATE DATABASE `test`
                     /*!40100 DEFAULT CHARACTER SET latin1 */

#### 13.5.4.5. Sintaxis de `SHOW CREATE TABLE`

    SHOW CREATE TABLE tbl_name

Muestra un comando `CREATE TABLE` que crea la tabla dada. Desde MySQL 5.0.1, este comando funciona con vistas.

    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row ***************************
           Table: t
    Create Table: CREATE TABLE t (
      id INT(11) default NULL auto_increment,
      s char(60) default NULL,
      PRIMARY KEY (id)
    ) ENGINE=MyISAM

`SHOW CREATE TABLE` entrecomilla los nombres de tabla y columna según el valor de la opción `SQL_QUOTE_SHOW_CREATE` . Sección 13.5.3, “Sintaxis de `SET`”.

#### 13.5.4.6. Sintaxis de `SHOW DATABASES`

    SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']

`SHOW DATABASES` lista la base de datos en el servidor MySQL . Puede obtener esta lista usando el comando mysqlshow . En MySQL 5.0, ve sólo las bases de datos para las que tiene alguna clase de permiso, si no tiene el permiso `SHOW DATABASES` .

Si el servidor se arrancó con la opción `--skip-show-database` , no puede usar este comando a no ser que tenga el permiso `SHOW DATABASES` .

`SHOW SCHEMAS` puede usarse desde MySQL 5.0.2

#### 13.5.4.7. Sintaxis de `SHOW ENGINE`

    SHOW ENGINE engine_name {LOGS | STATUS }

`SHOW ENGINE` muestra información de log o estado acerca de motores de almacenamiento. Los siguientes comandos se soportan actualmente:

    SHOW ENGINE BDB LOGS
    SHOW ENGINE INNODB STATUS

`SHOW ENGINE BDB LOGS` muestra información de estado acerca de ficheros de log `BDB` existentes. Retorna los siguientes campos:

- `File`

  Ruta completa al fichero de log.

- `Type`

  Tipo del fichero de log (`BDB` para ficheros de log Berkeley DB).

- `Status`

  Estado del fichero de log (`FREE` si el fichero puede borrarse, o `IN USE` si el fichero se necesita en el subsistema de transacción)

`SHOW ENGINE INNODB STATUS` muestra información extendida acerca del estado del comando `InnoDB` .

Sinónimos antiguos (ahora obsoletos) para estos comandos son `SHOW [BDB] LOGS` y `SHOW INNODB STATUS`.

`SHOW ENGINE` puede usarse desde MySQL 4.1.2.

#### 13.5.4.8. Sintaxis de `SHOW ENGINES`

    SHOW [STORAGE] ENGINES

`SHOW ENGINES` muestra su información de estado acerca del motor de almacenamiento. Esto es particularmente útil para chequear si un motor de almacenamiento se soporta, o para ver si el motr es. `SHOW TABLE TYPES` es un sinónimo obsoleto.

    mysql> SHOW ENGINES\G
    *************************** 1. row ***************************
    Engine: MyISAM
    Support: DEFAULT
    Comment: Default engine as of MySQL 3.23 with great performance
    *************************** 2. row ***************************
    Engine: MEMORY
    Support: YES
    Comment: Hash based, stored in memory, useful for temporary tables
    *************************** 3. row ***************************
    Engine: HEAP
    Support: YES
    Comment: Alias for MEMORY
    *************************** 4. row ***************************
    Engine: MERGE
    Support: YES
    Comment: Collection of identical MyISAM tables
    *************************** 5. row ***************************
    Engine: MRG_MYISAM
    Support: YES
    Comment: Alias for MERGE
    *************************** 6. row ***************************
    Engine: ISAM
    Support: NO
    Comment: Obsolete storage engine, now replaced by MyISAM
    *************************** 7. row ***************************
    Engine: MRG_ISAM
    Support: NO
    Comment: Obsolete storage engine, now replaced by MERGE
    *************************** 8. row ***************************
    Engine: InnoDB
    Support: YES
    Comment: Supports transactions, row-level locking, and foreign keys
    *************************** 9. row ***************************
    Engine: INNOBASE
    Support: YES
    Comment: Alias for INNODB
    *************************** 10. row ***************************
    Engine: BDB
    Support: YES
    Comment: Supports transactions and page-level locking
    *************************** 11. row ***************************
    Engine: BERKELEYDB
    Support: YES
    Comment: Alias for BDB
    *************************** 12. row ***************************
    Engine: NDBCLUSTER
    Support: NO
    Comment: Clustered, fault-tolerant, memory-based tables
    *************************** 13. row ***************************
    Engine: NDB
    Support: NO
    Comment: Alias for NDBCLUSTER
    *************************** 14. row ***************************
    Engine: EXAMPLE
    Support: NO
    Comment: Example storage engine
    *************************** 15. row ***************************
    Engine: ARCHIVE
    Support: YES
    Comment: Archive storage engine
    *************************** 16. row ***************************
    Engine: CSV
    Support: NO
    Comment: CSV storage engine
    *************************** 17. row ***************************
    Engine: FEDERATED
    Support: YES
    Comment: Federated MySQL storage engine
    *************************** 18. row ***************************
    Engine: BLACKHOLE
    Support: YES
    Comment: /dev/null storage engine (anything you write to it disappears)

Un valor `Support` indica si el motor se soporta, y cuál está activo por defecto. Por ejemplo, si el servidor se arranca con la opción `--default-table-type=InnoDB`, el valor `Support` para el registro `InnoDB` tiene el valor `DEFAULT`.

#### 13.5.4.9. Sintaxis de `SHOW ERRORS`

    SHOW ERRORS [LIMIT [offset,] row_count]
    SHOW COUNT(*) ERRORS

Este comando es similar a `SHOW WARNINGS`, excepto que en lugar de mostrar errores, advertencias, y notas sólo muestra errores.

La cláusula `LIMIT` tiene la misma sintaxis que para el comando `SELECT` . Consulte Sección 13.2.7, “Sintaxis de `SELECT`”.

El comando `SHOW COUNT(*) ERRORS` muestra el número de errores. Puede recibir este número de la variable `error_count` :

    SHOW COUNT(*) ERRORS;
    SELECT @@error_count;

Para más información consulte Sección 13.5.4.22, “Sintaxis de `SHOW WARNINGS`”.

#### 13.5.4.10. Sintaxis de `SHOW GRANTS`

    SHOW GRANTS FOR user

Este comando lista el comando `GRANT` que debe realizarse para duplicar los permisos para una cuenta de usuario MySQL.

    mysql> SHOW GRANTS FOR 'root'@'localhost';
    +---------------------------------------------------------------------+
    | Grants for root@localhost                                           |
    +---------------------------------------------------------------------+
    | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
    +---------------------------------------------------------------------+

Para listar los permisos de la sesión actual, puede usar cualquiera de los siguientes comandos:

    SHOW GRANTS;
    SHOW GRANTS FOR CURRENT_USER;
    SHOW GRANTS FOR CURRENT_USER();

#### 13.5.4.11. Sintaxis de `SHOW INDEX`

    SHOW INDEX FROM tbl_name [FROM db_name]

`SHOW INDEX` retorna información de índice de tabla en un formato que recuerda la llamada `SQLStatistics` en ODBC.

`SHOW INDEX` returna los siguientes campso:

- `Table`

  Nombre de tabla.

- `Non_unique`

  0 si el índice no puede contener duplicados, 1 si puede.

- `Key_name`

  Nombre del índice

- `Seq_in_index`

  Número de secuencia de columna en el índice, comenzando con 1.

- `Column_name`

  Nombre de columna.

- `Collation`

  Cómo se ordena la columan en el índice. En MySQL, puede tener valores '`A`' (Ascendente) o `NULL` (No ordenado).

- `Cardinality`

  Número de valores únicos en el índice. Se actualiza ejecutando `ANALYZE TABLE` o myisamchk -a. `Cardinality` se cuenta basándose en las estadísticas almacenadas como enteros, así que no es necesariamente precisa para tablas pequeñas. Mientras más grande sea, más grande es la probabilidad que MySQL use el índice al hacer joins.

- `Sub_part`

  Número de carácteres indexados si la columna sólo está indexada parcialmente. `NULL` si la columna entera está indexada.

- `Packed`

  Indica cómo está empaquetada la clave. `NULL` si no lo está.

- `Null`

  Contiene `YES` si la columna puede contener `NULL`. Si no, la columna contiene `NO` desde MySQL 5.0.3, y `''` antes.

- `Index_type`

  Método de índice usado (`BTREE`, `FULLTEXT`, `HASH`, `RTREE`).

- `Comment`

  Comentarios varios.

Puede usar `db_name.tbl_name` como alternativa para la sintaxis ``tbl_name` FROM `db_name`` . Estos dos comandos son equivalentes:

    mysql> SHOW INDEX FROM mytable FROM mydb;
    mysql> SHOW INDEX FROM mydb.mytable;

`SHOW KEYS` es sinónimo para `SHOW INDEX`. Puede listar los índices de una tabla con el comando mysqlshow -k `db_name` `tbl_name` .

#### 13.5.4.12. Sintaxis de `SHOW INNODB STATUS`

    SHOW INNODB STATUS

En MySQL 5.0, este es un sinónimo obsoleto para `SHOW ENGINE INNODB STATUS`. Consulte Sección 13.5.4.7, “Sintaxis de `SHOW ENGINE`”.

#### 13.5.4.13. Sintaxis de `SHOW LOGS`

    SHOW [BDB] LOGS

En MySQL 5.0, este es un sinónimo obsoleto para `SHOW ENGINE BDB LOGS`. Consulte Sección 13.5.4.7, “Sintaxis de `SHOW ENGINE`”.

#### 13.5.4.14. Sintaxis de `SHOW OPEN TABLES`

    SHOW OPEN TABLES

`SHOW OPEN TABLES` lista las tablas no `TEMPORARY` abiertas actualmente en la caché de tablas. Consulte Sección 7.4.8, “Cómo abre y cierra tablas MySQL”.

`SHOW OPEN TABLES` returna los siguientes campos:

- `Database`

  La base de datos que contiene la tabla.

- `Table`

  Nombre de tabla.

- `In_use`

  Número de veces que la tabla está en uso para consultas. Si el contador es cero, la tabla está abierta, pero no está siendo usada.

- `Name_locked`

  Si un nombre de tabla está bloqueado. El bloqueo de nombres se usa para operaciones tales como borrar o renombrar tablas.

`SHOW OPEN TABLES` se añadió en MySQL 3.23.33.

#### 13.5.4.15. Sintaxis de `SHOW PRIVILEGES`

    SHOW PRIVILEGES

`SHOW PRIVILEGES` muestra la lista de permisos de sistema que soporta MySQL server. La salida exacta depende de la versión de su servidor.

    mysql> SHOW PRIVILEGES\G
    *************************** 1. row ***************************
    Privilege: Alter
    Context: Tables
    Comment: To alter the table
    *************************** 2. row ***************************
    Privilege: Alter routine
    Context: Functions,Procedures
    Comment: To alter or drop stored functions/procedures
    *************************** 3. row ***************************
    Privilege: Create
    Context: Databases,Tables,Indexes
    Comment: To create new databases and tables
    *************************** 4. row ***************************
    Privilege: Create routine
    Context: Functions,Procedures
    Comment: To use CREATE FUNCTION/PROCEDURE
    *************************** 5. row ***************************
    Privilege: Create temporary tables
    Context: Databases
    Comment: To use CREATE TEMPORARY TABLE
    *************************** 6. row ***************************
    Privilege: Create view
    Context: Tables
    Comment: To create new views
    *************************** 7. row ***************************
    Privilege: Create user
    Context: Server Admin
    Comment: To create new users
    *************************** 8. row ***************************
    Privilege: Delete
    Context: Tables
    Comment: To delete existing rows
    *************************** 9. row ***************************
    Privilege: Drop
    Context: Databases,Tables
    Comment: To drop databases, tables, and views
    *************************** 10. row ***************************
    Privilege: Execute
    Context: Functions,Procedures
    Comment: To execute stored routines
    *************************** 11. row ***************************
    Privilege: File
    Context: File access on server
    Comment: To read and write files on the server
    *************************** 12. row ***************************
    Privilege: Grant option
    Context: Databases,Tables,Functions,Procedures
    Comment: To give to other users those privileges you possess
    *************************** 13. row ***************************
    Privilege: Index
    Context: Tables
    Comment: To create or drop indexes
    *************************** 14. row ***************************
    Privilege: Insert
    Context: Tables
    Comment: To insert data into tables
    *************************** 15. row ***************************
    Privilege: Lock tables
    Context: Databases
    Comment: To use LOCK TABLES (together with SELECT privilege)
    *************************** 16. row ***************************
    Privilege: Process
    Context: Server Admin
    Comment: To view the plain text of currently executing queries
    *************************** 17. row ***************************
    Privilege: References
    Context: Databases,Tables
    Comment: To have references on tables
    *************************** 18. row ***************************
    Privilege: Reload
    Context: Server Admin
    Comment: To reload or refresh tables, logs and privileges
    *************************** 19. row ***************************
    Privilege: Replication client
    Context: Server Admin
    Comment: To ask where the slave or master servers are
    *************************** 20. row ***************************
    Privilege: Replication slave
    Context: Server Admin
    Comment: To read binary log events from the master
    *************************** 21. row ***************************
    Privilege: Select
    Context: Tables
    Comment: To retrieve rows from table
    *************************** 22. row ***************************
    Privilege: Show databases
    Context: Server Admin
    Comment: To see all databases with SHOW DATABASES
    *************************** 23. row ***************************
    Privilege: Show view
    Context: Tables
    Comment: To see views with SHOW CREATE VIEW
    *************************** 24. row ***************************
    Privilege: Shutdown
    Context: Server Admin
    Comment: To shut down the server
    *************************** 25. row ***************************
    Privilege: Super
    Context: Server Admin
    Comment: To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
    *************************** 26. row ***************************
    Privilege: Update
    Context: Tables
    Comment: To update existing rows
    *************************** 27. row ***************************
    Privilege: Usage
    Context: Server Admin
    Comment: No privileges - allow connect only

#### 13.5.4.16. Sintaxis de `SHOW PROCESSLIST`

    SHOW [FULL] PROCESSLIST

`SHOW PROCESSLIST` le muestra qué flujos están en ejecución. Puede obtener esta información usando el comando mysqladmin processlist . Si tiene el permiso `SUPER` , puede ver todos los flujos. De otro modo, puede ver sólo los propios (esto es, flujos asociados con la cuenta MySQL que está usando). Consulte Sección 13.5.5.3, “Sintaxis de `KILL`”. Si no usa la palabra clave `FULL` , sólo los primeros 100 carácteres de cada consulta se muestran.

En MySQL 5.0, el comando reporta el nombre de equipo ara conexiones TCP/IP en formato ``host_name`:`client_port`` para hacer más fácil determinar qué hace cada cliente.

Este comando es útil si obtiene el mensaje de error "demasiadas conexiones" para encontrar qué ocurre. MySQL reserva una conexión extra para usar por cuentas con el permiso `SUPER`, para asegurar que el administrador siempre es capaz de conectar y comprobar el sistema (asumiendo que no da este permiso a todos los usuarios).

Algunos estados vistos comúnmente en la salida de `SHOW PROCESSLIST`:

- `Checking table`

  El flujo está realizando un chequeo (automático) de la tabla.

- `Closing tables`

  Significa que el flujo está volcando los datos que han cambiado de la tabla a disco y cerrando las tablas usadas. Esto debe ser una operación rápido. Si no lo es, debe verificar que no tiene el disco lleno y que el disco no tiene un uso muy pesado.

- `Connect Out`

  Esclavo conectando con el maestro.

- `Copying to tmp table on disk`

  El conjunto de resultados temporal era mayor que `tmp_table_size` y el flujo está cambiando la tabla temporal de memoria a disco para ahorrar memoria.

- `Creating tmp table`

  El flujo está creando una tabla temporal para guardar parte del resultado de una consulta.

- `deleting from main table`

  El servidor está ejecutando la primera parte de un borrado de tablas múltiple y borrando sólo la primera tabla.

- `deleting from reference tables`

  El servidor está ejecutando la segunda parte de un borrado de tablas múltiples y borrando los registros coincidentes de las otras tablas.

- `Flushing tables`

  El flujo está ejecutando `FLUSH TABLES` y espera a que todos los flujos cierren sus tablas.

- `Killed`

  Alguien ha enviado un comando `KILL` al flujo y debería abortar en cuanto chequee el flag kill. El flag se chequea en cada vuelta al bucle principal de MySQL, pero en algunos casos puede tardar algo de tiempo en que muera el flujo. Si el flujo está bloqueado por algún otro flujo, el kill tiene efecto en cuanto el otro flujo libera el bloqueo.

- `Locked`

  La consulta está bloqueada por otra consulta.

- `Sending data`

  El flujo está procesando registros para un comando `SELECT` y también enviando datos al cliente.

- `Sorting for group`

  El flujo está ordenando para un `GROUP BY`.

- `Sorting for order`

  El flujo está ordenando para un `ORDER BY`.

- `Opening tables`

  El flujo está intentando abrir una tabla. Esto debería ser un proceso muy rápido, a no ser que algo importante evite la abertura. Por ejemplo, un comando `ALTER TABLE` o `LOCK TABLE` puede evitar abrir una tabla hasta que el comando acabe.

- `Removing duplicates`

  La consulta usaba `SELECT DISTINCT` de forma que MySQL no podía optimizar las distintas operaciones en una fase temprana. Debido a ello, MySQL necesita una fase extra para borrar todos los registros duplicados antes de enviar el resultado al cliente.

- `Reopen table`

  El flujo obtivo un bloqueo para la tabla, pero se dio cuenta tras obtenerlo que la estructura de la tabla cambió. Se libera el bloqueo, cierra la tabla y trata de reabrirla.

- `Repair by sorting`

  El código de reparación está usando una ordenación para crear índices.

- `Repair with keycache`

  El código de reparación está usando creación de claves una a una en la caché de claves. Esto es mucho más lento que `Repair by sorting`.

- `Searching rows for update`

  El flujo hace una primera fase para encontrar todos los registro coincidentes antes de actualizarlos. Esto debe hacerse si `UPDATE` está cambiando el índice que se usa para encontrar los registros implicados.

- `Sleeping`

  El flujo espera que el cliente envíe un nuevo comando .

- `System lock`

  El flujo espera obtener un bloqueo de sistema externo para la tabla. Si no está usando múltiples servidors mysqld accediendo a las mismas tablas, puede deshabilitar los bloqueos de sistema con la opción `--skip-external-locking` .

- `Upgrading lock`

  El handler `INSERT DELAYED` trata de obtener un bloqueo para la tabla para insertar registros.

- `Updating`

  El flujo está buscando registros para actualizar.

- `User Lock`

  El flujo espera un `GET_LOCK()`.

- `Waiting for tables`

  El flujo obtuvo una notificación que la estructura de la tabla cambió y necesita reabrirla. Sin embargo, para ello, debe esperar a que el resto de flujos cierren la tabla en cuestión.

  Esta notificación tiene lugar si otro flujo ha usado `FLUSH TABLES` o uno de los siguientes comandos en la tabla en cuestión: `FLUSH TABLES `tbl_name``, `ALTER TABLE`, `RENAME TABLE`, `REPAIR TABLE`, `ANALYZE TABLE`, o `OPTIMIZE TABLE`.

- `waiting for handler insert`

  El handler `INSERT DELAYED` ha procesado las inserciones pendientes y espera nuevas.

La mayoría de estados se corresponden a operaciones rápidas. Si un flujo está en alguno de ellos varios segundos, puede existir un problema que necesite investigar.

Hay algunos estdos que no se mencionan en la lista precedente, pero varios de ellos son útiles sólo para encontrar fallos en el servidor.

#### 13.5.4.17. Sintaxis de `SHOW STATUS`

    SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern']

`SHOW STATUS` proporciona información de estado del servidor. Esta información puede obtenerse usando el comando mysqladmin extended-status .

Aquí se muestra una salida parcial. La lista de variables y sus vallires pueden ser distintos para su servidor. El significado de cada variable se da en Sección 5.3.4, “Variables de estado del servidor”.

    mysql> SHOW STATUS;
    +--------------------------+------------+
    | Variable_name            | Value      |
    +--------------------------+------------+
    | Aborted_clients          | 0          |
    | Aborted_connects         | 0          |
    | Bytes_received           | 155372598  |
    | Bytes_sent               | 1176560426 |
    | Connections              | 30023      |
    | Created_tmp_disk_tables  | 0          |
    | Created_tmp_tables       | 8340       |
    | Created_tmp_files        | 60         |
    ...                       ...          ...
    | Open_tables              | 1          |
    | Open_files               | 2          |
    | Open_streams             | 0          |
    | Opened_tables            | 44600      |
    | Questions                | 2026873    |
    ...                       ...          ...
    | Table_locks_immediate    | 1920382    |
    | Table_locks_waited       | 0          |
    | Threads_cached           | 0          |
    | Threads_created          | 30022      |
    | Threads_connected        | 1          |
    | Threads_running          | 1          |
    | Uptime                   | 80380      |
    +--------------------------+------------+

Con una cláusula `LIKE` , el comando muestra sólo las variables que coinciden con el patrón:

    mysql> SHOW STATUS LIKE 'Key%';
    +--------------------+----------+
    | Variable_name      | Value    |
    +--------------------+----------+
    | Key_blocks_used    | 14955    |
    | Key_read_requests  | 96854827 |
    | Key_reads          | 162040   |
    | Key_write_requests | 7589728  |
    | Key_writes         | 3813196  |
    +--------------------+----------+

Las opciones `GLOBAL` y `SESSION` son nuevas en MySQL 5.0.2 Con `GLOBAL`, obtiene los valores de estado para todas las conexiones a MySQL. Con `SESSION`, obtiene los valores de estado para la conexión actual. Si no usa estas opciones, por defecto es `SESSION`. `LOCAL` es sinónimo de `SESSION`.

Tenga en cuenta que algunas variables de estado sólo tienen un valor global. Para ellas obtiene el mismo valor para `GLOBAL` y `SESSION`.

#### 13.5.4.18. Sintaxis de `SHOW TABLE STATUS`

    SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']

`SHOW TABLE STATUS` funciona como `SHOW TABLE`, pero proporciona mucha más información acerca de cada tabla. Puede obtener esta lista usando el comando mysqlshow --status `db_name` . Desde MySQL 5.0.1, este comando también muestra información sobre vistas.

`SHOW TABLE STATUS` returna los siguientes campos:

- `Name`

  Nombre de tabla.

- `Engine`

  Motor para la tabla. Antes de MySQL 4.1.2, este valor se llama `Type`. Consulte Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.

- `Version`

  Número de versión del fichero `.frm` de la tabla.

- `Row_format`

  Formato de almacenamiento de registros (`Fixed`, `Dynamic`, `Compressed`, `Redundant`, `Compact`). Desde MySQL/InnoDB 5.0.3, el formato de tablas InnoDB se reporta como `Redundant` o `Compact`. Antes de 5.0.3, las tablas InnoDB siempre están en formato `Redundant` .

- `Rows`

  Número de registros. Algunos motores como `MyISAM`, guardan el número exacto.

  Para otros motores, como `InnoDB`, este valor es una aproximación y puede variar del valor real hasta de un 40 a 50%. En tales casos, use `SELECT COUNT(*)` para obtener el número real de registros.

  El valor `Rows` es `NULL` para tablas en la base de datos `INFORMATION_SCHEMA` .

- `Avg_row_length`

  Longitud de registro media.

- `Data_length`

  Tamaño del fichero de datos.

- `Max_data_length`

  Máxima longitud del fichero d edatos. Este es el número total de bytes de datos que pueden almacenarse en la tabla dado el tamaño de puntero de datos usado.

- `Index_length`

  Tamaño de fichero índice.

- `Data_free`

  Número de bytes reservados no usados.

- `Auto_increment`

  Siguiente valor `AUTO_INCREMENT` .

- `Create_time`

  Cuándo se creó la tabla .

- `Update_time`

  Cuándo se actualizó por última vez el fichero de datos.

- `Check_time`

  Cuándo se chequeó la tabla por última vez.

- `Collation`

  Conjunto de carácteres y colación de la tabla.

- `Checksum`

  Valor de checksum en vivo (si hay).

- `Create_options`

  Opciones extra usadas con `CREATE TABLE`.

- `Comment`

  Comentario usado al crear la tabla (o información de porqué MySQL no puede acceder a la información de tabla).

En el comentario de tabla, las tablas `InnoDB` reportan el espacio libre del espacio de tabla al que pertenece la tabla. Para una tabla localizada en el espacio compartido, este es el espacio libre del espacio de tabla compartido. Si usa múltiples espacios y la tabla tiene el suyo, el espacio libre es sólo para esa tabla.

Para tablas `MEMORY` (`HEAP`) los valores `Data_length`, `Max_data_length`, y `Index_length` aproximan la cantidad real de memoria reservada. El algoritmo de reserva reserva grandes cantidades de memoria para reducir el número de operaciones de reserva.

Para vistas, todos los campos mostrados por `SHOW TABLE STATUS` son `NULL` excepto que `Name` indicata el nombre de vista y `Comment` dice `view`.

#### 13.5.4.19. Sintaxis de `SHOW TABLES`

    SHOW [FULL] TABLES [FROM db_name] [LIKE 'pattern']

`SHOW TABLES` lista las tablas no `TEMPORARY` en una base de datos dada. Puede obtener esta lista usando el comando mysqlshow `db_name` .

Antes de MySQL 5.0.1, la salida de `SHOW TABLES` contiene una única columna de nombres de tabla. Desde MySQL 5.0.1, este comando lista cualquier vista en la base de datos. Desde MySQL 5.0.2, se soporta el modificador `FULL` de forma que `SHOW FULL TABLES` muestra una segunda columna de salida. Los valores para la segunda columna son `BASE TABLE` para una tabla `VIEW` para una vista.

Nota: Si no tiene permisos para una tabla, la tabla no se muestra en la salida de `SHOW TABLES` o mysqlshow db_name.

#### 13.5.4.20. Sintaxis de `SHOW TRIGGERS`

    SHOW TRIGGERS [FROM db_name] [LIKE expr]

`SHOW TRIGGERS` lista los disparadores definidos en el MySQL server. Se implementó en MySQL 5.0.10.

Para el disparadores `ins_sum` como se define en Sección 20.3, “Utilización de disparadores”, la salida de este comando es la que se muestra:

    mysql> SHOW TRIGGERS LIKE 'acc%';
    +---------+--------+---------+-------------------------------+--------+---------+
    | Trigger | Event  | Table   | Statement                     | Timing | Created |
    +---------+--------+---------+-------------------------------+--------+---------+
    | ins_sum | INSERT | account |  SET @sum = @sum + NEW.amount | BEFORE | NULL    |
    +---------+--------+---------+-------------------------------+--------+---------+

Nota: Cuando use una cláusula `LIKE` con `SHOW TRIGGERS`, la expresión a cumplir (`expr`) se compara con el nombre de la tabla en que se declara el disparador, y no con el nombre del disparador:

    mysql> SHOW TRIGGERS LIKE 'ins%';
    Empty set (0.01 sec)

Aquí se muestra una breve explicación de las columnas de la salida de este comando:

- `Trigger`: Nombre del disparador.

- `Event`: Evento que invoca el disparador. Debe ser `'INSERT'`, `'UPDATE'`, o `'DELETE'`.

- `Table`: La tabla para la que se define el disparador.

- `Statement`: Comando a ejecutar cuando se invoca el disparador. Es lo mismo que el texto mostrado en la columna `ACTION_STATEMENT` de `INFORMATION_SCHEMA.TRIGGERS`.

- `Timing`: Puede ser `'BEFORE'` o `'AFTER'`.

- `Created`: Actualmente el valor de esta columna siempre es `NULL`.

Debe tener el permiso `SUPER` para ejecutar `SHOW TRIGGERS`.

Consulte Sección 22.1.16, “La tabla `INFORMATION_SCHEMA TRIGGERS`”.

#### 13.5.4.21. Sintaxis de `SHOW VARIABLES`

    SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']

`SHOW VARIABLES` muestra los valores de algunas variables de sistema de MySQL. Esta información puede obtenerse usando el comando mysqladmin variables .

Con la opción `GLOBAL`, obtiene los valores que se usan para nuevas conexiones de MySQL. Con `SESSION`, obtiene los valores que hay en efecto para la conexión actual. Si no usa estas opciones, por defecto es `SESSION`.

`LOCAL` es sinónimo de `SESSION`.

Si los valores por defecto no son adecuados, puede cambiar la mayoría de variables usando opciones de línea de comandos cuando mysqld arranca o en tiempo de ejecución con el comando `SET` . Consulte Sección 5.3.1, “Opciones del comando mysqld” y Sección 13.5.3, “Sintaxis de `SET`”.

La salida parcial se muestra aquí. La lista de variables y sus valores pueden ser distintos para su servidor. El significado de cada variable se da en Sección 5.3.3, “Variables de sistema del servidor”. Información acerca de cómo adecuarlos se proporciona en Sección 7.5.2, “Afinar parámetros del servidor”.

    mysql> SHOW VARIABLES;
    +---------------------------------+---------------------------------------------------------+
    | Variable_name                   | Value                                                   |
    +---------------------------------+---------------------------------------------------------+
    | auto_increment_increment        | 1                                                       |
    | auto_increment_offset           | 1                                                       |
    | automatic_sp_privileges         | ON                                                      |
    | back_log                        | 50                                                      |
    | basedir                         | /                                                       |
    | bdb_cache_size                  | 8388600                                                 |
    | bdb_home                        | /var/lib/mysql/                                         |
    | bdb_log_buffer_size             | 32768                                                   |
    ...                               ...                                                       ...
    | max_connections                 | 100                                                     |
    | max_connect_errors              | 10                                                      |
    | max_delayed_threads             | 20                                                      |
    | max_error_count                 | 64                                                      |
    | max_heap_table_size             | 16777216                                                |
    | max_join_size                   | 4294967295                                              |
    | max_relay_log_size              | 0                                                       |
    | max_sort_length                 | 1024                                                    |
    ...                               ...                                                       ...
    | time_zone                       | SYSTEM                                                  |
    | timed_mutexes                   | OFF                                                     |
    | tmp_table_size                  | 33554432                                                |
    | tmpdir                          |                                                         |
    | transaction_alloc_block_size    | 8192                                                    |
    | transaction_prealloc_size       | 4096                                                    |
    | tx_isolation                    | REPEATABLE-READ                                         |
    | updatable_views_with_limit      | YES                                                     |
    | version                         | 5.0.7-beta-Max                                          |
    | version_bdb                     | Sleepycat Software: Berkeley DB 4.1.24: (June 11, 2005) |
    | version_comment                 | MySQL Community Edition - Max (GPL)                     |
    | version_compile_machine         | i686                                                    |
    | version_compile_os              | pc-linux-gnu                                            |
    | wait_timeout                    | 28800                                                   |
    +---------------------------------+---------------------------------------------------------+

Con una cláusula `LIKE` , el comando muestra sólo las variables que coinciden con el patrón:

    mysql> SHOW VARIABLES LIKE 'have%';
    +-----------------------+----------+
    | Variable_name         | Value    |
    +-----------------------+----------+
    | have_archive          | NO       |
    | have_bdb              | YES      |
    | have_blackhole_engine | YES      |
    | have_compress         | YES      |
    | have_crypt            | YES      |
    | have_csv              | YES      |
    | have_example_engine   | YES      |
    | have_federated_engine | YES      |
    | have_geometry         | YES      |
    | have_innodb           | YES      |
    | have_isam             | NO       |
    | have_ndbcluster       | DISABLED |
    | have_openssl          | NO       |
    | have_query_cache      | YES      |
    | have_raid             | NO       |
    | have_rtree_keys       | YES      |
    | have_symlink          | YES      |
    +-----------------------+----------+

#### 13.5.4.22. Sintaxis de `SHOW WARNINGS`

    SHOW WARNINGS [LIMIT [offset,] row_count]
    SHOW COUNT(*) WARNINGS

`SHOW WARNINGS` muestra los mensajes de error, advertencia y notas retornadas por el último comando que haya generado algún mensaje, o nada si el último mensaje que haya usado una tabla no haya generado mensajes. Un comando relacionado, `SHOW ERRORS`, sólo muestra los errores. Consulte Sección 13.5.4.9, “Sintaxis de `SHOW ERRORS`”.

La lista de mensajes se resetea para cada nuevo comando que use una tabla.

El comando `SHOW COUNT(*) WARNINGS` muestra el número total de errores, advertencias y notas. Puede recibir este número de la variable `warning_count` :

    SHOW COUNT(*) WARNINGS;
    SELECT @@warning_count;

El valor de `warning_count` puede ser mayor que el número de mensajes mostrados por `SHOW WARNINGS` si la variable de sistema `max_error_count` tiene un valor tan pequeño que no se almacenen todos los mensajes. Se muestra posteriormente un ejemplo de cómo puede pasar esto.

La cláusula `LIMIT` tiene la misma sintaxis que para el comando `SELECT` . Consulte Sección 13.2.7, “Sintaxis de `SELECT`”.

El servidor MySQL devuelve el número total de errores, advertencias, y notas que hayan resultado desde el último comando. Si usa la API de C, este valor puede obtenerse llamando a `mysql_warning_count()`. Consulte Sección 24.3.3.63, “`mysql_warning_count()`”.

Las advertencias se generan para comandos tales como `LOAD DATA INFILE` y comandos DML tales como `INSERT`, `UPDATE`, `CREATE TABLE`, y `ALTER TABLE`.

El siguiente comando `DROP TABLE` provoca una nota:

    mysql> DROP TABLE IF EXISTS no_such_table;
    mysql> SHOW WARNINGS;
    +-------+------+-------------------------------+
    | Level | Code | Message                       |
    +-------+------+-------------------------------+
    | Note  | 1051 | Unknown table 'no_such_table' |
    +-------+------+-------------------------------+

Aquí hay un ejemplo simple que muesta una advertencia de sintaxis para `CREATE TABLE` y advertencias de conversiones para `INSERT`:

    mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM;
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1287
    Message: 'TYPE=storage_engine' is deprecated, use
             'ENGINE=storage_engine' instead
    1 row in set (0.00 sec)

    mysql> INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'),
        -> (300,'Open Source');
    Query OK, 3 rows affected, 4 warnings (0.01 sec)
    Records: 3  Duplicates: 0  Warnings: 4

    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1265
    Message: Data truncated for column 'b' at row 1
    *************************** 2. row ***************************
      Level: Warning
       Code: 1263
    Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2
    *************************** 3. row ***************************
      Level: Warning
       Code: 1264
    Message: Data truncated, out of range for column 'a' at row 3
    *************************** 4. row ***************************
      Level: Warning
       Code: 1265
    Message: Data truncated for column 'b' at row 3
    4 rows in set (0.00 sec)

El máximo número de errores, advertencias y notas a almacenar se controla mediante la variable de sistema `max_error_count`. Por defecto, su valor es 64. Para cambiar el número de mensajes que quiere almacenar, cambie el valor de `max_error_count`. En el siguiente ejemplo, el comando `ALTER TABLE` produce tres mensajes de advertencia, pero sólo se almacena uno porque `max_error_count` vale 1:

    mysql> SHOW VARIABLES LIKE 'max_error_count';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_error_count | 64    |
    +-----------------+-------+
    1 row in set (0.00 sec)

    mysql> SET max_error_count=1;
    Query OK, 0 rows affected (0.00 sec)

    mysql> ALTER TABLE t1 MODIFY b CHAR;
    Query OK, 3 rows affected, 3 warnings (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 3

    mysql> SELECT @@warning_count;
    +-----------------+
    | @@warning_count |
    +-----------------+
    |               3 |
    +-----------------+
    1 row in set (0.01 sec)

    mysql> SHOW WARNINGS;
    +---------+------+----------------------------------------+
    | Level   | Code | Message                                |
    +---------+------+----------------------------------------+
    | Warning | 1263 | Data truncated for column 'b' at row 1 |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)

Para deshabilitar las advertencias, ponga `max_error_count` a 0. En este caso, `warning_count` indica cuántas advertencias ocurren, pero ninguno de los mensajes se almacenan.

Desde MySQL 5.0.3, puede poner la variable de sesión `SQL_NOTES` a 0 para que las advertencias del nivel `Note` no se guarden.

### 13.5.5. Otras sentencias para la administración

#### 13.5.5.1. Sintaxis de `CACHE INDEX`

    CACHE INDEX
      tbl_index_list [, tbl_index_list] ...
      IN key_cache_name

    tbl_index_list:
      tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]

El comando `CACHE INDEX` asigna índices de tabla a una caché de clave específica. Se usa sólo para tablas `MyISAM` .

El siguiente comando asigna índices de las tablas `t1`, `t2`, y `t3` a la caché de claves llamada `hot_cache`:

    mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
    +---------+--------------------+----------+----------+
    | Table   | Op                 | Msg_type | Msg_text |
    +---------+--------------------+----------+----------+
    | test.t1 | assign_to_keycache | status   | OK       |
    | test.t2 | assign_to_keycache | status   | OK       |
    | test.t3 | assign_to_keycache | status   | OK       |
    +---------+--------------------+----------+----------+

La sintaxis de `CACHE INDEX` le permite especifcar que sólo deben asignarse índicess particulares de una tabla a la caché. Sin embargo, la implementación actual asigna todos los índices de la tabla a la caché, así que no hay razón para especificar nada más que el nombre de tabla.

La caché de clave referenciada en un comando `CACHE INDEX` puede crearse cambiando su tamaño con un comando que asigne un valor al parámetro o en la configuración del parámetro del servidor. Por ejemplo:

    mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

Puede accederse a los parámetros de la caché de claves como miembros de una variable de sistema estructurada. Consulte Sección 9.4.1, “Variables estructuradas de sistema”.

Una caché de claves debe existir antes de asignarle índices:

    mysql> CACHE INDEX t1 IN non_existent_cache;
    ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'

Por defecto, los índices de tabla se asignan a la caché de claves principal (por defecto) creada en el arranque del servidor. Cuando se destruye una caché de índices, todos los índices asignados a la misma se asignan de nuevo a la caché por defecto.

Las asignaciones de índices afectan al servidor globalmente: Si un cliente asigna un índice a una caché dada, esta caché se usa para todas las consultas que tengan que ver con el índice, sin importar qué cliente realiza las consultas.

#### 13.5.5.2. Sintaxis de `FLUSH`

    FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ...

Debe usar el comando `FLUSH` si quiere limpiar algunas de las cachés internas que usa MySQL . Para ejecutar `FLUSH`, debe tener el permiso `RELOAD` .

`flush_option` puede ser cualquiera de los siguientes valores:

- `HOSTS`

  Vacía las tablas de la caché de equipos. Debe volcar las tablas de equipos si algunos de sus equipos cambia el número IP o si obtiene el mensaje de error `Host ... is blocked`. Cuando ocurren sucesivamente más de `max_connect_errors` errores para un equipo dado mientras conecta con el servidor MySQL , MySQL asume que hay algo incorrecto y bloquea el equipo de más peticiones de conexión. Volcar las tablas de equipos le permite al equipo intentar conectar de nuevo. Consulte Sección A.2.5, “`Host '`host_name`' is blocked`”. Puede arrancar mysqld con `--max_connect_errors=999999999` para evitar este mensaje de error.

- `DES_KEY_FILE`

  Recarga las claves DES del fichero que se especifica con la opción `--des-key-file` en tiempo de arranque del servidor.

- `LOGS`

  Cierra y reabre todos los ficheros de log. Si ha especificado un fichero de log de actualizaciones o un fichero de log binario sin una extensión, el número de extensión del fichero de log se incrementa en uno respecto al fichero anterior. Si ha usado una extensión del nombre de fichero, MySQL cierra y reabre el fichero de log. En Unix, esto es lo mismo que enviar una señal `SIGHUP` al servidor mysqld (excepto en algunas versiones Mac OS X 10.3 donde mysqld ignora `SIGHUP` y `SIGQUIT`).

- `PRIVILEGES`

  Recarga los permisos de las tablas de permisos en la base de datos `mysql` .

- `QUERY CACHE`

  Defragmenta caché de consulta para utilizar mejor su memoria. Este comando no borra ninguna consulta de la caché, no como `RESET QUERY CACHE`.

- `STATUS`

  Resetea la mayoría de variables de estado a cero. Esto es algo que debe usar sólo al debugar una consulta. Consulte Sección 1.6.1.3, “Cómo informar de bugs y problemas”.

- `{TABLE | TABLES} [`tbl_name` [, `tbl_name`] ...]`

  Cuando no se nombran tablas, cierra todas las tablas abiertas y fuerza a todas las tablas en uso a que se cierren. Esto también vuelca la caché de consultas. Con uno o más nombres de tabla, vuelca sólo las tablas dadas. `FLUSH TABLES` también borra todos los resultados de consultas de la caché de consultas, como el comando `RESET QUERY CACHE` .

- `TABLES WITH READ LOCK`

  Cierra todas las tablas abiertas y bloquea todas las tablas para todas las bases de datos con una bloqueo de lectura hasta que ejecute `UNLOCK TABLES`. Esto es una forma muy conveniente de obtener copias de seguridad si tiene un sistema de ficheros como Veritas que puede tomas muestras en puntos de tiempo concretos.

- `USER_RESOURCES`

  Resetea todos los recursos por hora de usuario a cero. Esto le permite a los clientes que hayan alcanzado el límite de su conexión de hora, de consulta o de actualización para reanudar las actividades inmediatamente. `FLUSH USER_RESOURCES` no se aplica al límite en conexiones máximas simultáneas. Consulte Sección 13.5.1.3, “Sintaxis de `GRANT` y `REVOKE`”.

En MySQL 5.0, los comandos `FLUSH` se escriben en el lob binario a no ser que la plabra `NO_WRITE_TO_BINLOG` (o su alias `LOCAL`) se use. Nota: `FLUSH LOGS`, `FLUSH MASTER`, `FLUSH SLAVE`, y `FLUSH TABLES WITH READ LOCK` no se loguean en ningún caso porque causarían problemas si se replicasen en un esclavo.

Puede acceder a algunos de estos comandos con la utilidad mysqladmin usando los comandos `flush-hosts`, `flush-logs`, `flush-privileges`, `flush-status`, o `flush-tables` .

Consulte Sección 13.5.5.5, “Sintaxis de `RESET`” para información acerca cómo se usa el comando `RESET` para replicación.

#### 13.5.5.3. Sintaxis de `KILL`

    KILL [CONNECTION | QUERY] thread_id

Cada conexión a mysqld se ejecuta en un flujo separado. Puede ver los flujos en ejecución con el comando `SHOW PROCESSLIST` y matar un flujo con el comando `KILL `thread_id`` .

En MySQL 5.0.0, `KILL` permite los modificadores opcionales `CONNECTION` o `QUERY`:

- `KILL CONNECTION` es lo mismo que `KILL` sin modificadores: termina la conexión asociada con el `thread_id` dado.

- `KILL QUERY` termina el comando que la conexión está ejecutando actualmente, pero deja a la conexión intacta.

Si tiene el permiso `PROCESS` , puede ver todos los flujos, puede matar todos los flujos y comandos. De otro modo, puede ver y matar sólo sus propios flujos y comandos.

Puede usar los comandos mysqladmin processlist y mysqladmin kill para examinar y matar flujos.

Nota: No puede usar `KILL` con la biblioteca Embedded MySQL Server porque el servidor empotrado se ejecuta dentro del flujo de la aplicación que lo aloja. No crea ningún flujo de conexión por sí solo.

Cuando hace un `KILL`, se activa un flag específico para el flujo. En la mayoría de casos, puede que el flujo tarde algo de tiempo en morir, porque el flag kill se chequea sólo cada ciertos intervalos:

- En `SELECT`, `ORDER BY` y `GROUP BY` , el flag se chequea tras leer un bloque de registros. Si el flag kill está activado, el comando se aborta.

- Durante `ALTER TABLE`, el flag kill se chequea antes de que se lea cada bloque de registros de la tabla original. Si el flag kill está activado, el comando se aborta y la tabla temporal se borra.

- Durante operaciones `UPDATE` o `DELETE` , el flag kill se chequea tras cada lectura de bloque y tras cada registro borrado o actualizado. Si el flag kill está activado, el comando se aborta. Tenga en cuenta que si no está usando transacciones, los cambios no se deshacen.

- `GET_LOCK()` aborta y retorna `NULL`.

- Un flujo `INSERT DELAYED` rápidamente vuelca (inserta) todos los registros que tiene en memoria y luego termina.

- Si el flujo está en el handler de bloqueo (estado: `Locked`), el bloqueo de tabla se aborta rápidamente.

- Si el flujo está esperando a espacio libre en disco en una llamada de lectura, la escritura se aborta con un mensaje de error "disco lleno".

- Advertencia: Matar una operación `REPAIR TABLE` o `OPTIMIZE TABLE` en una tabla `MyISAM` resulta en una tabla que corrupta y no usable. Cualquier lectura o escritura en una tabla así falla hasta que la optimiza o repara de nuevo (sin interrupción).

#### 13.5.5.4. Sintaxis de `LOAD INDEX INTO CACHE`

    LOAD INDEX INTO CACHE
      tbl_index_list [, tbl_index_list] ...

    tbl_index_list:
      tbl_name
        [[INDEX|KEY] (index_name[, index_name] ...)]
        [IGNORE LEAVES]

El comando `LOAD INDEX INTO CACHE` en MySQL 5.0 precarga un índice de tabla en la caché de clave para la que se ha asignado por un comando `CACHE INDEX` , o en la caché de claves por defecto en otro caso. `LOAD INDEX INTO CACHE` se usa sólo para tablas `MyISAM` .

El modificador `IGNORE LEAVES` hace que se carguen sólo los bloques para los nodos que no sean hojas del índice.

El siguiente comando precarga nodos (bloques índice) de índices para las tablas `t1` y `t2`:

    mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
    +---------+--------------+----------+----------+
    | Table   | Op           | Msg_type | Msg_text |
    +---------+--------------+----------+----------+
    | test.t1 | preload_keys | status   | OK       |
    | test.t2 | preload_keys | status   | OK       |
    +---------+--------------+----------+----------+

Este comando precarga todos los bloques índice de `t1`. Sólo precarga bloques para los nodos que no sean hojas de `t2`.

La sintaxis de `LOAD INDEX INTO CACHE` le permite especificar que sólo índices particulares de una tabla deben precargarse. Sin embargo, la implementación actual precarga todos los índices de tabla en la caché, así que no hay razón para especificar nada distinto al nombre de tabla.

#### 13.5.5.5. Sintaxis de `RESET`

    RESET reset_option [, reset_option] ...

El comando `RESET` se usa para limpiar el estado de varias operaciones de servidor. Actúa como una versión más fuerte del comando `FLUSH` . Consulte Sección 13.5.5.2, “Sintaxis de `FLUSH`”.

Debe tener el permiso `RELOAD` para ejecutar `RESET`,

`reset_option` puede ser cualquiera de las siguientes:

- `MASTER`

  Borra todos los logs binarios listados en el fichero índice, resetea el fichero de índice de log binario para vaciarlo, y crea un nuevo fichero de log binario. (Conocido como `FLUSH MASTER` en versiones prévias de MySQL.) Consulte Sección 13.6.1, “Sentencias SQL para el control de servidores maestros”.

- `QUERY CACHE`

  Borra todos los resultados de consulta de la caché de consulta.

- `SLAVE`

  Hace que el esclavo olvide su posición de replicación en los logs binarios del maestro. También resetea el log retardado borrando cualquier fichero de log retardado y comenzando uno nuevo. Conocido como `FLUSH SLAVE` en versiones prévias MySQL.) Consulte Sección 13.6.2, “Sentencias SQL para el control de servidores esclavos”.

## 13.6. Sentencias de replicación

Esta sección describe comandos SQL relacionados con replicación. Un grupo de comandos se usa para controlar los servidores maestros. El otro se usa para controlar servidores esclavos.

### 13.6.1. Sentencias SQL para el control de servidores maestros

La replicación puede controlarse mediante la interfaz SQL. Esta sección discute los comandos para administrar los maestros de replicación. Sección 13.6.2, “Sentencias SQL para el control de servidores esclavos” discute comandos para administrar servidores esclavos.

#### 13.6.1.1. Sintaxis de `PURGE MASTER LOGS`

    PURGE {MASTER | BINARY} LOGS TO 'log_name'
    PURGE {MASTER | BINARY} LOGS BEFORE 'date'

Borra todos los logs binarios listados en el índice de log prévio al log especificado o fecha. Los logs se borran de la lista guardada en el fichero de índice de log, así que el log dado pasa a ser el primero.

Ejemplo:

    PURGE MASTER LOGS TO 'mysql-bin.010';
    PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';

El argumento de `BEFORE` `date` puede estar en formato `'YYYY-MM-DD hh:mm:ss'` . `MASTER` y `BINARY` son sinónimos en MySQL 5.0.

Si tiene un esclavo activo que actualmente esté leyendo uno de los logs que está intentando borrar, este comando no hace nada y falla con un error. Sin embargo, si un esclavo está dormido y purga los logs que quiere leer, el esclavo no es capaz de replicar cuando se despierta. El comando puede ejecutarse mientras los esclavos se replican. No necesita pararlos.

Para purgar logs, siga este procedimiento:

1. En cada servidor esclavo, use `SHOW SLAVE STATUS` para chequear qué log está leyendo.

2. Obtinga una lista de los logs en el servidor maestro con `SHOW MASTER LOGS`.

3. Determine el primer log entre todos los esclavos. Este es el log objetivo. Si todos los esclavos están actualizados, este es el último log de la lista.

4. Haga una copia de seguridad de todos los logs que vaya a borrar. (Este paso es opcional, pero siempre recomendable.)

5. Purgue todos los logs hasta el log objetivo, pero no lo incluya.

#### 13.6.1.2. Sintaxis de `RESET MASTER`

    RESET MASTER

Borra todos los logs binarios listados en el fichero índice, resetea el fichero índice de lob binario a vaciar, y recrea un nuevo fichero de log binario.

#### 13.6.1.3. Sintaxis de `SET SQL_LOG_BIN`

    SET SQL_LOG_BIN = {0|1}

Activa o desactiva el logueo binario para la conexión actual (`SQL_LOG_BIN` es una variable de sesión) si el cliente conecta usando una cuenta que tenga el permiso `SUPER` . En MySQL 5.0, el comando se rechaza con un error si el cliente no tiene este permiso.

#### 13.6.1.4. Sintaxis de `SHOW BINLOG EVENTS`

    SHOW BINLOG EVENTS
       [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]

Muestra los eventos en el log binario. Si no especifica `'log_name'`, se muestra el primer log binario.

La cláusula `LIMIT` tiene la misma sintaxis que para el comando `SELECT` . Consulte Sección 13.2.7, “Sintaxis de `SELECT`”.

Nota: Realizar `SHOW BINLOG EVENTS` sin cláusula `LIMIT` puede iniciar un proceso muy largo y que consume muchos recursos mientras el servidor vuelca los contenidos completos del log binario (lo que incluye la mayoría de las consultas ejecutadas por MySQL) a stdout. Para guardar el log binario en un fichero de texto para analizar posteriormente, use la utilidad mysqlbinlog . Consulte Sección 8.5, “La utilidad mysqlbinlog para registros binarios”.

#### 13.6.1.5. Sintaxis de `SHOW MASTER LOGS`

    SHOW MASTER LOGS
    SHOW BINARY LOGS

Lista los ficheros del log binario en el servidor. Este comando se usa como parte del procedimiento descrito en Sección 13.6.1.1, “Sintaxis de `PURGE MASTER LOGS`” para determinar qué logs pueden purgarse.

    mysql> SHOW BINARY LOGS;
    +---------------+-----------+
    | Log_name      | File_size |
    +---------------+-----------+
    | binlog.000015 |    724935 |
    | binlog.000016 |    733481 |
    +---------------+-----------+

En MySQL 5.0, `SHOW BINARY LOGS`, es equivalente a `SHOW MASTER LOGS`. La columna `File_size` se muestra desde MySQL 5.0.7.

#### 13.6.1.6. Sintaxis de `SHOW MASTER STATUS`

    SHOW MASTER STATUS

Proporciona información de estado en los ficheros del log binario del maestro de replicación.

#### 13.6.1.7. Sintaxis de `SHOW SLAVE HOSTS`

    SHOW SLAVE HOSTS

Muestra una lista de esclavos de replicación registrados actualmente en el maestro. Cualquier esclavo no arrancado con la opción `--report-host=`slave_name`` no es visible en esta lista.

### 13.6.2. Sentencias SQL para el control de servidores esclavos

La replicación puede controlarse con la interfaz SQL. Esta sección discute comandos para administrar servidores de replicación esclavos. Sección 13.6.1, “Sentencias SQL para el control de servidores maestros” discute comandos para administrar servidores maestros.

#### 13.6.2.1. Sintaxis de `CHANGE MASTER TO`

      CHANGE MASTER TO master_def [, master_def] ...

    master_def:
          MASTER_HOST = 'host_name'
        | MASTER_USER = 'user_name'
        | MASTER_PASSWORD = 'password'
        | MASTER_PORT = port_num
        | MASTER_CONNECT_RETRY = count
        | MASTER_LOG_FILE = 'master_log_name'
        | MASTER_LOG_POS = master_log_pos
        | RELAY_LOG_FILE = 'relay_log_name'
        | RELAY_LOG_POS = relay_log_pos
        | MASTER_SSL = {0|1}
        | MASTER_SSL_CA = 'ca_file_name'
        | MASTER_SSL_CAPATH = 'ca_directory_name'
        | MASTER_SSL_CERT = 'cert_file_name'
        | MASTER_SSL_KEY = 'key_file_name'
        | MASTER_SSL_CIPHER = 'cipher_list'

Cambia los parámetros que usa el servidor esclavo para conectar y comunicar con el servidor maestro.

`MASTER_USER`, `MASTER_PASSWORD`, `MASTER_SSL`, `MASTER_SSL_CA`, `MASTER_SSL_CAPATH`, `MASTER_SSL_CERT`, y `MASTER_SSL_CIPHER` proporciona información para el esclavo acerca de cómo conectar con su maestro.

Las opciones SSL (`MASTER_SSL`, `MASTER_SSL_CA`, `MASTER_SSL_CAPATH`, `MASTER_SSL_CERT`, `MASTER_SSL_KEY`, y `MASTER_SSL_CIPHER`) pueden cambiarse incluso en esclavos que se compilan sin soporte SSL. Se guardan en el fichero `master.info`, pero se ignorarn hasta que use un servidor que tenga soporte SSL activado.

Si no especifica un parámetro dado, mantiene su valor antiguo, excepto cuando se indica en la siguiente discusión. Por ejemplo, si la contraseña para conectar a su maestro MySQL ha cambiado, necesita ejecutar este comando para decir al esclavo la nueva contraseña:

    mysql> STOP SLAVE; -- if replication was running
    mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
    mysql> START SLAVE; -- if you want to restart replication

Aquí no hay necesidad de especificar los parámetros que no cambian (equipo, puerto, usuario, y así).

`MASTER_HOST` y `MASTER_PORT` son el nombre de equipo (o dirección IP) del equipo maestro y su puerto TCP/IP. Tenga en cuenta que si `MASTER_HOST` es igual a `localhost`, entonces, como en otras partes de MySQL, el puerto puede ignorarse (si los ficheros socket Unix pueden usarse, por ejemplo).

Si especifica `MASTER_HOST` o `MASTER_PORT`, el esclavo asume que el servidor maestro es distinto que antes (incluso si especifica un valor de equipo o de puerto igual que el anterior.) En este caso, los antiguos valores para el log binario del servidor maestro y su posición no se consideran aplicables por más tiempo, así que si no especifica `MASTER_LOG_FILE` y `MASTER_LOG_POS` en el comando `MASTER_LOG_FILE=''` y `MASTER_LOG_POS=4` se añaden al final.

`MASTER_LOG_FILE` y `MASTER_LOG_POS` son las coordinadas en que flujo esclavo de entradea/salida debe empezar a leer del maestro la siguiente vez que el flujo arranque. Si especifica alguna de ellas, no puede especificar `RELAY_LOG_FILE` o `RELAY_LOG_POS`. Si no se especifica `MASTER_LOG_FILE` ni `MASTER_LOG_POS` , el esclavo usa las últimas coordenadas del flujo SQL del esclavo antes de realizar `CHANGE MASTER`. Esto asegura que no hay discontinuidad en la replicación, incluso si el flujo SQL esclavo se comparó posteriormente con el flujo esclavo de entrada/salida, cuando símplemente quiere cambiar, digamos, la contraseña a usar.

`CHANGE MASTER` borra todos los ficheros de log retardados y arranca uno nuevo, a no ser que especifique `RELAY_LOG_FILE` o `RELAY_LOG_POS`. En tal caso, los logs retardados se guardan; en MySQL 5.0, la variable global `relay_log_purge` se pone a 0.

`CHANGE MASTER TO` actualiza los contenidos de los ficheros `master.info` y `relay-log.info` .

`CHANGE MASTER` es útil para inicializar un esclavo cuando tiene una imagen del maestro y ha guardado el log y el desplazamiento correspondientes a la misma. Tras cargar la imagen en el esclavo, puede ejecutar `CHANGE MASTER TO MASTER_LOG_FILE='`log_name_on_master`', MASTER_LOG_POS=`log_offset_on_master`` en el esclavo.

Ejemplos:

    mysql> CHANGE MASTER TO
        ->     MASTER_HOST='master2.mycompany.com',
        ->     MASTER_USER='replication',
        ->     MASTER_PASSWORD='bigs3cret',
        ->     MASTER_PORT=3306,
        ->     MASTER_LOG_FILE='master2-bin.001',
        ->     MASTER_LOG_POS=4,
        ->     MASTER_CONNECT_RETRY=10;

    mysql> CHANGE MASTER TO
        ->     RELAY_LOG_FILE='slave-relay-bin.006',
        ->     RELAY_LOG_POS=4025;

El primer ejemplo cambia el maestro y las coordenadas del log binario del maestro. Esto se usa cuando quiere preparar el esclavo para replicar el maestro.

El segundo ejemplo muestra una operación que se emplea menos frecuentemente. Si se usa cuando el esclavo tiene logs retardados que quiere ejecutar de nuevo por alguna razón. Para ello, el maestro no necesita ser accesible. Sólo necesita usar `CHANGE MASTER TO` y arrancar el flujo SQL (`START SLAVE SQL_THREAD`).

Incluso puede usar la segunda operación en una configuración de no replicación con un servidor aislado, no esclavo, para recuperación de fallos posteriores. Suponga que su servidor ha fallado y ha restaurado una copia de seguridad. Quiere volver a ejecutar los logs binarios del servidor (no los logs retardados, sino los logs binarios regulares), llamados (por ejemplo) `myhost-bin.*`. En primer lugar, haga una copia de seguridad de los logs binarios en un sitio seguro, en caso que no siga exactamente el procedimiento posterior y accidentalmente haga que el servidor purgue los logs binarios. En MySQL 5.0, use `SET GLOBAL relay_log_purge=0` para seguridad adicional. Cuando arranca el servidor sin la opción `--log-bin` , En su lugar, use las opciones `--replicate-same-server-id`, `--relay-log=myhost-bin` (para que el servidor crea que los logs binarios regulares son los logs retardados), `--skip-slave-start` . Cuando el servidor arranca, ejecute estos comandos:

    mysql> CHANGE MASTER TO
        ->     RELAY_LOG_FILE='myhost-bin.153',
        ->     RELAY_LOG_POS=410,
        ->     MASTER_HOST='some_dummy_string';
    mysql> START SLAVE SQL_THREAD;

El servidor lee y ejecuta sus propios logs binarios, permitiendo recuperación de fallos. Una vez que finaliza la recuperación, ejecute `STOP SLAVE`, pare el servidor, borre `master.info` y `relay-log.info`, y reinicie el servidor con sus opciones originales.

Actualmente, especificar `MASTER_HOST` (incluso con un valor de prueba) se necesita para hacer que el servidor piense que es un esclavo. En el futuro, planeamos añadir opciones para evitar estas restricciones menores.

#### 13.6.2.2. Sintaxis de `LOAD DATA FROM MASTER`

    LOAD DATA FROM MASTER

Este comando toma una muesta del maestro y la copia en el esclavo. Actualiza los valores de `MASTER_LOG_FILE` y `MASTER_LOG_POS` para que el esclavo comience la replicación desde la posición correcta. Cualquier regla de exclusión de tabla y base de datos especificada con las opciones `--replicate-*-do-*` y `--replicate-*-ignore-*` se tienen en cuenta. `--replicate-rewrite-db` no se tienen en cuenta. Esto es porque un usuario puede, con esta opción, configurar un mapeo no único tal como `--replicate-rewrite-db=db1->db3` y `--replicate-rewrite-db=db2->db3`, que puede confundir al esclavo al cargar tablas del maestro.

El uso de este comando está sujeto a las siguientes condiciones:

- Esto sólo funciona con tablas `MyISAM` . Intentos de cargar de una tabla no `MyISAM` provoca el siguiente error:

      ERROR 1189 (08S01): Net error reading from master

- Adquiere un bloqueo de lectura global del maestro al tomar la muesta, que evita actualizaciones en el maestro durante la operación de carga.

En el futuro, planeamos hacer este comando compatible con tablas `InnoDB` y eliminar la necesidad de bloqueo de lectura global usando una copia de seguridad no bloqueante en línea.

Si está cargando tablas grandes, puede tener que incrementar los valores de `net_read_timeout` y `net_write_timeout` en los servidores esclavos y maestros. Consulte Sección 5.3.3, “Variables de sistema del servidor”.

Tenga en cuenta que `LOAD DATA FROM MASTER` no copia ninguna tabla de la base de datos `mysql`. Esto hace fácil tener distintos usuarios y permisos en el maestro y el esclavo.

El comando `LOAD DATA FROM MASTER` necesita la cuenta de replicación que se usa para conectar con el maesto para tener los permisos `RELOAD` y `SUPER` en el maestro y el permiso `SELECT` para todas las tablas maestras que quiera cargar. Todas las tablas del maestro para las que el usuario no tiene el permiso `SELECT` se ignoran por `LOAD DATA FROM MASTER`. Esto es porque el maestro las oculta del usuario: `LOAD DATA FROM MASTER` llama `SHOW DATABASES` para conocer las bases de datos a cargar por parte del maestro, pero `SHOW DATABASES` retorna sólo bases de datos para las que el usuario tenga algunos permisos. Consulte Sección 13.5.4.6, “Sintaxis de `SHOW DATABASES`”. En la parte del esclavo, el usuario que ejecuta `LOAD DATA FROM MASTER` debe tener permisos para crear y borrar bases de datos y tablas que se copien.

#### 13.6.2.3. Sintaxis de `LOAD TABLE `nombre_de_tabla` FROM MASTER`

    LOAD TABLE tbl_name FROM MASTER

Transfiere una copia de la tabla desde el maestro al esclavo. Este comando se implementa principalmente para depurar `LOAD DATA FROM MASTER`. Requiere que la cuenta usada para conectar con el servidor maestro tenga los permisos `RELOAD` y `SUPER` en el maestro y el permiso `SELECT` en la tabla maestra a cargar. En la parte del esclavo, el usuario que ejecuta `LOAD TABLE FROM MASTER` debe tener permisos para borrar y crear la tabla.

Las condiciones para `LOAD DATA FROM MASTER` se aplican aquí. Por ejemplo, `LOAD TABLE FROM MASTER` funciona sólo en tablas `MyISAM`. También se aplican las notas sobre timeouts para `LOAD DATA FROM MASTER` .

#### 13.6.2.4. Sintaxis de `MASTER_POS_WAIT()`

    SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)

Esto es una función, no un comando. Se usa para asegurar que el esclavo ha leído y ejecutado eventos hasta la posición dada en el log binario del maestro. Consulte Sección 12.9.4, “Funciones varias” para una descripción completa.

#### 13.6.2.5. Sintaxis de `RESET SLAVE`

    RESET SLAVE

Hace que el esclavo olvide su posición de replicación en el log binario del maestro. Este comando se debe usar para un inicio limpio: borra los ficheros `master.info` y `relay-log.info` , todos los logs retardados, y arranca un nuevo log retardado.

Nota: Todos los logs retardados se borran, incluso si no se han ejecutado completamente por parte del flujo SQL esclavo . (Esta es una condición que es probable que exista en un esclavo de replicación si ha ejecutado un comando `STOP SLAVE` o si el esclavo está muy cargado.)

La información de conexión almacenada en el fichero `master.info` se resetea inmediatamente usando cualquier valor especificado en las opciones de arranque correspondientes. Esta información incluye valores tales como el equipo maestro, puerto, usuario y contraseña del maestro. Si el flujo SQL esclavo está en medio de una operación de replicar tablas temporales cuando se paró, y se ejecuta `RESET SLAVE` , estas tablas temporales replicadas se borran en el esclavo.

#### 13.6.2.6. Sintaxis de `SET GLOBAL SQL_SLAVE_SKIP_COUNTER`

    SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n

Ignora los siguientes `n` eventos del maestro. Esto es útil para recuperarse de paradas de replicación provocadas por un comando.

Este comando es válido sólo cuando el flujo esclavo no está en ejecución. De otro modo, produce un error.

#### 13.6.2.7. Sintaxis de `SHOW SLAVE STATUS`

    SHOW SLAVE STATUS

Proporciona información de estado de parámetros esenciales de los flujos esclavos. Si ejecuta este comando usando el cliente mysql puede usar un terminador de comando `\G` en lugar de punto y coma para obtener una salida vertical más legible:

    mysql> SHOW SLAVE STATUS\G
    *************************** 1. row ***************************
           Slave_IO_State: Waiting for master to send event
              Master_Host: localhost
              Master_User: root
              Master_Port: 3306
            Connect_Retry: 3
          Master_Log_File: gbichot-bin.005
      Read_Master_Log_Pos: 79
           Relay_Log_File: gbichot-relay-bin.005
            Relay_Log_Pos: 548
    Relay_Master_Log_File: gbichot-bin.005
         Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
          Replicate_Do_DB:
      Replicate_Ignore_DB:
               Last_Errno: 0
               Last_Error:
             Skip_Counter: 0
      Exec_Master_Log_Pos: 79
          Relay_Log_Space: 552
          Until_Condition: None
           Until_Log_File:
            Until_Log_Pos: 0
       Master_SSL_Allowed: No
       Master_SSL_CA_File:
       Master_SSL_CA_Path:
          Master_SSL_Cert:
        Master_SSL_Cipher:
           Master_SSL_Key:
    Seconds_Behind_Master: 8

`SHOW SLAVE STATUS` retorna los siguientes campos:

- `Slave_IO_State`

  Una copia del campo `State` se la salida de `SHOW PROCESSLIST` para el flujo esclavo de entrada/salida. Le dice si el flujo está tratando de conectar con el maestro, esperando eventos del maestro, reconectando con el maestro, etc. Los estados posibles se listan en Sección 6.3, “Detalles de la implementación de la replicación”. Consultar este campo es necesario porque, por ejemplo, el flujo puede estar en ejecución pero intentando conectar con el maestro sin éxito; sólo este campo le muestra el problema de conexión. El estado del flujo SQL no se copia porque es más simple. Si está en ejecución, no hay problema; si no es así, puede encontrar el error en el campo `Last_Error` (descrito posteriormente).

- `Master_Host`

  Equipo maestro actual

- `Master_User`

  Usuario actual usado para conectar con el maestro.

- `Master_Port`

  Puerto maestro actual.

- `Connect_Retry`

  Valor actual de la opción `--master-connect-retry` .

- `Master_Log_File`

  Nombre del fichero de log binario desde el que está leyendo actualmente el flujo de entrada/salida.

- `Read_Master_Log_Pos`

  La posición hasta la que el flujo de entrada/salida ha leído en el log binario del maestro.

- `Relay_Log_File`

  Nombre del fichero de log retardado desde el que el flujo SQL está leyendo y ejecutando actualmente.

- `Relay_Log_Pos`

  La posición hasta la que el flujo SQL ha leído y ejecutado en el flujo en el log retardado actual.

- `Relay_Master_Log_File`

  Nombre del log binario maestro que contiene la mayoría de los eventos recientes ejecutados por el flujo SQL.

- `Slave_IO_Running`

  Si el flujo de entrada/salida está activo.

- `Slave_SQL_Running`

  Si el flujo SQL está activo.

- `Replicate_Do_DB, Replicate_Ignore_DB`

  La lista de bases de datos especificadas con las opciones `--replicate-do-db` y `--replicate-ignore-db` , si se dió alguna.

- `Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table`

  Lista de tablas especificadas con las opciones `--replicate-do-table`, `--replicate-ignore-table`, `--replicate-wild-do-table`, y `--replicate-wild-ignore_table` , si se dió alguna.

- `Last_Errno, Last_Error`

  Número y mensaje de error retornados por la última consulta ejecutada. Un número de error 0 y mensaje vacío significa “no error.” Si el valor `Last_Error` no está vacío, también aparece como mensaje en el log de errores del esclavo.

  Por ejemplo:

      Last_Errno: 1051
      Last_Error: error 'Unknown table 'z'' on query 'drop table z'

  El mensaje indica que la tabla `z` existió en el maestro y se borró allí, pero no existió en el esclavo, así que `DROP TABLE` falló en el esclavo. (Esto puede ocurrir, por ejemplo, si olvidó copiar la tabla en el esclavo al configurar la replicación.)

- `Skip_Counter`

  El último valor usado para `SQL_SLAVE_SKIP_COUNTER`.

- `Exec_Master_Log_Pos`

  La posición del último evento ejecutado por el flujo SQL del log binario del maestro (`Relay_Master_Log_File`). (`Relay_Master_Log_File`, `Exec_Master_Log_Pos`) en el log binario del maestro correspondiente a (`Relay_Log_File`, `Relay_Log_Pos`) en el log retardado.

- `Relay_Log_Space`

  Tamaño total combinado de todos los logs retardados existentes.

- `Until_Condition, Until_Log_File, Until_Log_Pos`

  Valores especificados en la cláusula `UNTIL` del comando `START SLAVE` .

  `Until_Condition` tiene estos valores:

  - `None` si no se especificó `UNTIL`

  - `Master` si el esclavo está leyendo hasta una posición dada en el log binario del maestro

  - `Relay` si el esclavo está leyendo hasta una posición dada en su log retardado

  `Until_Log_File` y `Until_Log_Pos` indica los valors del nombre de fichero y posición que definen el punto en que el flujo SQL para su ejecución.

- `Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key`

  Estos campos muestran los parámetros SSL usados por el esclavo para conectar con el maestro, si hay algo.

  `Master_SSL_Allowed` tiene estos valores:

  - `Yes` si se permite conexión SSL con el maestro

  - `No` si no se permite una conexión SSL con el maestro

  - `Ignored` se se permite una conexión SSL pero el servidor esclavo no tiene soporte SSL activdo

  Los valores de los otros campos relacionados con SSL se corresponden con los valores de las opciones `--master-ca`, `--master-capath`, `--master-cert`, `--master-cipher`, y `--master-key` .

- `Seconds_Behind_Master`

  Este campo indica el “retardo” del esclavo. Cuando el flujo SQL esclavo está en ejecución (procesando actualizaciones), este campo es el número de segundos que han pasado desde el momento del evento más reciente del maestro ejecutado por este flujo. Cuando ese flujo lo atrapa el flujo de entrada/salida esclavo y pasa a espera de más eventos del flujo de entrada/salida este campo es cero. En resumen, este campo mide en segundos la diferencia temporal entre el flujo SQL esclavo y el flujo de entrada/salida esclavo.

  Si la conexión de red entre maestro y esclavo es rápida, el flujo de entrada/salida esclavo es muy cercano al maestro, así que este campo es una buena aproximación de cuanto tarda el flujo SQL esclavo en compararse con el maestro. Si la red es lenta, esta no es una buena aproximación, el flujo SQL esclavo puede verse atrapado a menudo por un flujo de entrada/salida esclavo lento , así que `Seconds_Behind_Master` a menudo muestra un valor de 0, incluso si el flujo de entrada/salida se compara posteriormente con el maestro. En otras palabras, esta columna es útil sólo para redes rápidas.

  Esta computación de diferencia temporal funciona incluso si el esclavo y maestro no tienen relojes idénticos ( la diferencia de tiempo se computa cuando el flujo de entrada/ salida del esclavo arranca, y se asume como que permance constante desde ese momento). `Seconds_Behind_Master` es `NULL` (que significa “desconocido”) si el flujo SQL esclavo no está en ejecución, o si el flujo de entrada/salida esclavo no está en ejecución o no conectado con el maestro. Por ejemplo si el flujo de entrada/salida esclavo está durmiendo durante `master-connect-retry` segundos antes de reconectar, `NULL` se muestra, ya que el esclavo no puede saber lo que hace el maestro, y así no puede asegurar el retardo.

  Este campo tiene una limitación. El timestamp se preserva a través de la replicación, lo que significa que, si un maestr M1 es un esclavo de M0, cualquier evento desde el log binario de M1 que se origine al replicar un evento del log binario M0 tiene el timestamp del evento. Esto permite a MySQL replicar `TIMESTAMP` con éxito. Sin embargo, la desventaja para `Seconds_Behind_Master` es que si M1 también recibe actualizaciones directas de los clientes, el valor se desvía aleatoriamente, ya que a veces el último evento de M1 es de M0 y otras de actualización directa, y por lo tanto es el timestampo más reciente.

#### 13.6.2.8. Sintaxis de `START SLAVE`

    START SLAVE [thread_type [, thread_type] ... ]
    START SLAVE [SQL_THREAD] UNTIL
        MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
    START SLAVE [SQL_THREAD] UNTIL
        RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos

    thread_type: IO_THREAD | SQL_THREAD

`START SLAVE` sin opciones arranca los flujos esclavos. El flujo de entrada/salida lee consultas del servidor maestro y las almacena en el log retardado. El flujo SQL lee el log retardado y ejecuta las consultas. `START SLAVE` require el permiso `SUPER`.

Si `START SLAVE` tiene éxito al arrancar los flujos esclavos, retorna sin ningún error. Sin emgargo, incluso en tal caso, puede ser que el flujo esclavo arranqu y luego pare (por ejemplo, porque no puede conectar con el maestro o leer sus logs binarios, o algún otro problema). `START SLAVE` no le advierte acerca de esto. Debe chequear el log de errores esclavo para mensajes de error generados por los flujos esclavos, o chequear que estén ejecutándos correctamente con `SHOW SLAVE STATUS`.

En MySQL 5.0, puede añadir las opciones `IO_THREAD` y `SQL_THREAD` al comando para decir qué flujo arrancar.

Una cláusula `UNTIL` puede añadirse para especificar que el esclavo debe arrancar y ejecutar hasta que el flujo SQL llegue a un punto dado en los logs binarios del maestro o en los logs retardados del esclavo. Cuando el flujo SQL llega a ese punto, para. Si la opción `SQL_THREAD` se especifica en el comando, arranca sólo el flujo SQL. De otro modo, arranca ambos flujos esclavos. Si el flujo SQL está en ejecución, la cláusula `UNTIL` se ignora y se muestra una advertencia.

Para una cláusula `UNTIL` , debe especificar nombre de fichero de log y posición. No mezcle opciones de maestro y log retardado.

Cualquier condición `UNTIL` se resetea mediante un comando `STOP SLAVE` , un comando `START SLAVE` que no incluya cláusula `UNTIL` , o reinicio de servidor.

La cláusula `UNTIL` puede ser útil para depurar replicación, o para que la replicación proceda justo antes del punto en que quiera evitar tener un esclavo replicando un comando. Por ejemplo, si se ejecuta un comando `DROP TABLE` no deseado, puede usar `UNTIL` para decir al esclavo que ejecute hasta ese punto pero no más. Para encontrar el evento, use mysqlbinlog con los logs maestros o los logs retardados del esclavo, o usando un comando `SHOW BINLOG EVENTS` .

Si está usando `UNTIL` para tener las consultas replicadas por el proceso esclavo en secciones, se recomienda que arranque el esclavo con la opción `--skip-slave-start` para evitar que el flujo SQL se ejecute cuando arranque el servidor. Es probablemente mejor usar esta opción con un fichero de opciones en lugar que en la línea de comandos, así que un reinicio inesperado del servidor no hace que se olvide.

El comando `SHOW SLAVE STATUS` incluye campos de salida que muestran los valores actuales de la condición `UNTIL` .

En versiones prévias de MySQL, este comando se llamó `SLAVE START` cuyo uso todavía se acepta en MySQL 5.0 por compatibilidad con versiones anteriores, pero ahora está obsoleto.

#### 13.6.2.9. Sintaxis de `STOP SLAVE`

    STOP SLAVE [thread_type [, thread_type] ... ]

    thread_type: IO_THREAD | SQL_THREAD

Para el flujo esclavo. `STOP SLAVE` necesita el permiso `SUPER` .

Como `START SLAVE`, este comando puede usarse con las opciones `IO_THREAD` y `SQL_THREAD` para nombrar el flujo o flujos a parar.

En versiones prévias de MySQL, este comando se llamó `SLAVE STOP`. Su uso se acepta en MySQL 5.0 por compatibilidad con versiones anteriores, pero ahora está obsoleto.

## 13.7. Sintaxis SQL de sentencias preparadas

MySQL 5.0 proporciona soporte para comandos preparados en la parte del servidor. Este soporte aprovecha del protocolo binario cliente-servidor implementado en MySQL 4.1, dado que use una interfaz de programación cliente apropiada. Las interfaces candidatas incluyen la biblioteca de la API de C de MySQL y MySQL Connector/NET. Por ejemplo, la API C proporciona un conjunto de llamadas de funciones que prepararn su API de comandos preparados. Consulte Sección 24.3.4, “Sentencias preparadas de la API C”. Otras interficies de lenguajes pueden proporcionar soporte para comandos preparados que usen el protocolo binario enlazando la biblioteca cliente C, un ejemplo es la extensión mysqli extension in PHP 5.0.

Una interfaz SQL alternativa para comandos preparados está disponible Su intefaz no es tan eficiente como usar el protocolo binario mediante una API de comandos preparados, pero no necesita programación porque está disponible directamente a nivel SQL:

- Puede usarlo cuando no haya interfaz programable diponible

- Puede usarlo desde cualquier programa que le permita enviar comandos SQL al servidor, tales como el programa cliente mysql .

- Puede usarlo incluso si el cliente está usando una antigua versión de la biblioteca cliente. El único requerimiento es que sea capaz de conectar a un servidor lo suficientemente reciente para soporta sintaxis SQL para comandos preparados.

La sintaxis SQL para comandos preparados está pensada para usar en situaciones como la siguiente:

- Puede querer testear cómo fucionan los comandos preparados en su aplicación antes de codificar la aplicación. O quizás una aplicación tenga un problema ejecutando comandos preparados y quiera determinar interactivamente cuál es el problema.

- Quiere crear un test de uso que describa un problema que está teniendo con comandos preparados, así que puede perparar un reporte de error.

- Necesita usar comandos preparados pero no tiene acceso a la API de programación que los soporta.

La sintaxis SQL para comandos preparados se abasa en tres comandos SQL:

    PREPARE stmt_name FROM preparable_stmt;

    EXECUTE stmt_name [USING @var_name [, @var_name] ...];

    {DEALLOCATE | DROP} PREPARE stmt_name;

El comando `PREPARE` prepara un comando y le asigna un nombre, `stmt_name`, con el que referirse al comando posteriormente. Los nombres de comando no son sensibles a mayúsculas. `preparable_stmt` es una cadena literal o una variable de usuario que contenga el texto del comando. El texto debe representar un comando SQL único, no varios. Dentro del comando, pueden usarse carácteres '`?`' como marcadores de parámetros para indicar dónde estarán los valores en la consulta posterior cuando la ejecute. Los carácteres '`?`' no deben delimitarse con comillas, incluso si pretende ligarlos con valores de cadenas.

Si un comando preparado con ese nombre existe, se elimina implícitamente antes que se prepare el nuevo comando. Esto significa que si el nuevo comando contiene un error y no puede preparase, se retorna un error y no existe un comando con el nombre dado.

El alcance de los comandos preparados es la sesión de cliente dentro de la que se crea. Otros clintes no pueden verlos.

Tras preparar un comando, lo ejecuta con un comando `EXECUTE` que se refiere al nombre de comando preparado. Si el comando preparado contiene cualquier marcador de parámetro, debe añadir una cláusula `USING` que liste las variables de usuario conteniendo los valores a ligar con los parámetros. Los valores de parámetros pueden proporcionarse sólo por variables de usuario, y la cláusula `USING` debe nombrar exactamente tantas variables como el número de marcadores de parámetros en el comando.

Puede ejecutar un comando preparado dado varias veces, pasando distintas variables al mismo o configurando las variables con distintos valores para cada ejecución.

Para eliminar un comando preparado, use el comando `DEALLOCATE PREPARE` . Tratar de ejecutar un comando preparado tras borrarlo provoca un error.

Si termina una sesión de cliente sin borrar un comando preparado préviamente, el servidor lo borra automáticamente.

Los siguientes comandos SQL pueden usarse en comandos preparados: `CREATE TABLE`, `DELETE`, `DO`, `INSERT`, `REPLACE`, `SELECT`, `SET`, `UPDATE`, y la mayoría de comandos `SHOW` . Otros comandos no se soportan todavía.

Los siguientes ejemplos muestran dos formas equivalentes de preparar un comando que calcula la hipotenusa de un triángulo dadas las longitudes de los dos catetos.

El primer ejemplo muestra cómo crear un comando preparado usando una cadena literal para proporcionar el texto del comando:

    mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
    mysql> SET @a = 3;
    mysql> SET @b = 4;
    mysql> EXECUTE stmt1 USING @a, @b;
    +------------+
    | hypotenuse |
    +------------+
    |          5 |
    +------------+
    mysql> DEALLOCATE PREPARE stmt1;

El segundo ejemplo es similar, pero proporciona el texto del comando como variable de usuario:

    mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
    mysql> PREPARE stmt2 FROM @s;
    mysql> SET @a = 6;
    mysql> SET @b = 8;
    mysql> EXECUTE stmt2 USING @a, @b;
    +------------+
    | hypotenuse |
    +------------+
    |         10 |
    +------------+
    mysql> DEALLOCATE PREPARE stmt2;

La sintaxis SQL para comandos preparados no puede usarse anidada. Esto es, un comando pasado a `PREPARE` no puede ser el mismo un comando `PREPARE`, `EXECUTE`, o `DEALLOCATE PREPARE` .

Además, la sintaxis SQL para comandos preparados es distinta de la usada en llamadas a la API de comandos preparados. Por ejemplo, use la función `mysql_stmt_prepare()` de la API C para preparar un comando `PREPARE`, `EXECUTE`, o `DEALLOCATE PREPARE` .

La sintaxis SQL para comandos preparados no puede usarse dentro de procedimientos almacenados y funciones.

Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.

Anterior |  | Siguiente
Capítulo 12. Funciones y operadores | Inicio | Capítulo 14. Motores de almacenamiento de MySQL y tipos de tablas