Как удалить из нескольких таблиц, используя INNER JOIN на сервере SQL - PullRequest
101 голосов
/ 24 апреля 2009

В MySQL вы можете использовать синтаксис

DELETE t1,t2 
FROM table1 AS t1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

Как мне сделать то же самое в SQL Server?

Ответы [ 13 ]

110 голосов
/ 01 мая 2009

В этом примере вы можете воспользоваться «удаленной» псевдо-таблицей. Что-то вроде:

begin transaction;

   declare @deletedIds table ( id int );

   delete from t1
   output deleted.id into @deletedIds
   from table1 as t1
    inner join table2 as t2
      on t2.id = t1.id
    inner join table3 as t3
      on t3.id = t2.id;

   delete from t2
   from table2 as t2
    inner join @deletedIds as d
      on d.id = t2.id;

   delete from t3
   from table3 as t3 ...

commit transaction;

Очевидно, что вы можете сделать «вывод удален». на втором также удалите, если вам нужно что-то присоединиться к третьей таблице.

В качестве примечания вы также можете вставить. * В оператор вставки, а также вставить. * И удалить. * В оператор обновления.

EDIT: Кроме того, вы рассматривали возможность добавления триггера на table1 для удаления из table2 + 3? Вы будете внутри неявной транзакции, и вам также будут доступны псевдотаблицы «вставлено. » и «удалено. ».

15 голосов
/ 24 апреля 2009
  1. Вы всегда можете установить каскадные удаления для отношений таблиц.

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

  3. Вы можете использовать транзакцию для обеспечения одной единицы работы.

14 голосов
/ 24 апреля 2009

Вы можете использовать синтаксис JOIN в предложении FROM в DELETE в SQL Server, но вы все равно удаляете только из первой таблицы, и это собственное расширение Transact-SQL, которое является альтернативой подзапросу.

Из примера здесь :

 -- Transact-SQL extension
 DELETE 
   FROM Sales.SalesPersonQuotaHistory 
     FROM Sales.SalesPersonQuotaHistory AS spqh INNER JOIN 
          Sales.SalesPerson AS sp ON spqh.BusinessEntityID = sp.BusinessEntityID
    WHERE sp.SalesYTD > 2500000.00;
11 голосов
/ 07 апреля 2011

Пример удаления некоторых записей из основной таблицы и соответствующих записей из двух таблиц подробностей:

BEGIN TRAN

  -- create temporary table for deleted IDs
  CREATE TABLE #DeleteIds (
    Id INT NOT NULL PRIMARY KEY
  )

  -- save IDs of master table records (you want to delete) to temporary table    
  INSERT INTO #DeleteIds(Id)
  SELECT DISTINCT mt.MasterTableId
  FROM MasterTable mt 
  INNER JOIN ... 
  WHERE ...  

  -- delete from first detail table using join syntax
  DELETE d
  FROM DetailTable_1 D
  INNER JOIN #DeleteIds X
    ON D.MasterTableId = X.Id


  -- delete from second detail table using IN clause  
  DELETE FROM DetailTable_2
  WHERE MasterTableId IN (
    SELECT X.Id
    FROM #DeleteIds X
  )


  -- and finally delete from master table
  DELETE d
  FROM MasterTable D
  INNER JOIN #DeleteIds X
    ON D.MasterTableId = X.Id

  -- do not forget to drop the temp table
  DROP TABLE #DeleteIds

COMMIT
9 голосов
/ 24 апреля 2009

Просто интересно ... это действительно возможно в MySQL? это удалит t1 и t2? или я просто неправильно понял вопрос.

Но если вы просто хотите удалить table1 с несколькими условиями соединения, просто не создавайте псевдоним таблицы, которую вы хотите удалить

это:

DELETE t1,t2 
FROM table1 AS t1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

должно быть написано так, чтобы работать в MSSQL:

DELETE table1
FROM table1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

для сравнения того, как две другие распространенные СУБД выполняют операцию удаления:

http://mssql -to-postgresql.blogspot.com / 2007/12 / удаление-дубликаты-в-PostGreSQL-ms.html

7 голосов
/ 24 апреля 2009

По сути, нет необходимости делать три оператора удаления в транзакции, сначала детей, а затем родителей. Настройка каскадного удаления - это хорошая идея, если это не одноразовая вещь и ее существование не будет конфликтовать ни с одной из существующих настроек триггера.

3 голосов
/ 24 апреля 2009

На сервере SQL нет способа удалить несколько таблиц с помощью объединения. Таким образом, вы должны сначала удалить ребенка, а затем удалить родительскую форму.

2 голосов
/ 14 июля 2011

Это альтернативный способ удаления записей, не оставляя сирот.


Declare @user Table(keyValue int  , someString varchar(10))
insert into @user
values(1,'1 value')

insert into @user
values(2,'2 value')

insert into @user
values(3,'3 value')

Declare @password Table(  keyValue int , details varchar(10))
insert into @password
values(1,'1 Password')
insert into @password
values(2,'2 Password')
insert into @password
values(3,'3 Password')

        --before deletion
  select * from @password a inner join @user b
                on a.keyvalue = b.keyvalue
  select * into #deletedID from @user where keyvalue=1 -- this works like the output example
  delete  @user where keyvalue =1
  delete @password where keyvalue in (select keyvalue from #deletedid)

  --After deletion--
  select * from @password a inner join @user b
                on a.keyvalue = b.keyvalue

2 голосов
/ 06 августа 2010

Все было указано. Просто используйте DELETE ON CASCADE на родительском table или удалите из child-table в parent.

1 голос
/ 24 апреля 2009

Как уже указывал Аарон, вы можете установить поведение удаления в CASCADE, и это будет удалять дочерние записи при удалении родительской записи. Если вы не хотите, чтобы случилась какая-то другая магия (в этом случае пункты 2, 3 ответа Аарона были бы полезны), я не понимаю, зачем вам удалять с помощью внутренних объединений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...