【问题标题】:Delete from two tables in one query在一个查询中从两个表中删除
【发布时间】:2010-11-17 00:50:08
【问题描述】:

我在 MySQL 中有两个表

#messages table  : 
messageid
messagetitle 
.
.

#usersmessages table 
usersmessageid 
messageid
userid
.
.

现在,如果我想从消息表中删除,没关系。但是当我通过 messageid 删除消息时,该记录仍然存在于 usersmessage 中,我必须立即从这两个表中删除。

我使用了以下查询:

DELETE FROM messages LEFT JOIN usersmessages USING(messageid) WHERE messageid='1' ; 

然后我测试

   DELETE FROM messages , usersmessages 
   WHERE messages.messageid = usersmessages.messageid 
   and messageid='1' ; 

但是这两个查询并没有完成这个任务。

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    你不能用分号分隔它们吗?

    Delete from messages where messageid = '1';
    Delete from usersmessages where messageid = '1'
    

    只需使用INNER JOIN,如下所示

    DELETE messages , usersmessages  FROM messages  INNER JOIN usersmessages  
    WHERE messages.messageid= usersmessages.messageid and messages.messageid = '1'
    

    【讨论】:

    • 如果我想把这段代码放在一个循环中会发生什么?我知道我绝对可以输入分号。
    • 它可以放在一个循环中。您可以通过编程方式执行此操作并将消息 ID 作为参数发送。只要您不继续发送相同的 id,它就不会一遍又一遍地删除。
    • 如果你在两个查询中这样做,你真的应该把它包装在一个事务中。至于在循环中运行删除查询,您最好制定一个查询来执行所有删除。
    • 查看另一个带有连接的删除查询示例bennadel.com/blog/…
    • 不适用于 SQL Server:',' 附近的语法不正确。
    【解决方案2】:
    DELETE a.*, b.* 
    FROM messages a 
    LEFT JOIN usersmessages b 
    ON b.messageid = a.messageid 
    WHERE a.messageid = 1
    

    翻译:从表 messages 中删除 messageid =1,如果表 uersmessages 具有表 messages 的 messageid = messageid,则删除该行uersmessages 表。

    【讨论】:

    • 对所有人的评论:如本例所示,指定删除应该在哪个表中工作很重要。很棒的帖子@angry_kiwi
    • 我只需要更改顺序,FROM usersmessages b LEFT JOIN messages a
    【解决方案3】:

    您应该使用ON DELETE CASCADE 创建一个FOREIGN KEY

    ALTER TABLE usersmessages
    ADD CONSTRAINT fk_usermessages_messageid
    FOREIGN KEY (messageid)
    REFERENCES messages (messageid)
    ON DELETE CASCADE
    

    ,或者在一个事务中使用两个查询:

    START TRANSACTION;;
    
    DELETE
    FROM    usermessages
    WHERE   messageid = 1
    
    DELETE
    FROM    messages
    WHERE   messageid = 1;
    
    COMMIT;
    

    不过,事务仅影响 InnoDB 表。

    【讨论】:

    • 可以在一个查询中从多个表中删除! dev.mysql.com/doc/refman/5.0/en/delete.html
    • 是的,你可以!但对我来说……按照我的回答更容易。
    • 我在我的一张类似的桌子上添加了级联。当我尝试仅从 1 个表中删除时,它删除了记录并使相关的记录成为孤立的。约束有什么好处?
    • @barfoon: 你的桌子是InnoDB吗?
    • @Quassnoi 哎呀!我绝对认为它是,多么愚蠢。所有表都是 MyISAM。我可以使用其中的数据即时更改所有这些吗?还是有问题?
    【解决方案4】:

    你有两个选择:

    首先,在事务中执行两条语句:

    BEGIN;
      DELETE FROM messages WHERE messageid = 1;
      DELETE FROM usermessages WHERE messageid = 1;
    COMMIT;
    

    或者,您可以使用外键设置 ON DELETE CASCADE。这是更好的方法。

    CREATE TABLE parent (
      id INT NOT NULL,
        PRIMARY KEY (id)
    );
    
    CREATE TABLE child (
      id INT, parent_id INT,
      FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
    );
    

    您可以阅读更多关于 ON DELETE CASCADE here

    【讨论】:

      【解决方案5】:

      不需要加入:

      DELETE m, um FROM messages m, usersmessages um
      
      WHERE m.messageid = 1 
      
      AND m.messageid = um.messageid 
      

      【讨论】:

      • 但这仍然是一个隐含的CROSS JOIN
      【解决方案6】:
      DELETE message.*, usersmessage.* from users, usersmessage WHERE message.messageid=usersmessage.messageid AND message.messageid='1'
      

      【讨论】:

        【解决方案7】:

        OP 只是在删除后缺少表别名

        DELETE t1, t2 
        FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id 
        WHERE t1.id = some_id
        

        【讨论】:

        • 感谢您的回答。如果您尝试解释为什么这会起作用以及为什么 OPs 解决方案不起作用,将会更有帮助。
        • 为什么需要别名?
        【解决方案8】:

        请试试这个

        DELETE FROM messages,usersmessages
        
        USING messages
        
        INNER JOIN usermessages on (messages.messageid = usersmessages.messageid)
        
        WHERE messages.messsageid='1'
        

        【讨论】:

          【解决方案9】:

          试试这个..

          DELETE a.*, b.*  
          FROM table1 as a, table2 as b  
          WHERE a.id=[Your value here] and b.id=[Your value here]
          

          我让id作为示例列。

          很高兴这有帮助。 :)

          【讨论】:

          • 为了正确呈现星号 (*),您需要在查询前缩进 4 个空格。
          【解决方案10】:

          你也可以这样使用,当两个列有 2 个或多个相同的列名时删除特定的值。

          DELETE project , create_test  FROM project INNER JOIN create_test
          WHERE project.project_name='Trail' and  create_test.project_name ='Trail' and project.uid= create_test.uid = '1';
          

          【讨论】:

            【解决方案11】:

            这里没有提到另一种方法(我还没有完全测试它的性能),您可以为所有表设置数组 -> 要删除的行如下

            // set your tables array
            $array = ['table1', 'table2', 'table3'];
            
            
            // loop through each table
            for($i = 0; $i < count($array); $i++){
            
             // get each single array
             $single_array = $array[$i];
            
             // build your query
             $query = "DELETE FROM $single_array WHERE id = 'id'";
            
             // prepare the query and get the connection
             $data = con::GetCon()->prepare($query);
            
             // execute the action
             $data->execute();
            }
            

            然后您可以将用户重定向到主页。

            header('LOCATION:' . $home_page);
            

            希望这会对某人有所帮助:)

            谢谢

            【讨论】:

            • 这可能会对某人有所帮助...虽然看起来像 PHP,但我认为这不一定在问题的范围内 :)
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-09
            • 1970-01-01
            • 1970-01-01
            • 2023-03-05
            • 2016-04-07
            相关资源
            最近更新 更多