SQL Server:从表中删除表

时间:2019-06-05 00:57:03

标签: sql-server tsql

我一直在SQL Server中遇到这种DELETE FROM FROM语法,并且不得不提醒自己它的作用。

DELETE FROM tbl
FROM #tbl
  INNER JOIN tbl ON fk = pk AND DATEDIFF(day, #tbl.date, tbl.Date) = 0

编辑:为了使大多数评论和建议答案有意义,原始问题具有以下查询:

DELETE FROM tbl
FROM tbl2

2 个答案:

答案 0 :(得分:4)

据我了解,您将使用类似 的结构,在该结构中,您将根据from查询的结果来限制从第一张表中删除哪些行。但是要做到这一点,您需要在两者之间建立关联。

在您的示例中,没有关联,这实际上是一种交叉连接,这意味着“对于tbl2中的每一行,删除tbl1中的每一行”。换句话说,它将删除第一张表中的每一行。

这里是一个例子:

declare @t1 table(A int, B int)
insert @t1 values (15, 9)
,(30, 10)
,(60, 11)
,(70, 12)
,(80, 13)
,(90, 15)

declare @t2 table(A int, B int)
insert @t2 values (15, 9)
,(30, 10)
,(60, 11)

delete from @t1 from @t2

结果为空@ t1。

另一方面,这只会删除匹配的行:

delete from @t1 from @t2 t2 join @t1 t1 on t1.A=t2.A

答案 1 :(得分:2)

我以前从没见过。 DELETE的文档告诉我们:

  

FROM table_source指定附加的FROM子句。这个   Transact-SQL扩展到DELETE允许从    并从表中删除相应的行   第一个FROM子句。

     

可以使用此扩展名(指定连接)来代替子查询   在WHERE子句中以标识要删除的行。

后来在我们找到的同一文档中

  

D。使用联接和子查询到一个表中的数据以删除其中的行   另一个表以下示例显示了两种删除表中行的方法   一个表基于另一个表中的数据。在两个示例中,来自   AdventureWorks2012数据库中的SalesPersonQuotaHistory表   根据存储在SalesPerson中的最新销售额删除   表。第一条DELETE语句显示与ISO兼容的子查询   解决方案,第二个DELETE语句显示Transact-SQL FROM   连接两个表的扩展名。

通过这些示例来展示差异

-SQL-2003标准子查询

DELETE FROM Sales.SalesPersonQuotaHistory   
WHERE BusinessEntityID IN   
    (SELECT BusinessEntityID   
     FROM Sales.SalesPerson   
     WHERE SalesYTD > 2500000.00);

-Transact-SQL扩展

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;  

在这种情况下,第二个FROM提到了同一张表。这是获得类似于可更新的cte 派生表

的方法的怪异方法

在D部分的第三个示例中,文档清楚地说明了

-无需多次提及目标表。

DELETE spqh  
  FROM  
        Sales.SalesPersonQuotaHistory AS spqh  
    INNER JOIN Sales.SalesPerson AS sp  
        ON spqh.BusinessEntityID = sp.BusinessEntityID  
  WHERE  sp.SalesYTD > 2500000.00;  

因此,给我的印象是,这样做的唯一原因是使用真实表的名称作为DELETE的目标而不是别名。