Как удалить данные из нескольких таблиц?
У меня есть следующие таблицы:
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 и запустите на сервере.