【问题标题】:How can I delete using INNER JOIN with SQL Server?如何在 SQL Server 中使用 INNER JOIN 进行删除?
【发布时间】:2013-05-05 02:04:01
【问题描述】:

我想在 SQL Server 2008 中使用INNER JOIN删除。

但我收到此错误:

消息 156,级别 15,状态 1,第 15 行
关键字“INNER”附近的不正确语法。

我的代码:

DELETE 
FROM WorkRecord2 
INNER JOIN Employee 
        ON EmployeeRun=EmployeeNo
WHERE Company = '1' 
    AND Date = '2013-05-06'

【问题讨论】:

  • documentation 中的示例 C 显示了如何将 DELETE 与连接一起使用
  • 示例 C 也使用了光标和一堆无关的东西

标签: sql sql-server sql-server-2008 inner-join sql-delete


【解决方案1】:

您需要指定要从哪个表中删除。这是一个带有别名的版本:

DELETE w
FROM WorkRecord2 w
INNER JOIN Employee e
  ON EmployeeRun=EmployeeNo
WHERE Company = '1' AND Date = '2013-05-06'

【讨论】:

  • @bluefeet 您能否为 SQL Server 提供正确的语法以从两个表中删除?
  • @user2070775 在 SQL Server 中要从 2 个表中删除,您需要使用 2 个单独的语句。
  • @user2070775在SQL Server中,可以使用事务和伪表,如stackoverflow.com/questions/783726/…所示
  • @MathieuRodic 感谢分享。在我的设置中,如果我分别从 2 个表中删除,我真的不知道要从第 2 个表中删除哪些行,所以这将有所帮助:)
  • @ShahryarSaljoughi 是 WorkRecord2 表的别名。
【解决方案2】:

只需在要删除记录的DELETE 和FROM 之间添加表名,因为我们必须指定要删除的表。同时删除ORDER BY 子句,因为在删除记录时没有什么可订购的。

所以你的最终查询应该是这样的:

    DELETE WorkRecord2 
      FROM WorkRecord2 
INNER JOIN Employee 
        ON EmployeeRun=EmployeeNo
     WHERE Company = '1' 
       AND Date = '2013-05-06';

【讨论】:

  • 如果您只打算从第一个表中删除,此方法适用于 SQL Server。
  • @mattwonk:如果您使用第二个表的名称,您可以从第二个表中删除。例如。使用 DELETE Employee 将从 Employee 表中删除,而不是 WorkRecord2 表。
  • @matwonk:这是一个例子:1) Deleting from the first table 2) Deleting from the second table.
  • 如果您要从以自身为外键的表中删除(而不是使用级联删除),则删除顺序可能很重要。但我同意一般来说没关系...
【解决方案3】:

这可能对你有帮助 -

DELETE FROM dbo.WorkRecord2
WHERE EmployeeRun IN (
    SELECT e.EmployeeNo
    FROM dbo.Employee e
    WHERE ...
)

或者试试这个 -

DELETE FROM dbo.WorkRecord2
WHERE EXISTS(
    SELECT 1
    FROM dbo.Employee e
    WHERE EmployeeRun = e.EmployeeNo
        AND ....
)

【讨论】:

  • 这是唯一适用于 Sql Server 的答案。只需构建您的查询,例如 select Id from... join ... join 等,然后将其包装为子查询并从(表)中删除(子查询)中的 Id
  • 这是适用于 SQL Server 的众多答案之一。我建议接受的答案是最好的方法。
【解决方案4】:

试试这个:

DELETE FROM WorkRecord2 
       FROM Employee 
Where EmployeeRun=EmployeeNo
      And Company = '1' 
      AND Date = '2013-05-06'

【讨论】:

    【解决方案5】:

    试试这个查询:

    DELETE WorkRecord2, Employee 
    FROM WorkRecord2 
    INNER JOIN Employee ON (tbl_name.EmployeeRun=tbl_name.EmployeeNo)
    WHERE tbl_name.Company = '1' 
    AND tbl_name.Date = '2013-05-06';
    

    【讨论】:

    • 我很确定 DELETE 只能指定一个表。这对我不起作用。
    • 我相信您可以在 mySQL 中指定要删除的多个表,但不能指定 SQL Server(问题要求)。
    【解决方案6】:

    这个版本应该可以工作:

    DELETE WorkRecord2
    FROM WorkRecord2 
    INNER JOIN Employee ON EmployeeRun=EmployeeNo
    Where Company = '1' AND Date = '2013-05-06'
    

    【讨论】:

      【解决方案7】:

      应该是:

      DELETE zpost 
      FROM zpost 
      INNER JOIN zcomment ON (zpost.zpostid = zcomment.zpostid)
      WHERE zcomment.icomment = "first"       
      

      【讨论】:

        【解决方案8】:
         DELETE a FROM WorkRecord2 a 
               INNER JOIN Employee b 
               ON a.EmployeeRun = b.EmployeeNo 
               Where a.Company = '1' 
               AND a.Date = '2013-05-06'
        

        【讨论】:

          【解决方案9】:

          在SQL Server Management Studio 中我可以轻松创建SELECT 查询:

          SELECT Contact.Naam_Contactpersoon, Bedrijf.BedrijfsNaam, Bedrijf.Adres, Bedrijf.Postcode
          FROM Contact
          INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
          

          我可以执行它,我的所有联系人都会显示出来。

          现在将SELECT 更改为DELETE:

          DELETE Contact
          FROM Contact
          INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
          

          您在SELECT 语句中看到的所有记录都将被删除。

          您甚至可以使用相同的过程创建更困难的内部连接,例如:

          DELETE FROM Contact
          INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
          INNER JOIN LoginBedrijf ON Bedrijf.IDLoginBedrijf = LoginBedrijf.IDLoginBedrijf
          

          【讨论】:

            【解决方案10】:

            这是我的 SQL Server 版本

            DECLARE @ProfileId table(Id bigint)
            
            DELETE FROM AspNetUsers
            OUTPUT deleted.ProfileId INTO @ProfileId
            WHERE Email = @email
            
            DELETE FROM UserProfiles    
            WHERE Id = (Select Id FROM @ProfileId)
            

            【讨论】:

              【解决方案11】:

              您没有为Company 和Date 指定表,您可能需要解决这个问题。

              使用MERGE的标准SQL:

              MERGE WorkRecord2 T
                 USING Employee S
                    ON T.EmployeeRun = S.EmployeeNo
                       AND Company = '1'
                       AND Date = '2013-05-06'
              WHEN MATCHED THEN DELETE;
              

              The answer from Devart 也是标准 SQL,虽然不完整。它应该看起来更像这样:

              DELETE
                FROM WorkRecord2
                WHERE EXISTS ( SELECT *
                                 FROM Employee S
                                WHERE S.EmployeeNo = WorkRecord2.EmployeeRun
                                      AND Company = '1'
                                      AND Date = '2013-05-06' );
              

              关于上述要注意的重要一点是,很明显删除是针对单个表的,正如第二个示例中通过要求标量子查询强制执行的那样。

              对我来说,各种专有语法答案更难阅读和理解。我想the answer by frans eilering 中最好地描述了这种心态,即编写代码的人不一定关心阅读和维护代码的人。

              【讨论】:

                【解决方案12】:

                另一种方法是使用CTE:

                ;WITH cte
                     AS (SELECT *
                         FROM   workrecord2 w
                         WHERE  EXISTS (SELECT 1
                                        FROM   employee e
                                        WHERE  employeerun = employeeno
                                               AND company = '1'
                                               AND date = '2013-05-06'))
                DELETE FROM cte
                

                注意:当你想delete时,我们不能在CTE中使用JOIN。

                【讨论】:

                  【解决方案13】:

                  这是我目前用于删除甚至更新的内容:

                  DELETE           w
                  FROM             WorkRecord2   w,
                                   Employee      e
                  WHERE            w.EmployeeRun = e.EmployeeNo
                               AND w.Company = '1' 
                               AND w.Date = '2013-05-06'
                  

                  【讨论】:

                    【解决方案14】:

                    这是一次从两个表中删除记录的简单查询。

                    DELETE table1.* ,
                           table2.* 
                    FROM table1 
                    INNER JOIN table2 ON table1.id= table2.id where table1.id ='given_id'
                    

                    【讨论】:

                    • 这个问题是针对 SQL Server 的。您不能在 SQL Server 的一个语句中从两个表中删除。我的理解是这可以在mysql和MS Access中完成。
                    【解决方案15】:

                    你甚至可以做一个子查询。如下代码:

                    DELETE FROM users WHERE id IN(
                        SELECT user_id FROM Employee WHERE Company = '1' AND Date = '2013-05-06'
                    )
                    

                    【讨论】:

                      【解决方案16】:

                      使用事务块、表变量和JOIN删除多个表数据。

                      BEGIN TRANSACTION;
                      
                         declare @deletedIds table ( id int );
                         
                         DELETE w
                         output deleted.EmployeeRun into @deletedIds
                         FROM WorkRecord2 w
                         INNER JOIN Employee e
                                 ON e.EmployeeNo = w.EmployeeRun
                                AND w.Company = 1
                                AND w.date = '2013-05-06';
                      
                         DELETE e
                         FROM Employee as e
                         INNER JOIN @deletedIds as d
                                 ON d.id = e.EmployeeNo;
                      COMMIT TRANSACTION;
                      

                      请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=43330dda6f1b71b8ec4172a24d5b6921

                      用临时表和JOIN删除多个表数据。删除后删除临时表。

                      BEGIN TRANSACTION;
                      
                          -- create temporary table
                          create table #deletedRecords (employeeId int);
                          
                          -- INSERT INTO #deletedRecords
                          SELECT e.EmployeeNo
                          FROM WorkRecord2 w
                          INNER JOIN Employee e
                                 ON e.EmployeeNo = w.EmployeeRun
                                AND w.Company = 1
                                AND w.date = '2013-05-06';
                                
                          -- delete from WorkRecord2
                          DELETE w
                          FROM WorkRecord2 w
                          INNER JOIN #deletedRecords d
                                 ON w.EmployeeRun = d.employeeId;
                                 
                          -- delete from Employee using exists
                          DELETE 
                          FROM Employee
                          WHERE EXISTS (SELECT 1
                                        FROM #deletedRecords d
                                        WHERE d.employeeId = EmployeeNo);
                                        
                          -- drop temporary table
                          DROP TABLE #deletedRecords;
                      
                      COMMIT TRANSACTION;
                      

                      请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=d52c6c1ed91669d68fcc6bc91cb32d78

                      使用 SELECT INTO 创建临时表的另一种方法

                      BEGIN TRANSACTION;
                      
                          SELECT  e.EmployeeNo employeeId 
                          INTO #deletedRecords
                          FROM WorkRecord2 w
                          INNER JOIN Employee e
                                 ON e.EmployeeNo = w.EmployeeRun
                                AND w.Company = 1
                                AND w.date = '2013-05-06';
                                
                          -- delete from WorkRecord2
                          DELETE w
                          FROM WorkRecord2 w
                          INNER JOIN #deletedRecords d
                                 ON w.EmployeeRun = d.employeeId;
                                 
                          -- delete from Employee using exists
                          DELETE 
                          FROM Employee
                          WHERE EXISTS (SELECT 1
                                        FROM #deletedRecords d
                                        WHERE d.employeeId = EmployeeNo);
                                        
                          -- drop temporary table
                          DROP TABLE #deletedRecords;
                      
                      COMMIT TRANSACTION;
                      

                      请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=0f02f05616ce5b4dcc8fc67c6cf1e640

                      使用JOIN删除单个表数据

                      DELETE w
                      FROM WorkRecord2 w
                      INNER JOIN Employee e
                              ON e.EmployeeNo = w.EmployeeRun
                             AND w.Company = 1
                             AND w.date = '2013-05-06'
                      

                      请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=84a60d1368556a8837281df36579334a

                      使用 CTE 删除单表数据

                      WITH cte AS (
                           SELECT w.EmployeeRun
                           FROM WorkRecord2 w
                           WHERE EXISTS (SELECT 1
                                         FROM Employee 
                                         WHERE EmployeeNo = w.EmployeeRun)
                               AND w.Company = 1
                               AND w.date = '2013-05-06'
                      )
                      DELETE
                      FROM cte
                      

                      请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=6590007b3c8c2ffad5563bd86606c5b1

                      在子表中创建外键时使用ON CASCADE DELETE。如果删除父表数据,则对应的子表数据会被自动删除。

                      【讨论】:

                        猜你喜欢
                        • 2010-10-21
                        • 2020-03-20
                        • 2019-08-10
                        • 2018-05-25
                        • 1970-01-01
                        • 2013-01-07
                        • 1970-01-01
                        相关资源
                        最近更新 更多