lunes, 14 de junio de 2010

Delete y el MySQL

A veces creemos que la función DELETE del MySQL es exclusivamente DELETE FROM table WHERE condicion='verdadera'; pero en realidad va mucho más que esa simple sintaxis.

Aquí les dejo la explicación para los estudiantes que me preguntaron.


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


Sintaxis multitabla:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
table_name[.*] [, table_name[.*] ...]
FROM table-references
[WHERE where_definition]


O:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM table_name[.*] [, table_name[.*] ...]
USING table-references
[WHERE where_definition]


DELETE elimina columnas desde "table_name" que satisfagan la condición dada por la "where_definition", y devuelve el número de registros borrados.

Si se usa una sentencia DELETE sin cláusula WHERE, todas las filas serán borradas. Una forma más rápida de hacer esto, cuando no se necesita conocer el número de filas eliminadas, es usar .
En MySQL 3.23, DELETE sin la cláusula WHERE retorna cero como número de filas afectadas.
En esta versión, si realmente se quiere saber cuántas filas fueron eliminadas cuando se borran todas, y se está dispuesto a sufrir una pérdida de velocidad, se puede usar una sentencia DELETE con una cláusula WHERE que siempre se cumpla.
Por ejemplo:mysql> DELETE FROM table_name WHERE 1>0;

Esto es mucho más lento que DELETE FROM table_name sin cláusula WHERE, porque borra filas una a una.

Si se borra la fila que contiene el valor máximo para una columna AUTO_INCREMENT, ese valor podrá ser usado por una tabla ISAM oBDB, pero no por una tabla MyISAM o InnoDB. Si se borran todas las filas de una tabla con DELETE FROM tbl_name (sin un WHERE) en modo AUTOCOMMIT, la secuencia comenzará de nuevo para todos los motores de almacenamiento, excepto para InnoDB y (desde MySQL 4.0) MyISAM. Hay algunas excepciones a este comportamiento oara tablas InnoDB.

Para tablas MyISAM y BDB, se puede especificar una columna secundaria AUTO_INCREMENT en una clave multicolumna. En ese caso, la reutilización de los valores mayores de la secuencia borrados ocurre para tablas MyISAM.

La sentencia DELETE soporta los siguientes modificadores:
Si se especifica la palabra LOW_PRIORITY, la ejecución de DELETE se retrasa hasta que no existan clientes leyendo de la tabla.

Para tablas MyISAM, si se especifica la palabra QUICK entonces el motor de almacenamiento no mezcla los permisos de índices durante el borrado, esto puede mejorar la velocidad en ciertos tipos de borrado.

La opción IGNORE hace que MySQL ignore todos los errores durante el proceso de borrado. (Los errores encontrados durante en análisis de la sentencia se procesan normalmente.) Los errores que son ignorados por el uso de esta opción se devuelven como avisos. Esta opción apareció en la versión 4.1.1.

La velocidad de las operaciones de borrado pueden verse afectadas por otros factores, como el número de índices o el tamaño del caché para índices.

En tablas MyISAM, los registros borrados se mantienen en una lista enlazada y subsiguientes operaciones hacen uso de posiciones anteriores. Para recuperar el espacio sin usar y reducir el tamaño de los ficheros, usar la sentencia o la utilidad myisamchk para reorganizar tablas. es más fácil, pero myisamchk es más rápido.

El modificador QUICK afecta a si las páginas de índice se funden para operaciones de borrado. DELETE QUICK es más práctico para aplicaciones donde los valores de índice para las filas borradas serán reemplazadas por valores de índice similares para filas insertadas más adelante. En ese caso, los huecos dejados por los valores borrados serán reutilizados.

DELETE QUICK no es práctico cuando los valores borrados conducen a bloques de indices que no se llenan dejando huecos en valores de índice para nuevas inserciones. En ese caso, usar QUICK puede dejar espacios desperdiciados en el índice que permanecerán sin reclamar. Veamos un ejemplo de este tipo de problema:

Crear una tabla que contiene un índice en una columna AUTO_INCREMENT.
Insertar muchos registros en esa tabla. Cada inserción produce un valor de índice que es añadido al extremo mayor del índice.

Borrar un bloque de registros en el extremo inferior del rango de valores de la columna usando DELETE QUICK.

En este caso, los bloques de índices asociados con los valores de índice borrados quedan vacíos por debajo pero no se mezclan con otros bloques de índices debido al uso de QUICK. Esos bloques permanecen sin rellenar cuando se insertan nuevas filas, ya que los nuevos registros no tienen valores de índice en el rango borrado. Además, permanecerán sin rellenar aunque después se use DELETE sin QUICK, a no ser que alguno de los valores de índice borrados hagan que afecten a bloques de índices dentro o adyacentes a los bloques vacíos por debajo. Para liberar el espacio de índices no usado bajo estas circunstancias, se puede usar .
Si se van a borrar muchas filas de una tabla, puede ser mucho más rápido usar DELETE QUICK seguido de . Esto reconstruye el índice en lugar de reliazar muchas operaciones de mezcla de bloques de índice.

La opción LIMIT row_count, específica de MySQL para DELETE indica al servidor el máximo número de filas a borrar antes de que el control se devuelva al cliente. Esto se puede usar para asegurar que una sentencia DELETE específica no tomará demasiado tiempo. Se puede repetir la sentencia DELETE hasta que el número de filas afectadas sea menor que el valor de LIMIT.
Si se usa una cláusula ORDER BY las filas serán borradas en el orden especificado por la cláusula. Esto sólo será práctico si se usa en conjunción con LIMIT. Por ejemplo, la siguiente sentencia encuentra filas que satisfagan la cláusula WHERE, las ordena por tiempos, y borra la primera (la más antigua):
DELETE FROM somelog
WHERE user = 'jcole'
ORDER BY timestamp
LIMIT 1


ORDER BY se puede usar con DELETE desde MySQL 4.0.0. Desde MySQL 4.0, se pueden especificar múltiples tablas en la sentencia DELETE para eliminar filas de una o más tablas dependiendo de una condición particular en múltiples tablas. Sin embargo, no es posible usar ORDER BY o LIMIT en un DELETE multitabla.

La primera sintaxis de DELETE para tablas múltiples está soportada a partir de MySQL 4.0.0. La segunda desde MySQL 4.0.2. La parte 'table_references' lista las tablas involucradas en la fusión. Su sintaxis se descirbe en .

Para la primera sintaxis, sólo se borran las filas coincidentes de las tablas listadas antes de la cláusula FROM. Para la segunda, sólo se borran las filas coincidentes de las tablas listadas en la cláusula FROM (antes de la cláusula USING). El efecto es que se pueden borrar filas de muchas tablas al mismo tiempo y además tener tablas adicionales que se usan para búsquedas:
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

Estas sentencias usan los tres ficheros cuando buscan filas para borrar, pero borran las filas coincidentes sólo de las tablas t1 y t2.

Los ejemplos muestran fusiones internas usando en operador coma, pero las sentencias DELETE multitabla pueden usar caulquier tipo de fusión (join) permitidas en sentencias , como LEFT JOIN.

El .* después de los nombres de tabla aparece sólo por compatibilidad con Access:
Si se usa una sentencia DELETE multitabla que afecte a tablas InnoDB para las que haya definiciones de claves foráneas, el optimizador MySQL procesará las tablas en un orden diferente del de la relación padre/hijo. En ese caso, la sentencia puede fallar y deshará los cambios (roll back). En su lugar, se debe borrar de una sola tabla y confiar el las capacidades de ON DELETE que proporciona InnoDB que harán que las otras tablas se modifiquen del modo adecuado.

Nota: en MySQL 4.0, se deben refirir a los nombre de tablas a borrar mediante su verdadero nombre. En MySQL 4.1, se debe usar un alias (si se ha dado uno) cuando se haga referencia al nombre de la tabla:

En MySQL 4.0:
DELETE test FROM test AS t1, test2 WHERE ...

En MySQL 4.1:
DELETE t1 FROM test AS t1, test2 WHERE ...

El motivo por el que no se hizo este cambio en 4.0 es que no se quería romper cualquier aplicación anterior a 4.0 que usase la sintaxis antigua.

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


Tomado de http://mysql.conclase.net/curso/?sqlsen=DELETE

saludos.