Можно ли удалить из нескольких таблиц в одной инструкции SQL?
можно удалить с помощью операторов join, чтобы квалифицировать набор для удаления, например:
DELETE J
FROM Users U
inner join LinkingTable J on U.id = J.U_id
inner join Groups G on J.G_id = G.id
WHERE G.Name = 'Whatever'
and U.Name not in ('Exclude list')
однако я заинтересован в удалении обеих сторон критериев соединения - обоих LinkingTable
запись и запись пользователя, от которых он зависит. Я не могу включить каскады, потому что мое решение-это код Entity Framework, а двунаправленные отношения-для нескольких каскадных путей.
В идеале, я хотел бы что-то например:
DELETE J, U
FROM Users U
inner join LinkingTable J on U.id = J.U_id
...
синтаксически это не работает, но мне интересно, возможно ли что-то подобное?
5 ответов
нет, вам нужно будет запустить несколько операторов.
поскольку вам нужно удалить из двух таблиц, подумайте о создании временной таблицы соответствующих идентификаторов:
SELECT U.Id INTO #RecordsToDelete
FROM Users U
JOIN LinkingTable J ON U.Id = J.U_Id
...
а затем удалить из каждой таблицы:
DELETE FROM Users
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
DELETE FROM LinkingTable
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
как вы говорите, возможно в MY SQL
но не на SQL SERVER
вы можете использовать "удаленную" псевдо-таблицу для удаления значений из двух таблиц одновременно, например,
begin transaction;
declare @deletedIds table ( samcol1 varchar(25) );
delete #temp1
output deleted.samcol1 into @deletedIds
from #temp1 t1
join #temp2 t2
on t2.samcol1 = t1.samcol1
delete #temp2
from #temp2 t2
join @deletedIds d
on d.samcol1 = t2.samcol1;
commit transaction;
для краткого объяснения вы можете взглянуть на это ссылке
и знать использование удаленной таблицы вы можете следовать этому С использованием inserted и deleted
единственный способ, который я мог придумать, - это логически сломать двунаправленные внешние ключи в процедурные путь.
этот подход может иметь огромное влияние на вашу сторону приложения, если у вас нет некоторых флагов для visualization
государство или status
что-то вроде
-
INSERT
фиктивные не видимые строки для пользователей (с чем-то вродеId = -1
для фиктивных значений) -
добавить
LinkingTable
альтернативный столбец точка кUsers
, Я называю этоU_ComesFrom
ALTER TABLE LinkingTagble добавить U_ComesFrom_U_id INT по умолчанию (-1)
-
добавить
FOREIGN KEY
СNOCHECK
изменить таблицу LinkingTable с NOCHECK
Внешний ключ (U_ComesFrom_U_id)
Ссылки пользователей (Id); -
добавить
Users
колонкипользователи ALTER TABLE добавляют бит MarkedForDeletion не NULL По умолчанию (0)
тогда ваш SQL будет выглядеть как
BEGIN TRANSACTION
UPDATE J
SET U_Comes_From_U_id = U_ID, U_id = -1 -- or some N/R value that you define in Users
FROM Users U
inner join LinkingTable J on U.id = J.U_id
inner join Groups G on J.G_id = G.id
WHERE G.Name = 'Whatever'
and U.Name not in ('Exclude list')
UPDATE U
SET MarkedForDeletion = 1
FROM Users
inner join LinkingTable J on U.id = J.U_ComesFrom_U_id
WHERE U_id > 0
DELETE FROM LinkingTable
WHERE U_ComesFrom_U_id > 0
DELETE FROM Users
WHERE MarkedForDeletion = 1
COMMIT
этот подход повлияет на производительность, так как каждая транзакция будет составлять не менее 4 операций DML на двунаправленные ключи.
используйте TRY CATCH с транзакцией
BEGIN TRANSACTION
BEGIN TRY
DELETE from A WHERE id=1
DELETE FROM b WHERE id=1
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
или для этого также можно использовать процедуру Store Использование Хранимой Процедуры С Транзакцией:
Если вы создаете внешний ключ через T-SQL, вы должны добавить параметр on DELETE CASCADE к внешнему ключу:
Code Snippet
ALTER TABLE <tablename>
ADD CONSTRAINT <constraintname> FOREIGN KEY (<columnname(s)>)
REFERENCES <referencedtablename> (<columnname(s)>)
ON DELETE CASCADE;