Как удалить данные из нескольких таблиц?

У меня есть следующие таблицы:

event     (evt_id, evt_code, reg_id)

magnitude (mag_id, evt_id, value)

trace     (trace_id, pt_id)

point     (pt_id, evt_id)

Я хочу удалить все строки из всех таблиц, связанных с evt_id=1139.
Как это сделать?

Ответы

Ответ 1

Если у вас есть контроль над вашей схемой, я бы сделал использование схемы каскадным удалением.

Из статьи (более подходящая часть переведена для вашего примера)

CREATE TABLE point
(
    pt_id integer PRIMARY KEY,
    evt_id integer REFERENCES event ON DELETE CASCADE
)

Если у вас установлены каскады, вы можете просто удалить из основной таблицы событий, а все остальные таблицы будут автоматически очищены.

В противном случае сначала необходимо удалить все ссылки, а затем удалить основную таблицу. Вы должны сделать это в одной транзакции, чтобы сохранить согласованные данные

BEGIN;
DELETE FROM trace WHERE EXISTS 
    (SELECT 1 FROM point WHERE evt_id = 1139 AND trace.pt_id = point.pt_id);
DELETE FROM point where evt_id = 1139;
DELETE FROM magnitude where evt_id = 1139;
DELETE FROM event where evt_id = 1139;
COMMIT;

Ответ 2

Единственный нетривиальный элемент в вашем вопросе - удалить из таблицы trace. Я думаю, можно с уверенностью предположить, что trace.pt_id ссылается на point.pt_id?

Либо вы определяете внешний ключ с ON DELETE CASCADE, и просто забудьте о таблице trace (как уже указанном @kevin), или вам нужно позаботиться о разных строках вручную.

Поскольку PostgreSQL 9.1 вы можете использовать изменяющие данные CTE:

BEGIN;

WITH x AS (
    DELETE FROM point WHERE evt_id = 1139
    RETURNING pt_id
    )
DELETE FROM trace
USING x
WHERE trace.pt_id = x.pt_id;

DELETE FROM magnitude WHERE evt_id = 1139;

DELETE FROM event WHERE evt_id = 1139;

COMMIT;

Предложение RETURNING DELETE FROM point возвращает все затронутые pt_id - те, которые в свою очередь используются для удаления всех соответствующих строк из trace.

Вы не указали, является ли проблема concurrency в вашем случае. Если это так, и если вы хотите избежать возможных результатов в коротком временном окне между удалением, где строки для evt_id = 1139 присутствуют в одной таблице, а уже удалены из другого, заверните все это в транзакцию .
Если это вас не касается, игнорируйте BEGIN и COMMIT.

Ответ 3

Если строки, которые вы хотите удалить, могут быть представлены как иерархия, вы можете определить ограничения FOREIGN KEY для отношений с предложением ON DELETE CASCADE. Удаление строки сверху приведет к каскаду и удалению всех.

http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK

Ответ 4

Я предполагаю, что идентификатор в разных таблицах соответствует и используется для связывания. Я также предполагаю, что вы хотите удалить все точки трассировки, хотя они косвенно связаны с evt_id

Вы можете удалить свои записи из всех таблиц следующим образом:

DELETE event , magnitude, trace, point
FROM event left join magnitude on event.evt_id = magnitude.evt_id
   left join point on event.evt_id = point.evt_id
       left join trace on point.pt_id = trace.trace_id
where event_id=1139

Ответ 5

$delete =  1139;
$query = "DELETE FROM event, magnitude, point WHERE evt_id = '$delete'";
mysql_query($query, $con);
$query = "DELETE FROM trace WHERE pt_id = '$delete'";

или просто вставьте этот оператор в файл .sql и запустите его или в окно запроса программного обеспечения sql или поместите его в файл .php и запустите на сервере.