Сценарий:
Скажем, у меня есть две таблицы: TableA и TableB. Первичный ключ TableB представляет собой отдельный столбец (BId) и является столбцом внешнего ключа в TableA.
В моей ситуации я хочу удалить все строки в TableA, которые связаны с определенными строками в TableB: Могу ли я сделать это через соединения? Удалить все строки, вытянутые из соединений?
DELETE FROM TableA
FROM
TableA a
INNER JOIN TableB b
ON b.BId = a.BId
AND [my filter condition]
Или я вынужден сделать это:
DELETE FROM TableA
WHERE
BId IN (SELECT BId FROM TableB WHERE [my filter condition])
Причина, по которой я спрашиваю, заключается в том, что мне кажется, что первый вариант будет намного эффективнее при работе с большими таблицами.
Спасибо!





DELETE TableA
FROM TableA a
INNER JOIN TableB b
ON b.Bid = a.Bid
AND [my filter condition]
должно сработать
Один вопрос. Почему нам нужно писать «УДАЛИТЬ TableA FROM» вместо «DELETE FROM»? Я вижу, это работает только в этом случае, но почему?
Думаю, потому что нужно указать, из какой таблицы удалять записи. Я только что выполнил запрос с синтаксисом DELETE TableA, TableB ... и фактически удалил соответствующие записи из обоих. Хороший.
В PostgreSQL синтаксис с join не работает, но можно использовать ключевое слово using. DELETE from TableA a using TableB b where b.Bid = a.Bid and [my filter condition]
В MySQL вы получите сообщение об ошибке «Неизвестная таблица TableA в MULTI DELETE», потому что вы объявили псевдоним для TableA (a). Небольшая регулировка: DELETE a FROM TableA a INNER JOIN TableB b on b.Bid = a.Bid and [my filter condition]
У меня работает в SQL2008 +1
У меня похожий вопрос. Я хочу удалить из обеих таблиц A и B. Как мне это сделать? Вопрос - stackoverflow.com/questions/21620018/… Спасибо.
Этот ответ мне просто помог ... Спасибо и спасибо за базы знаний.
DELETE a FROM TableA a ... ... - это правильный путь
Это не лучшее решение. Объединения следует использовать только тогда, когда пользователю необходимо получить данные из нескольких таблиц. Для DML, таких как обновления и удаления, вам нужно только уточнить совокупность. Таким образом, запрос на удаление должен относиться к 1 таблице, а затем вы присоединяетесь к подзапросу. мой ответ ниже.
Да, ты можешь. Пример :
DELETE TableA
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
Я предпочитаю ссылаться на таблицу в первой строке по ее псевдониму. То есть «Удалить», а не «Удалить таблицу А». В случае, когда вы присоединяетесь к таблице с самим собой, он дает понять, с какой стороны вы хотите удалить.
Я бы использовал этот синтаксис
Delete a
from TableA a
Inner Join TableB b
on a.BId = b.BId
WHERE [filter condition]
Я тоже предпочитаю этот синтаксис, который, кажется, имеет больше логического смысла в том, что происходит. Кроме того, я знаю, что вы можете использовать такой же синтаксис для ОБНОВЛЕНИЯ.
Я тоже предпочитаю это, потому что размещение псевдонима таблицы после DELETE всегда казалось мне более интуитивным в отношении того, что удаляется.
На самом деле, это тоже предпочтительнее для меня. В частности, в тех случаях, когда мне действительно нужно присоединиться к одной и той же таблице (например, для удаления повторяющихся записей). В этом случае мне нужно использовать псевдоним для «стороны», с которой я удаляю, и этот синтаксис делает очень понятным, что я удаляю из псевдонима дубликатов.
Это почти то же самое в MySQL, но вы должны использовать псевдоним таблицы сразу после слова "DELETE":
DELETE a
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
Пытался сделать это с помощью базы данных доступа и обнаружил, что мне нужно использовать а. * сразу после удаления.
DELETE a.*
FROM TableA AS a
INNER JOIN TableB AS b
ON a.BId = b.BId
WHERE [filter condition]
Из отклоненного ожидающего редактирования: «Свойство UniqueRecords должно иметь значение« да », иначе оно не будет работать. (support.microsoft.com/kb/240098)»
Приведенный выше синтаксис не работает в Interbase 2007. Вместо этого мне пришлось использовать что-то вроде:
DELETE FROM TableA a WHERE [filter condition on TableA]
AND (a.BId IN (SELECT a.BId FROM TableB b JOIN TableA a
ON a.BId = b.BId
WHERE [filter condition on TableB]))
(Обратите внимание, Interbase не поддерживает ключевое слово AS для псевдонимов)
Допустим, у вас есть 2 таблицы, одна с главным набором (например, сотрудники) и одна с дочерним набором (например, зависимые), и вы хотите избавиться от всех строк данных в таблице зависимых, которые не могут быть задействованы. с любыми строками в главной таблице.
delete from Dependents where EmpID in (
select d.EmpID from Employees e
right join Dependents d on e.EmpID = d.EmpID
where e.EmpID is null)
Здесь следует обратить внимание на то, что вы сначала собираете «массив» идентификаторов EmpID из соединения, используя этот набор идентификаторов EmpID для выполнения операции удаления в таблице зависимых.
В SQLite единственное, что работает, - это что-то вроде ответа beauXjames.
Кажется, все сводится к этому
DELETE FROM table1 WHERE table1.col1 IN (SOME TEMPORARY TABLE);
и что некоторая временная таблица может быть создана с помощью SELECT и JOIN ваших двух таблиц, которые вы можете фильтровать эту временную таблицу на основе условия, при котором вы хотите удалить записи в Table1.
Вы можете запустить этот запрос:
DELETE FROM TableA
FROM
TableA a, TableB b
WHERE
a.Bid=b.Bid
AND
[my filter condition]
Я использую это
DELETE TableA
FROM TableA a
INNER JOIN
TableB b on b.Bid = a.Bid
AND [condition]
и способ @TheTXI достаточно хорош, но я прочитал ответы и комментарии и обнаружил, что на одну вещь, на которую нужно ответить, нужно ответить, это использование условия в предложении WHERE или как условие соединения. Поэтому я решил протестировать его и написать отрывок, но не нашел между ними значимой разницы. Здесь вы можете увидеть sql-скрипт, и важным моментом является то, что я предпочел написать его как commnet, потому что это не точный ответ, но он большой и не может быть помещен в комментарии, пожалуйста, простите меня.
Declare @TableA Table
(
aId INT,
aName VARCHAR(50),
bId INT
)
Declare @TableB Table
(
bId INT,
bName VARCHAR(50)
)
Declare @TableC Table
(
cId INT,
cName VARCHAR(50),
dId INT
)
Declare @TableD Table
(
dId INT,
dName VARCHAR(50)
)
DECLARE @StartTime DATETIME;
SELECT @startTime = GETDATE();
DECLARE @i INT;
SET @i = 1;
WHILE @i < 1000000
BEGIN
INSERT INTO @TableB VALUES(@i, 'nameB:' + CONVERT(VARCHAR, @i))
INSERT INTO @TableA VALUES(@i+5, 'nameA:' + CONVERT(VARCHAR, @i+5), @i)
SET @i = @i + 1;
END
SELECT @startTime = GETDATE()
DELETE a
--SELECT *
FROM @TableA a
Inner Join @TableB b
ON a.BId = b.BId
WHERE a.aName LIKE '%5'
SELECT Duration = DATEDIFF(ms,@StartTime,GETDATE())
SET @i = 1;
WHILE @i < 1000000
BEGIN
INSERT INTO @TableD VALUES(@i, 'nameB:' + CONVERT(VARCHAR, @i))
INSERT INTO @TableC VALUES(@i+5, 'nameA:' + CONVERT(VARCHAR, @i+5), @i)
SET @i = @i + 1;
END
SELECT @startTime = GETDATE()
DELETE c
--SELECT *
FROM @TableC c
Inner Join @TableD d
ON c.DId = d.DId
AND c.cName LIKE '%5'
SELECT Duration = DATEDIFF(ms,@StartTime,GETDATE())
Если вы могли почерпнуть из этого сценария вескую причину или написать другой полезный, поделитесь. Спасибо и надеюсь, что это поможет.
Более простой способ:
DELETE TableA
FROM TableB
WHERE TableA.ID = TableB.ID
DELETE FROM table1
where id IN
(SELECT id FROM table2..INNER JOIN..INNER JOIN WHERE etc)
Сведите к минимуму использование запросов DML с помощью соединений. Вы должны уметь выполнять большинство всех запросов DML с подзапросами, как указано выше.
В общем, объединения следует использовать только тогда, когда вам нужно ВЫБРАТЬ или ГРУППИРОВАТЬ по столбцам в 2 или более таблицах. Если вы Только касаетесь нескольких таблиц для определения совокупности, используйте подзапросы. Для запросов DELETE используйте коррелированный подзапрос.
Я использовал And [мое условие фильтра] для соединения вместо предложения Where. Я предполагаю, что оба будут работать, но условие фильтрации соединения ограничит ваши результаты от соединения.