2009-08-27 4 views
7

Ho due tabelle: ordini e ordini_itemi. Entrambi condividono il campo orderID.Elimina righe da due tabelle in una query

Voglio eliminare tutte le righe da entrambe le tabelle dove orderID = 500, ma ho bisogno di farlo in una sola query. È possibile?

+0

Perché dovresti farlo in una query? A seconda del modo in cui si accede al database, è possibile utilizzare due istruzioni separate da punto e virgola e trattarle come una sola. L'unico altro modo che conosco è usare la stored procedure. –

+0

sì, lo so. Ma devo farlo manualmente con migliaia di righe. L'idea è di farlo in una sola query per cercare di evitare errori di ribaltamento. Le stored procedure –

risposta

8

È possibile definire la tabella con ON DELETE CASCADE. Se lo fai, devi solo cancellare nella tabella degli ordini. Le voci in altre tabelle che utilizzano order_id come chiave esterna con quell'opzione abilitata verranno eliminate automaticamente.

Questo esempio è tratto dal 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; 

Si noti che il motore è InnoDB.

+0

Suono ok, ci proverò E tornerò –

+1

Ha funzionato come un incantesimo Grazie ALTER TABLE orders_items AGGIUNGI CHIAVE ESTERA (orderID) REFERENCES ordini (orderID) ON DELETE CASCADE –

1

È possibile utilizzare una funzione memorizzata e chiamarla?

E quindi all'interno della funzione memorizzata si avranno entrambe le query DELETE. Quindi, quando viene chiamata la funzione memorizzata, verrà eseguita come una transazione e sarà possibile restituire tutto ciò che ti piace.

+0

sono inafferrabili per me. Non mi piaccio :-( –

10

Sicuramente si può fare:

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

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

[EDIT:]

Questo è il trucco tutto:

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

Se orderId è un varchar, quindi modificare la dichiarazione in = '500'.

+0

# 1064 - Si è verificato un errore nella sintassi SQL, controllare il manuale corrispondente alla versione del server MySQL per la sintassi corretta da utilizzare vicino a "where IDID = 500" alla riga 1 –

3

Questo dipende dal vostro motore di database, ma in fondo quello che vi serve Sembra che si desidera una tabella di corrispondenza tra l'altro utilizzando un FOREIGN KEY con ON DELETE CASCADE opzione e quindi la rimozione dalla tabella padre rimuoverà automaticamente righe corrispondenti dalle tabelle dipendenti.

+0

Volevo solo scrivere la stessa cosa :) Cascade è la cosa più facile da fare. – Thinker

+0

guardando dentro, grazie –

2

Ecco una semplice soluzione se si sta utilizzando MySQL/PgSQL ...

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

Garantito per lavorare come un fascino!

Assicurarsi di sostituire table1 e table2 con opportuni nomi di tabella nel tuo caso.

Ho usato un sacco di questa query nel mio CMS progettato su misura - ovunque io abbia voluto evitare due distinte query atomiche. Questo è buono come eliminazione a cascata e la query può essere espansa per estendersi su tutte le tabelle che vuoi.

Ecco un altro esempio che coinvolge 3 tabelle:

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; 

Acclamazioni, m^e

+0

Oh, bello. Lo terrò a mente. –

2

Se stai usando InnoDB (o un motore di storage che li sostiene) è possibile utilizzare FOREIGN KEY constraints per eliminare il righe corrispondenti.Questo è uno degli approcci più facili/sicuri se non ti interessa il leggero impatto sulle prestazioni delle chiavi esterne. Si noti tuttavia che le righe eliminate a causa di vincoli non attivano i trigger.

In alternativa, è possibile utilizzare i trigger. Funzionano con qualsiasi motore di archiviazione e di solito sono abbastanza facili da scrivere. Mi piacciono, ma non sono molto performante se si sta cancellando un gran numero di righe in una sola volta (diverse centinaia o migliaia.)

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

Infine, come suggerito in una risposta precedente, è possibile utilizzare multi- tabella DELETE:

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

grazie mille –