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

MySQL 5.0

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 
         [WHERE ]
         [ORDER BY ...]
         [LIMIT ]
       

Sintaxis para múltiples tablas:

       DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
       [.*] [, [.*] ...]
       FROM 
       [WHERE ]
     

O:

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

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

Si realiza un comando sin cláusula 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 . Consulte Sección 13.2.9, “Sintaxis de .

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

Para tablas y , puede especificar una columna 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 . Consulte Sección 3.6.9, “Utilización de .

El comando soporta los siguientes modificadores:

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

  • Para tablas , si usa la palabra , 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 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 .

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

El modificador afecta si las hojas del índice es mezclan en operaciones de borrado. 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.

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 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 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 .

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 . 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 sin , 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 .

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

La opción de MySQL para 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 específico no tarada demasiado tiempo. Puede simplemente repetir el comando hasta que el número de registros afectados sea menor que el valor .

Si el comando incluye una cláusula , los registros se borran en el orden especificado por la cláusula. Esto es muy útil sólo en conjunción con . Por ejemplo, el siguiente ejemplo encuentra registros coincidentes con la cláusula ordenados por , 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 para borrar registros de una o más tablas dependiendo de una condición particular en múltiples tablas. Sin embargo, no puede usar o en un de múltiples tablas.

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

Para la primera sintaxis, sólo los registros coincidentes de las tablas listadas antes de la cláusula se borran. Para la segunda sintaxis, sólo los registros coincidentes de las tablas listadas en la cláusula (antes de la cláusula ) 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 y .

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

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

Si usa un comando de varias tablas incluyendo tablas 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 que proporciona 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  [, ] ...
     

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

es útil principalmente con funciones que tienen efectos colaterales, tales como .

13.2.3. Sintaxis de HANDLER

HANDLER  OPEN [ AS  ]
HANDLER  READ  { = | >= | <= | < } (,,...)
[ WHERE  ] [LIMIT ... ]
HANDLER  READ  { FIRST | NEXT | PREV | LAST }
[ WHERE  ] [LIMIT ... ]
HANDLER  READ { FIRST | NEXT }
[ WHERE  ] [LIMIT ... ]
HANDLER  CLOSE

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

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

La primera sintaxis recibe un registro donde el índice especificado satisface los valores dados y la condición 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 , , y , en ese orden. El comando puede especificar valores para las tres columnas en el índice, o para las columnas en el prefijo a la izquierda. Por ejemplo:

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

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

La tercera sintaxis recibe un registro de la tabla en orden de registro natural que cumple la condición . Es más rápido que 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 . Este comando funciona para tablas también, pero no hay tal concepto porque no hay un fichero de datos separado.

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

cierra una tabla que se abrió con .

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

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

es un comando de bajo nivel. Por ejemplo, no proporciona consistencia. Esto es, no toma una muestra de la tabla, y no bloquea la tabla. Esto significa que tras un comando 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 o .

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

  • es más rápido que :

    • Un objeto de tratamiento de motor de almacenamiento designado se reserva para . El objeto se reúsa para posteriores comandos 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 no permite.

  • hace mucho más fácil portar aplicaciones que usen una interfaz tipo a MySQL.

  • le permite consultar una base de datos de forma difícil o imposible de realizar con . La interfície de 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]  [(,...)]
VALUES ({ | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE =, ... ]

O:

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

O:

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

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

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 indican las columnas explícitamente.

  • Si no especifica la lista de columnas para o , los valores para cada columna en la tabla deben proporcionarse en la lista o por el . Si no sabe el orden de las columnas en la tabla, use 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 . Consulte Sección 1.7.6.2, “Restricciones (constraints) sobre datos inválidos”.

    Si quiere que un comando 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 . Consulte Sección 5.3.2, “El modo SQL del servidor”.

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

    En MySQL 5.0, puede usar ) 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 están vacías, crea un registro con cada conjunto de columnas con sus valores por defecto:

    mysql> INSERT INTO  () VALUES();
    

    En modo 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 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 en una columna , , , o resulta en los valores , , , y insertados, respectivamente. La razón de que el valor almacenado en las columnas y sea 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 puede referirse a cualquier columna que se haya asignado antes en una lista de valores. Por ejemplo, puede hacer esto porque el valor para se refiere a , que se ha asignado préviamente:

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

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

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

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

El comando soporta los siguientes modificadores:

  • Si usa la palabra , el servidor pone el registro o registros a ser insertados en un búffer, y el cliente realizando el comando 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 .

  • Si usa la palabra , la ejecución de 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 está en espera. Es posible, por lo tanto, para un cliente que realice un comando esperar durante mucho tiempo (o incluso para siempre) en un entorno de muchas lecturas. (Esto es un contraste de , que deja al cliente continuar. Consulte Sección 13.2.4.2, “Sintaxis de .) Tenga en cuenta que no debe usarse normalmente con tablas y que hacerlo deshabilita inserciones concurrentes. Consulte Sección 14.1, “El motor de almacenamiento .

  • Si especifica , deshabilita el efecto de la opción si el servidor se arrancó con esa opción. Hace que las insecionces concurrentes no se usen.

  • Los valores afectados por un pueden usarse usando la función de la API de C. Consulte Sección 24.3.3.1, “.

  • Si usa la palabra en un comando , los errores que ocurren mientras se ejecuta el comando se tratan como advertencias. Por ejemplo, sin , un registro que duplique un índice existente o valor en la tabla hace que un error de clave duplicada en el comando se aborte. Con , 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 . Con , 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 de la API de C cuántos registros se insertan realmente en la tabla.

Si especifica , y un registro se inerta que haría que un valor duplicado en un índice o , se realiza un del antiguo registro. Por ejemplo, si la columna se declara como y contiene el valor , 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 es única, el sería equivalente a este comando :

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

Si se cumple para varios registros, sólo un registro se actualiza. En general, debería intentar evitar usar una cláusula en tablas con claves únicas múltiples.

MySQL 5.0 permite el uso de la función en la cláusula que se refiere a los valores de columna de la porción del comando . En otras palabras, en la cláusula se refiere al valor de 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 tiene sentido sólo en comandos y retorna 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 , la opción se ignora.

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

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

Records: 100 Duplicates: 0 Warnings: 0

indica el número de registros procesados por el comando. (Este no es necesariamente el número de registros realmente insertados, ya que puede ser distinto a cero.) indica el número de registros que no pueden insertarse ya que duplicarían algunos valores de índice únicos existentes 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 en una columna que se ha declarado . Para comandos de múltiples columnas o comandos , la columna se asigna con el valor por defecto para el tipo de datos de la columna. Este es para tipos numéricos, la cadena vacía () para tipos de cadenas, y el valor “cero” para tipos de fecha y hora. Los comandos se tratan del mismo modo que inserciones de múltiples registros porque el servidor no examina el resultado del para ver si retorna o no un único registro. (para un único registro , no hay ninguna advertencia cuando se inserta en una columna . 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 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 .

  • Insertar una cadena en una columna de cadena (, , , o ) 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 Consulte Sección 24.3.3.32, “.

13.2.4.1. Sintaxis de

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

Con , 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 :

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

  • No use con .

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

  • Las columnas funcionan normalmente.

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

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

En las partes de valores de puede referirse a una columna en otras tablas, mientras no use en la parte . Un efecto lateral es que debe calificar los nombres de columna no únicos en la parte de valores.

Puede usar en lugar de para sobreescribir registros antiguos es la contraparte de 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 ...
       

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

Cuando un cliente usa , 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 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 :

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

  • En MySQL 5.0, debe usarse sólo para comandos que especifiquen una lista de valores. El servidor ignora para comandos .

  • El servidor ignora para comandos .

  • Debido a que el comando retorna inmediatamente antes que los registros se inserten, no puede usar para obtener el valor que el comando genera.

  • Los registros no son visibles por los comandos hasta que se hayan insertado realmente.

  • 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 ) 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 con o . En esta descriión, el “flujo” es el flujo que recibe un comando y “handler” es el flujo que trata todos los comandos para una tabla particular.

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

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

  • El flujo ejecuta el comando , 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 del registro resultante, ya que retorna antes que se complete la operación de inserción. (Si usa la API C, la función 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 los registros se escriben, el handler chequea si algún comando 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 en segundos, el handler termina.

  • Si más de registros están pendientes en una cola de handler específica, el flujo que pida el 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 en la columna . Si muere si ejecuta un comando o puede matarlo con . Sin embargo, antes de salir, primero almacena todos los registros encolados en la tabla. Durante esta operación no acepta ningún nuevo comando de otros flujos. Si ejecuta un comando a continuación, se crea un nuevo flujo handler.

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

  • Las siguientes variables de estado proporcionan información acerca de comandos :

    Variable de estado Significado
    Número de flujos handler
    Número de registros escritos con
    Número de registros esperando a ser escritos

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

Tenga en cuenta que es más lento que un 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 sólo cuando esté realmente seguro que lo necesita.

13.2.5. Sintaxis de LOAD DATA INFILE

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE '.txt'
    [REPLACE | IGNORE]
    INTO TABLE 
    [FIELDS
        [TERMINATED BY '']
        [[OPTIONALLY] ENCLOSED BY '']
        [ESCAPED BY '' ]
    ]
    [LINES
        [STARTING BY '']
        [TERMINATED BY '']
    ]
    [IGNORE  LINES]
    [(,...)]
    [SET  = ,...)]

El comando 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 contra y acelerar , consulte Sección 7.2.14, “Velocidad de la sentencia .

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

Puede cargar ficheros de datos usando la utilidad mysqlimport ; opera enviando un comando al servidor. La opción hace que mysqlimport lea ficheros de datos desde el equipo cliente. Puede especificar la opción 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 , la ejecución del comando se retarda hasta que no haya más clientes leyendo de la tabla.

Si especifica con una tabla 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 . Usar esta opción afecta al rendimiento de ligeramente, incluso si no hay otro flujo usando la tabla al mismo tiempo.

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

  • Si se especifica , 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 , 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 se lee del directorio de datos del servidor, mientras que el mismo fichero llamado como se lee desde el directorio de base de datos de la base de datos por defecto. Por ejemplo, el siguiente comando lee el fichero del directorio de la base de datos para porque es la base de datos actual, incluso si el comando carga explícitamente el fichero en una tabla en la base de datos :

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 en ficheros del servidor, debe tener el permiso .

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

Usar 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 para cargar ficheros locales.

En MySQL 5.0, funciona sólo si su servidor y su cliente lo tienen activado. Por ejemplo, si mysqld se arranca con , entonces no funciona. Consulte Sección 5.5.4, “Cuestiones relacionadas con la seguridad y .

Si necesita 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 y controlan el tratamiento de registros de entrada que duplican registros existentes en claves únicas.

Si especifica , 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 .

Si especifica , 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 se ha especificado o no. Sin , ocurre un error cuando se encuentra un valor de clave duplicado, y el resto del fichero de texto se ignora. Con , el comportamiento por defecto es el mismo que si se especifica , 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 antes de ejecutar .

Si usa en una tabla vacía , todos los índices no únicos se crean en batch separados (como para ). Esto hace 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 antes de cargar el fichero en la tabla y usar para recrear los índices tras cargar el fichero. Consulte Sección 7.2.14, “Velocidad de la sentencia .

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

Si especifica una cláusula , cada una de sus subcláusulas (, , y ) también es opcional, excepto que debe especificar al menos una de ellas.

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

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

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

       LINES TERMINATED BY '\n' STARTING BY ''
     

En otras palabras, por defecto 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 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 , 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 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 como terminador de línea al escribir ficheros. Para leer tales ficheros, use .

Si todas las líneas que quiere leer tienen un prefijo común que quiere ignorar, puede usar ' 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 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 y .

La opción LINES puede usarse para ignorar líneas al inicio del fichero. Por ejemplo, puede usar 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 junto con 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, no interpreta los contenidos del fichero correctamente. Suponga que usa 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 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.

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 
->           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 y deben ser un único carácter. Los valores , , y 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 .

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

controla el entrecomillado de los campos. Para la salida (), si omite la palabra , todos los campos se delimitan por el carácter . 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 , el carácter se usa sólo para delimitar valores en columnas que tienen datos de cadenas (tales como , , , o ):

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 dentro de un campo se escapan mediante un prefijo del carácter . También tenta en cuenta que si especifica un valor vacío, es posible generar salida que no puede leerse correctamente con . 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 , si está presente, se elimina del final de los valores de campos . (Esto es cierto se especifique o no; no tiene efecto en la interpretación de la entrada.) Las ocurrencias del carácter prececdidas por el carater se interpretan como parte del campo actual.

Si el campo comienza con el carácter , las instancias del mismo se reorganizan como terminadores del campo sólo si van seguidas por el campo o la secuencia . Para evitar ambigüedad, las ocurrencias del carácter dentro de un campo se pueden doblar y se interpretan como una única instancia del carácter. Por ejemplo, si se especifica , 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

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

  • El carácter

  • El carácter

  • El primer carácter de los valores y

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

Si el carácter está vacío, no se escapan carácteres y se muestra como , no . 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 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 '' escapado o '' (por ejemplo, o si el carácter de escape es ''). Estas secuencias se interpretan como ASCII NUL (un byte con valor cero) y . Las reglas para tratamiento de 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 es una cadena vacío y no está vacío, las líneas se terminan con .

  • Si los valores y 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 , 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.

    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 , 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 varía en función de las opciones y en uso:

  • Para los valores y por defecto, se escribe como para la salida, y para la entrada se lee como (considerando que el carácter es '').

  • Si no está vacílo, un campo que contenga el literal como valor se lee como el valor . Esto difiere de la palabra delimitada por carácteres , que se lee como la cadena .

  • Si está vacío, se escribe como la palabra .

  • Con formato fijo de registro (lo que ocurre cuando y están vacíos), se escribe como una cadena vacía. Teng en cuenta que esto hace que ambos valores 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 :

  • Registros de tamaño fijo ( y ambos vacíos) y columnas o .

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

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

El siguiente ejemplo carga todas las columnas de la tabla :

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

Por defecto, cuando no se proporciona una lista al final de un comando , 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 no se soporta. Desde MySQL 5.0.3, la lista de columnas puede contener nombres de columna o variables y la cláusula 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 puede usarse de distintos modos. El siguiente ejemplo usa la primera columna en el fichero de datos directamente para el valor de , 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 :

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

La cláusula puede usarse para proporcionar valores no derivados del fichero de entrada. Los siguientes comandos actualizan 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 está sujeto a las siguientes restricciones:

  • Las asignaciones en la cláusula 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 . 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 no se procesan por parta de la lista de columnas/variables o por la cláusula .

  • 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, la divide en campos y usa los valores según la lista de columnas/ variables y la cláusula , si están presentes. A continuación se inserta el registro resultante en la tabla. Si hay disparadores o 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 .

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 .

  • 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 o statement.

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

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

Cuando acaba el comando , 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 . Consulte Sección 24.3.3.32, “.

Las advertencias se producen bajo las mismas circunstancias que cuando los valores se insertan mediante el comando (consulte Sección 13.2.4, “Sintaxis de ), excepto que 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 para obtener una lista de las primeras advertencias como información acerca de qué ha fallado. Consulte Sección 13.5.4.22, “Sintaxis de .

13.2.6. Sintaxis de REPLACE

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

O:

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

O:

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

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

Tenga en cuenta que a menos que la tabla tenga un índice , o usar un comando no tiene sentido. Es equivalente a , 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 . Cualquier columna no presente adquiere su valor por defecto, como ocurre con . No puede referirse a valores del registro actual y usarlos en el nuevo registro. Si usa un comando tal como = + 1, la referencia al nombre de columna en la parte derecha se trata como ), así que es equivalente a = DEFAULT() + 1.

Para ser capaz de usar , debe tener los permisos y para la tabla.

El comando 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 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 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 .

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 ):

  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]
, ...
[INTO OUTFILE '' 
| INTO DUMPFILE '']
[FROM 
[WHERE ]
[GROUP BY { |  | }
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING ]
[ORDER BY { |  | }
[ASC | DESC] , ...]
[LIMIT {[,]  |  OFFSET }]
[PROCEDURE ()]
[FOR UPDATE | LOCK IN SHARE MODE]]

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

  • Cada indicata una columna que quiere recibir.

  • indicata la tabla o tablas desde la que recibir registros. Su sintaxis se describe en Sección 13.2.7.1, “Sintaxis de .

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

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 debe ir tras cualquier cláusula y antes de cualquier cláusula .

  • Una puede tener un alias usando . El alias se usa como el nombre de columna de la expresión y puede usarse en cláusulas , , o . Por ejemplo:

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

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

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

    Como es opcional, puede ocurrir un sutil problema si olvida la coma entre dos expresiones : MySQL interpreta el segundo como un nombre de alias. Por ejemplo, en el siguiente comando, 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 .

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

  • La cláusula 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 . Para cada tabla especificada, puede opcionalmente especificar un alias.

     [[AS] ]
    [[USE INDEX ()]
    | [IGNORE INDEX ()]
    | [FORCE INDEX ()]]
    

    El uso de , , para dar al optimizador pistas acerca de cómo escoger los indices se describe en Sección 13.2.7.1, “Sintaxis de .

    En MySQL 5.0, puede usar 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 (dentro de la base de datos actual) , o como para referirse a una base de datos explícitamente. Puede referirse a una columna como , , o . No necesita especificar un prefijo o 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 como nombre de tabla falso en siguaciones donde no se referencian tablas:

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

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

  • Una referencia de tabla puede tener un alias usando AS o :

    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 , 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 y 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 (descendiente) al nombre de la columna en la cláusula por la que está ordenando. Por defecto es orden ascendente; puede especificarse explícitamente usando la palabra clave .

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

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

    SELECT a, COUNT(b) FROM test_table GROUP BY a DESC
    
  • MySQL extiende el uso de para permitir seleccionar campos que no se mencionan en la cláusula . Si no obtiene los resultados que espera de la consulta, por favor lea la descripción de en Sección 12.10, “Funciones y modificadores para cláusulas .

  • En MySQL 5.0, permite un modificador . Consulte Sección 12.10.2, “Modificadores de .

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

    Antes de MySQL 5.0.2, una cláusula podía referirse a cualquier columna o alias nombrado en una en la lista o en subconsultas externas, y para funciones agregadas. Sin embargo, el estándar SQL requiere que debe referirse sólo a columnas en la cláusula 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 , MySQL 5.0.2 y posteior permite a referirse a columnas en la lista , en la cláusula , 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 se refiere a una columna ambígua, se muestra una advertencia. En el siguiente comando, 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 se usa en un y como alias de columna en la lista de columnas de salida, se da preferencia a la columna en .

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

    mysql> SELECT  FROM  HAVING  > 0;
    

    Escriba esto en su lugar:

    mysql> SELECT  FROM  WHERE  > 0;
    
  • La cláusula puede referirse a funciones de agregación, algo que no puede hacer la cláusula :

    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 puede usarse para restringir el número de registros retornados por el comando . 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 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, es equivalente a .

  • La forma de escribe los registros seleccionados en un fichero. El fichero se crea en el equipo servidor, así que debe tener el permiso para usar esta sintaxis. El fichero no puede existir, que entre otras cosas evita destruir ficheros cruciales tales como y tablas de la base de datos.

    El comando 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 . En tal caso, debería usar algún comando como en el equipo cliente para generar el fichero.

    es el complemento de ; la sintaxis para la parte del comando consiste en las mismas cláusulas y usadas con el comando . Consulte Sección 13.2.5, “Sintaxis de .

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

    • El carácter

    • El carácter

    • El primer carácter de y

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

    Si el carácter está vacío, no hay ningún carácter de escape y se muestra por salida como , no . 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 , , , o para ser capaz de volver a leer el fichero correctamente. ASCII 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 en lugar de , 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 en un fichero.

  • Nota: Cualquier fichero creado por o 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 por esta y otras razones). El fichero debe ser modificable por todo el mundo para que pueda maminpular sus contenidos.

  • Una cláusula 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 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 crea un bloqueo compartido que evita a otras transacciones actualizar o borrar los registros examinados. Consulte Sección 15.10.5, “Bloquear lecturas y .

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

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

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

  • da a 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 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.

    no puede usarse con comandos que sean parte de una .

  • fuerza al optimizador a hacer un join de las tablas en el orden en que se listan en la cláusula . 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 (Obtener información acerca de un )”. también puede usarse en la lista . Consulte Sección 13.2.7.1, “Sintaxis de .

  • puede usarse con o 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 .

  • 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.

  • puede usarse con o 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.

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

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

  • 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 o subconsultas esta opción afecta a cualquier en la consulta.

13.2.7.1. Sintaxis de

MySQL soporta las siguientes sintaxis de para la parte de comandos y y de múltiples tablas:

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

se define como:

   [[AS] ]
  [[USE INDEX ()]
  | [IGNORE INDEX ()]
  | [FORCE INDEX ()]]

se define como:

ON  | USING ()

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

La sintaxis mostrada en la lista precedente existe sólo por compatibilidad con ODBC.

  • Puede oner un alias en una referencia de tabla usando AS o :

    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 es cualquier expresión condicional de la forma que puede usarse en una cláusula .

  • Si no hay ningún registro coincidiente para la tabla de la derecha en la parte o en un , se usa un registro con todos las columnas a 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 con un valor no presente en (esto es, todos los registros en sin registro correspondiente en ). Esto asume que se declara . Consulte Sección 7.2.9, “Cómo optimiza MySQL los y .

  • La cláusula ) 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 de dos tablas se define semánticamente equivalente a un o con una cláusula que nombra todas las columnas que existen en ambas tablas.

  • 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).

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

  • es idéntico a , 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 , puede decirle a MySQL que use sólo uno de los posibles índices para encontrar registros en la tabla. La sintaxis alternativa puede usarse para decir a MySQL que no use algún índice particular. Estos trucos son útiles si muestra que MySQL está usando el índice incorrecto de la lista de posibles índices.

También puede usar , que actúa como ) 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.

, , y son sinónimos de , , y .

Nota: , , y 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 o .

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 y .

13.2.7.2. Sintaxis de

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

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

Las columnas seleccionadas lisatadas en posiciones correspondientes de cada comando 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 se usan como nombres de columna para los resultados retornados.

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

  • Sólo el último comando puede usar .

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

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

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

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

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

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

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

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

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

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

En MySQL 5.0, los tipos y longitudes de las columnas en el conjunto de resultados de una tienen en cuenta los valores recibidos por todos los comandos . 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 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, es la consulta externa (o comando externo), y 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 ordinario: , , , , joins, trucos de índices, constructores , comentarios, funciones, y así.

Una restricción es que el comando exterior de una subconsulta debe ser: , , , , , o . 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 , , , y . 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 , 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 retorna un valor único () que tiene un tipo de datos , 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 , y una indicación que el valor en la columna puede ser . De hecho, casi todas las consultas pueden ser . Si la tabla usada en este ejemplo estuviese vacía, la tabla de la subconsulta sería .

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, necesita argumentos enteros, y 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 , 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 s1 FROM t2) FROM t1;

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

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:

  ()

Donde 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 que son iguales a un valor máximo en la tabla :

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 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 , y

Sintaxis:

  ANY ()
 IN ()
  SOME ()

La palabra clave , que debe seguir a un operador de comparación, significa “return si la comparación es para (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 que contiene . La expresión es si la tabla contiene ya que hay un valor en que es menor que . La expresión es si la tabla contiene , o si la tabla está vacía. La expresión es si la tabla contiene .

La palabra es un alias para . 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, no es un alias para , sino para . Consulte Sección 13.2.8.4, “Subconsultas con .

La palabra es un alias para . 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 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 en su lugar ayuda a asegurar que todo el mundo entiende el significado de la consulta.

13.2.8.4. Subconsultas con

Sintaxis:

  ALL ()

La palabra , que debe seguir a un operador de comparación, significa “return si la comparación es para 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 que contiene . La expresión es si la tabla contiene ya que es mayor que los otros tres valores en . La expresión es si la tabla contiene ya que hay un único valor en la tabla mayor que . La expresión es si la tabla contiene .

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

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

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

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

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

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

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

es un alias para . 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 si la tabla tiene un registro en que y .

Las expresiones y 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 que también existen en la tabla ”:

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

13.2.8.6. y

Si una subconsulta no retorna ningún registro, entonces es , y es . Por ejemplo:

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

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

Para el ejemplo precedente, si contiene algún registro, incluso registros sólo con valores entonces la condición es . Este es un ejemplo poco probable, ya que prácticamente siempre una subconsulta 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 . Esto es, tiene una cláusula dentro de otra . Formalmente, responde a la pregunta “¿existe una ciudad con una tienda que no esté en ?” Sin embargo, es más fácil decir que un responde a la pregunta “¿es x 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 , incluso aunque la cláusula de la subconsulta no menciona una tabla . Por lo tanto, MySQL busca fuera de la subconsulta y encuentra en la consulta externa.

Suponga que la tabla contiene un registro en que y ; mientras, la tabla contiene un registro en que y . La expresión sería , pero en este ejemplo, la cláusula dentro de la subconsulta es (ya que no es igual a ), así que la subconsulta como un todo es .

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, debe ser una columna en la tabla ya que renombra . No hay una columna en la tabla porque es una consulta externa que está demasiado fuera.

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

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

 IN (SELECT  FROM  WHERE )

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

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

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

La cláusula es obligatoria, ya que cada tabla en la cláusula debe tener un nombre. Cualquier columna en la lista selecta de la 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 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: .

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 se reconoce en la consulta exterior.

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

Las subconsultas en la cláusula se ejecutan incluso para el comando (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 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 , ya que las subconsultas son legales en los comandos y así como en los . Sin embargo, no puede usar la misma tabla (en este caso la tabla ) para la cláusula 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 en lugar de .

  • Use en lugar de .

  • Use en lugar de .

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

    SELECT * FROM t1 WHERE t1.
    = (SELECT a FROM t2 WHERE b = );
    

    En lugar de:

    SELECT * FROM t1 WHERE t1.
    IN (SELECT a FROM t2 WHERE b = );
    

Estos trucos pueden hacer que los programas vayan más rápidos o lentos. Usar recursos MySQL como la función 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 para asegurar que una subconsulta dada realmente no está correlacionada.

  • MySQL reescribe subconsultas , , , y 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 describe como tipo especial de join ( o ):

    ... IN (SELECT  FROM  ...)
    
  • MySQL mejora expresiones de la siguiente forma con una expresión que involucre o , a no ser que hayan involucrados valores o conjuntos vacíos:

     {ALL|ANY|SOME} {> | < | >= | <=} ()
    

    Por ejemplo, esta cláusula :

    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 en el directorio .

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 y . 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 :

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 :

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

Un 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 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 para múltiples tablas también se soportan en MySQL 5.0.

13.2.9. Sintaxis de TRUNCATE

TRUNCATE TABLE 

vacía una tabla completamente. Lógicamente, esto es equivalente a un comando que borre todos los registros, pero hay diferencias prácticas bajo ciertas circunstáncias.

Para antes de la versión 5.0.3, se mapea a , así que no hay diferencia. A partir de MySQL/InnoDB-5.0.3, está disponible muy rápido. La operación se mapea a si hay restricciones de clave foránea que referencien la tabla.

Para otros motores, difiere de 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 .frm sea válido, la tabla puede recrearse como una vacía con , incluso si los ficheros de datos o de índice se han corrompido.

  • El tratador de tablas no recuerda el último valor usado, pero empieza a contar desde el principio. Esto es cierto incluso para y , que normalmente no reúsan valores de secuencia.

es una extensión de Oracle SQL adoptada en MySQL.

13.2.10. Sintaxis de UPDATE

Sintaxis para una tabla:

UPDATE [LOW_PRIORITY] [IGNORE] 
SET = [, = ...]
[WHERE ]
[ORDER BY ...]
[LIMIT ]

Sintaxis para múltiples tablas:

UPDATE [LOW_PRIORITY] [IGNORE] 
SET = [, = ...]
[WHERE ]

El comando actualiza columnas en registros de tabla existentes con nuevos valores. La cláusula indica qué columna modificar y los valores que puede recibir. La cláusula , si se da, especifica qué registros deben actualizarse. De otro modo, se actualizan todos los registros. Si la cláusula se especifica, los registros se actualizan en el orden que se especifica. La cláusula es el límite de registros a actualizar.

El comando soporta los siguientes modificadores:

  • Si usa la palabra clave , la ejecución de se retrasa hasta que no haya otros clientes leyendo de la tabla.

  • Si usa la palabra clave , 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 en una expresión, usa el valora ctual de la columna. Por ejemplo, el siguiente comando pone la columna a uno más que su valor actual:

mysql> UPDATE persondata SET age=age+1;

Las asignaciones se avalúna de izquierda a derecha. Por ejemplo, el siguiente comando dobla la columna 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 con un valor , 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 para tipos numéricos, la cadena vacía () para tipos de cadena, y el valor “cero” para valores de fecha y hora.

retorna el número de registros que se cambian. En MySQL 5.0, la función de la API de C retorna el número de registros coincidentes actualizados y el número de advertencias que ocurren durante el .

Puede usar para restringir el alcance del . Una cláusula es una restricción de registros coincidentes. El comando para en cuanto encuentra registos que satisfagan la cláusula , tanto si han sido cambiados como si no.

Si un comando incluye una cláusula , los registros se actualizan en el orden especificado por la cláusula.

Puede realizar operaciones que cubran varias tablas. La parte lista las tablas involucradas en el join. Su sintaxis se describe ámpliamente en Sección 13.2.7.1, “Sintaxis de . 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 de múltiples tablas pueden usar cualquier tipo de join permitido en comandos tales como .

Nota: No puede usar o con un de múltiples tablas.

En MySQL 5.0, necesita el permiso sólo para columnas referenciadas en un de múltiples tablas que se actualizan realmente. Necesita sólo el permiso para algunas columnas que se leen pero no se modifican.

Si usa un comando de múltiples tablas que involucren tablas 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 que proporciona para que el resto de tablas se modifiquen acórdemente. Consulte Sección 15.6.4, “Restricciones (constraints) .

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