2009-08-27 17 views
7

Tengo dos tablas: orders y orders_items. Ambos comparten el campo orderID.Eliminar filas de dos tablas en una consulta

Quiero eliminar todas las filas de ambas tablas donde orderID = 500, pero tengo que hacer esto en una sola consulta. es posible?

+0

¿Por qué tendrías que hacerlo en una consulta? Dependiendo de la forma en que acceda a la base de datos, puede usar dos declaraciones separadas por punto y coma y tratarla como una sola. La única otra forma que conozco es utilizar el procedimiento almacenado. –

+0

sí, lo sé. Pero tengo que hacerlo manualmente con miles de filas. La idea es hacerlo en una sola consulta para tratar de evitar errores de volcado. –

Respuesta

8

Puede definir la tabla con ON DELETE CASCADE. Si lo hace, solo debe eliminar en la tabla de pedidos. Las entradas en otras tablas que usan order_id como clave foránea con esa opción activada se eliminarán automágicamente.

Este ejemplo se toma de la MySQL manual:

CREATE TABLE parent(
    id INT NOT NULL, 
    PRIMARY KEY (id) 
) ENGINE=INNODB; 

CREATE TABLE child(
    id INT, parent_id INT, 
    INDEX par_ind (parent_id), 
    FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE 
) ENGINE=INNODB; 

Tenga en cuenta que el motor es InnoDB.

+0

Suena bien. Lo intentaré. Y vuelva. –

+1

Funcionó como un amuleto. Gracias. ALTER TABLE orders_items ADD FOREIGN KEY (orderID) REFERENCES orders (orderID) ON DELETE CASCADE –

1

¿Podría utilizar una función almacenada y llamarla?

Y luego, dentro de su función almacenada, tendría ambas consultas ELIMINAR. Luego, cuando se llame a la función almacenada, se ejecutará como una transacción y usted podrá hacer que devuelva lo que quiera.

+0

procedimientos almacenados son difíciles de alcanzar para mí. No me gusta :-( –

10

Sin duda, se puede hacer eso:

DELETE FROM `table1`, `table2` WHERE `orderId` = 500 

ver http://dev.mysql.com/doc/refman/5.0/en/delete.html

[EDIT:]

Este es todo el truco:

DELETE FROM `orders`, `orders_items` 
    USING `orders` 
    INNER JOIN `orders_items` ON `orders`.`orderId` = `orders_items`.`orderId` 
    WHERE `orders`.`orderId`= 500 

Si orderId es un varchar luego cambie la instrucción a = '500'.

+0

# 1064 - Tiene un error en su sintaxis SQL, consulte el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de 'donde orderID = 500' en la línea 1 –

3

Eso depende del motor de su base de datos, pero básicamente lo que necesita suena como que quiere una tabla haciendo referencia al otro usando una opción FOREIGN KEY con ON DELETE CASCADE y luego la eliminación de la tabla primaria eliminará automáticamente las filas correspondientes de las tablas dependientes.

+0

Solo quería escribir lo mismo :) Cascade es lo más fácil de hacer. – Thinker

+0

investigando, gracias –

2

Aquí hay una simple solución si estás usando MySQL/PgSQL ...

DELETE t1, t2 FROM table1 AS t1 
LEFT JOIN table2 AS t2 USING(orderID) 
WHERE t1.orderID = 500; 

garantizado para trabajar como un encanto!

Asegúrese de reemplazar tabla1 tabla2 y con los nombres de tablas apropiadas en su caso.

He utilizado muchas de estas consultas en mi CMS personalizado, dondequiera que haya querido evitar dos consultas atómicas distintas. Esto es tan bueno como una eliminación en cascada y la consulta se puede expandir para abarcar tantas tablas como desee.

Aquí hay otro ejemplo que implica 3 tablas:

DELETE t1, t2, t3 FROM table1 AS t1 
LEFT JOIN table2 AS t2 USING(orderID) 
LEFT JOIN table3 AS t3 USING(orderID) 
WHERE t1.orderID = 500; 

Cheers, m^e

+0

Oh, bien. Lo tendré en cuenta. –

2

Si está utilizando InnoDB (o un motor de almacenamiento compatible con ellas) que puede utilizar FOREIGN KEY constraints para eliminar la Correspoding filas.Este es uno de los enfoques más fáciles/más seguros si no le importa el ligero impacto en el rendimiento de las claves externas. Sin embargo, tenga en cuenta que las filas eliminadas debido a restricciones no reciben activadores para disparar.

Alternativamente, puede usar desencadenantes. Funcionan con cualquier motor de almacenamiento y generalmente son lo suficientemente fáciles de escribir. Me gustan pero no son de buen calidad si va a eliminar un gran número de filas a la vez (varios cientos o miles.)

CREATE TRIGGER ad_orders AFTER DELETE ON orders 
FOR EACH ROW DELETE FROM orders_items WHERE orderID = OLD.orderID; 

Por último, como se sugiere en una respuesta anterior, podría utilizar múltiples table DELETE:

DELETE o, oi 
FROM orders o 
LEFT JOIN orders_items oi USING (orderID) 
WHERE o.orderID = 500; 
+0

muchas gracias –

Cuestiones relacionadas