Mysql 如何在一个查询中更新两个不同的表?

Mysql 如何在一个查询中更新两个不同的表?,mysql,sql,sql-update,Mysql,Sql,Sql Update,我有两张这样的桌子: // users +----+--------+----------------------------+------------------+ | id | name | email | notification_num | +----+--------+----------------------------+------------------+ | 1 | John | John134@gmail.com

我有两张这样的桌子:

// users
+----+--------+----------------------------+------------------+
| id |  name  |            email           | notification_num |
+----+--------+----------------------------+------------------+
| 1  | John   | John134@gmail.com          | 4                |
| 2  | Peter  | matrix_peter@ymail.com     | 2                |
| 3  | Jack   | jk_43m@gmail.com           | 6                |
+----+--------+----------------------------+------------------+

// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1  | 4325    | 2       | NULL |
| 2  | 8765    | 3       | NULL | 
| 3  | 5454    | 3       | 1    |
| 4  | 4346    | 2       | NULL |
| 5  | 3243    | 1       | 1    |
| 6  | 3246    | 2       | 1    |
| 7  | 3764    | 3       | 1    |
+----+---------+---------+------+
UPDATE users SET notification_num = 0 WHERE id = :user_id

UPDATE notifications SET seen = 1 WHERE seen is NULL and user_id = :user_id
好的,我只有一个用户id。例如
:user\u id=2
,然后我想要这个输出:

// users
+----+--------+----------------------------+------------------+
| id |  name  |            email           | notification_num |
+----+--------+----------------------------+------------------+
| 1  | John   | John134@gmail.com          | 4                |
| 2  | Peter  | matrix_peter@ymail.com     | 0                |
| 3  | Jack   | jk_43m@gmail.com           | 6                |
+----+--------+----------------------------+------------------+

// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1  | 4325    | 2       | 1    |
| 2  | 8765    | 3       | NULL | 
| 3  | 5454    | 3       | 1    |
| 4  | 4346    | 2       | 1    |
| 5  | 3243    | 1       | 1    |
| 6  | 3246    | 2       | 1    |
| 7  | 3764    | 3       | 1    |
+----+---------+---------+------+
如您所见,我想更新
用户.codition_num
并将其设置为
0
(对于这样的用户),我还想更新
通知.seed
,并将所有行设置为
1
(对于这样的用户)。我该怎么做


我可以通过以下两种不同的查询来实现:

// users
+----+--------+----------------------------+------------------+
| id |  name  |            email           | notification_num |
+----+--------+----------------------------+------------------+
| 1  | John   | John134@gmail.com          | 4                |
| 2  | Peter  | matrix_peter@ymail.com     | 2                |
| 3  | Jack   | jk_43m@gmail.com           | 6                |
+----+--------+----------------------------+------------------+

// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1  | 4325    | 2       | NULL |
| 2  | 8765    | 3       | NULL | 
| 3  | 5454    | 3       | 1    |
| 4  | 4346    | 2       | NULL |
| 5  | 3243    | 1       | 1    |
| 6  | 3246    | 2       | 1    |
| 7  | 3764    | 3       | 1    |
+----+---------+---------+------+
UPDATE users SET notification_num = 0 WHERE id = :user_id

UPDATE notifications SET seen = 1 WHERE seen is NULL and user_id = :user_id

但是我想知道如何通过一个查询实现这一点?

您可以使用多个表
更新

UPDATE users u LEFT JOIN notifications n ON n.user_id = u.id
SET    u.notification_num = 0,
       n.seen = 1
WHERE  u.id = 2

您可以使用多表更新:

UPDATE users u LEFT JOIN notifications n ON n.user_id = u.id
SET    u.notification_num = 0,
       n.seen = 1
WHERE  u.id = 2

您可以在一个查询中将两个表连接在一起以更新:

UPDATE users, notifications
SET users.notification_num = 0
  ,  notification.seen = 1
WHERE users.id = notifications.user_id AND
      users.id = 2 AND
      notifications.seen is NULL
阅读了解更多信息。另一种选择是在一个事务中简单地进行两次单独的更新:

START TRANSACTION;
UPDATE users SET notification_num = 0 WHERE id = 2;
UPDATE notifications SET seen = 1 WHERE user_id = 2 AND notifications.seen is NULL;
COMMIT;

您可以在一个查询中将两个表连接在一起以更新:

UPDATE users, notifications
SET users.notification_num = 0
  ,  notification.seen = 1
WHERE users.id = notifications.user_id AND
      users.id = 2 AND
      notifications.seen is NULL
阅读了解更多信息。另一种选择是在一个事务中简单地进行两次单独的更新:

START TRANSACTION;
UPDATE users SET notification_num = 0 WHERE id = 2;
UPDATE notifications SET seen = 1 WHERE user_id = 2 AND notifications.seen is NULL;
COMMIT;

请注意,我的模式与您的模式略有不同,但差别很小

 DROP TABLE IF EXISTS users;

CREATE TABLE users 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name  VARCHAR(12) NOT NULL
,email VARCHAR(20) NOT NULL
,notification_num INT NOT NULL
);

INSERT INTO users VALUES
(1,'John','John134@gmail.com',4),
(2,'Peter','matrix_peter@ymail.com',2),
(3,'Jack','jk_43m@gmail.com',6);

DROP TABLE IF EXISTS notifications;

CREATE TABLE notifications 
(post_id INT NOT NULL
,user_id INT NOT NULL
,seen TINYINT DEFAULT 0
,PRIMARY KEY(post_id,user_id)
);

INSERT INTO notifications VALUES
(4325,2,0),
(8765,3,0),
(5454,3,1),
(4346,2,0),
(3243,1,1),
(3246,2,1),
(3764,3,1);

 SELECT * FROM notifications;
 +---------+---------+------+
 | post_id | user_id | seen |
 +---------+---------+------+
 |    3243 |       1 |    1 |
 |    3246 |       2 |    1 |
 |    3764 |       3 |    1 |
 |    4325 |       2 |    0 |
 |    4346 |       2 |    0 |
 |    5454 |       3 |    1 |
 |    8765 |       3 |    0 |
 +---------+---------+------+

 SELECT * FROM users;
 +----+-------+----------------------+------------------+
 | id | name  | email                | notification_num |
 +----+-------+----------------------+------------------+
 |  1 | John  | John134@gmail.com    |                4 |
 |  2 | Peter | matrix_peter@ymail.c |                2 |
 |  3 | Jack  | jk_43m@gmail.com     |                6 |
 +----+-------+----------------------+------------------+


UPDATE users u 
  JOIN notifications n 
    ON n.user_id = u.id
   SET u.notification_num = 0, n.seen = 1
 WHERE u.id = 2;

 SELECT * FROM users;
  +----+-------+----------------------+------------------+
  | id | name  | email                | notification_num |
  +----+-------+----------------------+------------------+
  |  1 | John  | John134@gmail.com    |                4 |
  |  2 | Peter | matrix_peter@ymail.c |                0 |
  |  3 | Jack  | jk_43m@gmail.com     |                6 |
  +----+-------+----------------------+------------------+

  SELECT * FROM notifications;
  +---------+---------+------+
  | post_id | user_id | seen |
  +---------+---------+------+
  |    3243 |       1 |    1 |
  |    3246 |       2 |    1 |
  |    3764 |       3 |    1 |
  |    4325 |       2 |    1 |
  |    4346 |       2 |    1 |
  |    5454 |       3 |    1 |
  |    8765 |       3 |    0 |
  +---------+---------+------+

请注意,我的模式与您的模式略有不同,但差别很小

 DROP TABLE IF EXISTS users;

CREATE TABLE users 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name  VARCHAR(12) NOT NULL
,email VARCHAR(20) NOT NULL
,notification_num INT NOT NULL
);

INSERT INTO users VALUES
(1,'John','John134@gmail.com',4),
(2,'Peter','matrix_peter@ymail.com',2),
(3,'Jack','jk_43m@gmail.com',6);

DROP TABLE IF EXISTS notifications;

CREATE TABLE notifications 
(post_id INT NOT NULL
,user_id INT NOT NULL
,seen TINYINT DEFAULT 0
,PRIMARY KEY(post_id,user_id)
);

INSERT INTO notifications VALUES
(4325,2,0),
(8765,3,0),
(5454,3,1),
(4346,2,0),
(3243,1,1),
(3246,2,1),
(3764,3,1);

 SELECT * FROM notifications;
 +---------+---------+------+
 | post_id | user_id | seen |
 +---------+---------+------+
 |    3243 |       1 |    1 |
 |    3246 |       2 |    1 |
 |    3764 |       3 |    1 |
 |    4325 |       2 |    0 |
 |    4346 |       2 |    0 |
 |    5454 |       3 |    1 |
 |    8765 |       3 |    0 |
 +---------+---------+------+

 SELECT * FROM users;
 +----+-------+----------------------+------------------+
 | id | name  | email                | notification_num |
 +----+-------+----------------------+------------------+
 |  1 | John  | John134@gmail.com    |                4 |
 |  2 | Peter | matrix_peter@ymail.c |                2 |
 |  3 | Jack  | jk_43m@gmail.com     |                6 |
 +----+-------+----------------------+------------------+


UPDATE users u 
  JOIN notifications n 
    ON n.user_id = u.id
   SET u.notification_num = 0, n.seen = 1
 WHERE u.id = 2;

 SELECT * FROM users;
  +----+-------+----------------------+------------------+
  | id | name  | email                | notification_num |
  +----+-------+----------------------+------------------+
  |  1 | John  | John134@gmail.com    |                4 |
  |  2 | Peter | matrix_peter@ymail.c |                0 |
  |  3 | Jack  | jk_43m@gmail.com     |                6 |
  +----+-------+----------------------+------------------+

  SELECT * FROM notifications;
  +---------+---------+------+
  | post_id | user_id | seen |
  +---------+---------+------+
  |    3243 |       1 |    1 |
  |    3246 |       2 |    1 |
  |    3764 |       3 |    1 |
  |    4325 |       2 |    1 |
  |    4346 |       2 |    1 |
  |    5454 |       3 |    1 |
  |    8765 |       3 |    0 |
  +---------+---------+------+


继续。试试看,继续。试试看。有一件事,为什么
左连接
?@MartinAJ:如果该用户的
通知
表中没有记录,内部连接将无法更新
用户
表,而此外部连接仍会更新。啊,你说的“外部连接”是什么意思?
outer-join
left-join
是否相同?@MartinAJ:left-join是三种类型的外部连接之一(RIGHT-join和FULL-join是另外两种,尽管MySQL不支持后者);在每种情况下,关键字OUTER都可以选择性地插入到单词JOIN之前,例如LEFT-OUTER-JOIN等。请参阅Jeff Attwood的优秀文章,以获得对差异的良好解释。@MartinAJ:在这种情况下,不,您也可以使用INNER-JOIN。不过,拥有一个外部联接并没有什么害处。有一件事,为什么
左联接
?@MartinAJ:如果该用户的
通知
表中没有记录,内部联接将无法更新
用户
表,而这个外部联接仍然会这样做。啊,“外部联接”是什么意思?
outer-join
left-join
是否相同?@MartinAJ:left-join是三种类型的外部连接之一(RIGHT-join和FULL-join是另外两种,尽管MySQL不支持后者);在每种情况下,关键字OUTER都可以选择性地插入到单词JOIN之前,例如LEFT-OUTER-JOIN等。请参阅Jeff Attwood的优秀文章,以获得对差异的良好解释。@MartinAJ:在这种情况下,不,您也可以使用INNER-JOIN。不过,使用外部联接并没有什么害处。IS NULL位似乎是多余的。@well绝对不是<代码>。。。并且seen为空避免重新更新已经
seen=1
的行。@MartinAJ根据您的评论进行了更新,谢谢您的澄清。@MartinAJ这没有什么区别。MySQL不会更新不需要的行to@Strawberry有趣的是,我不知道。IS NULL位似乎是多余的。@草莓好吧,绝对不是<代码>。。。并且seen为空避免重新更新已经
seen=1
的行。@MartinAJ根据您的评论进行了更新,谢谢您的澄清。@MartinAJ这没有什么区别。MySQL不会更新不需要的行to@Strawberry有趣的是,我不知道。我看不出你的模式和我的模式有什么不同。。无论如何,谢谢你。向上投票。只有一个,为什么不
左连接
?通知上没有代理键,看到的
上没有空值。为什么离开加入?对我来说,这似乎是一个非常奇怪的想法!有一件事,为什么要使用
0
而不是
NULL
?在这里,NULL的意思是“我不知道消息是否被看到”。我看不出这有什么用。当然,最好说“我假设一条消息没有被看到,除非我知道它已经被看到”。0更好地反映了该逻辑。我看不出您的架构和我的架构之间有任何差异。。无论如何,谢谢你。向上投票。只有一个,为什么不
左连接
?通知上没有代理键,看到的
上没有空值。为什么离开加入?对我来说,这似乎是一个非常奇怪的想法!有一件事,为什么要使用
0
而不是
NULL
?在这里,NULL的意思是“我不知道消息是否被看到”。我看不出这有什么用。当然,最好说“我假设一条消息没有被看到,除非我知道它已经被看到”。0更好地反映了这一逻辑。