【发布时间】:2019-08-21 13:17:35
【问题描述】:
我有一个更新三个表的函数,但我使用三个查询来执行此操作。我希望使用更方便的方法进行良好实践。
如何在 MySQL 中使用单个查询更新多个表?
【问题讨论】:
-
你能提供一个生成代码的例子吗?表之间是否有公用键?
标签: mysql sql sql-update
我有一个更新三个表的函数,但我使用三个查询来执行此操作。我希望使用更方便的方法进行良好实践。
如何在 MySQL 中使用单个查询更新多个表?
【问题讨论】:
标签: mysql sql sql-update
假设我有Table1 主键_id 和一个布尔列doc_availability; Table2 带有外键 _id 和 DateTime 列 last_update 并且我想将 Table1 中带有 _id 14 的文档的可用性更改为 0 即不可用并使用文档时的时间戳更新 Table2最近更新时间。以下查询将完成任务:
UPDATE Table1, Table2
SET doc_availability = 0, last_update = NOW()
WHERE Table1._id = Table2._id AND Table1._id = 14
【讨论】:
以Books 和Orders 这两个表为例。如果我们在Orders 表中以特定顺序增加具有Order.ID = 1002 的书籍数量,那么我们还需要在Books 表中将我们库存中可用的书籍总数减少相同的数量。
UPDATE Books, Orders
SET Orders.Quantity = Orders.Quantity + 2,
Books.InStock = Books.InStock - 2
WHERE
Books.BookID = Orders.BookID
AND Orders.OrderID = 1002;
【讨论】:
UPDATE t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
SET t1.a = 'something',
t2.b = 42,
t3.c = t2.c
WHERE t1.a = 'blah';
要查看这将更新什么,您可以将其转换为 select 语句,例如:
SELECT t2.t1_id, t2.t3_id, t1.a, t2.b, t2.c AS t2_c, t3.c AS t3_c
FROM t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
WHERE t1.a = 'blah';
使用与其他答案相同的表的示例:
SELECT Books.BookID, Orders.OrderID,
Orders.Quantity AS CurrentQuantity,
Orders.Quantity + 2 AS NewQuantity,
Books.InStock AS CurrentStock,
Books.InStock - 2 AS NewStock
FROM Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
WHERE Orders.OrderID = 1002;
UPDATE Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
SET Orders.Quantity = Orders.Quantity + 2,
Books.InStock = Books.InStock - 2
WHERE Orders.OrderID = 1002;
编辑:
只是为了好玩,让我们添加一些更有趣的东西。
假设您有一个books 的表和一个authors 的表。你的books 有一个author_id。但是最初创建数据库时,没有设置外键约束,后来前端代码中的一个错误导致一些书籍添加了无效的author_ids。作为 DBA,您不想通过所有这些 books 来检查 author_id 应该是什么,因此决定数据捕获器将修复 books 指向正确的 @ 987654333@。但是每一本书都有太多的书要读,假设你知道那些有 author_id 对应于实际 author 的书是正确的。只有那些不存在的author_ids 是无效的。已经有一个供用户更新书籍详细信息的界面,开发人员不想仅仅为了这个问题而改变它。但是现有的接口做了一个INNER JOIN authors,所以所有作者无效的书都被排除了。
您可以这样做:插入一个虚假的作者记录,例如“未知作者”。然后更新所有不良记录的author_id 以指向未知作者。然后数据捕获者可以搜索所有作者设置为“未知作者”的书籍,查找正确的作者并修复它们。
如何更新所有不良记录以指向未知作者?像这样(假设未知作者的author_id是99999):
UPDATE books
LEFT OUTER JOIN authors ON books.author_id = authors.id
SET books.author_id = 99999
WHERE authors.id IS NULL;
以上内容还将更新books 具有NULL author_id 的未知作者。如果不想这样,当然可以加AND books.author_id IS NOT NULL。
【讨论】:
INNER JOIN (= 不会在连接表中有对应项)不会更新,即使没有 where 子句?所以我可以 ``` UPDATE table1 INNER JOIN table2 ON table1.id = table2.table1_id SET ... ``` 而不是 ``` UPDATE table1 SET ... WHERE EXISTS( SELECT 1 FROM table2 WHERE table1_id = table. id) ```
您也可以使用一个查询来执行此操作,如下所示:
UPDATE table1,table2 SET table1.col=a,table2.col2=b
WHERE items.id=month.id;
当然,然后只发送这个查询。您可以在此处阅读有关联接的更多信息:http://dev.mysql.com/doc/refman/5.0/en/join.html。还有一些关于订购和限制多个表更新的限制,您可以在此处阅读:http://dev.mysql.com/doc/refman/5.0/en/update.html(只需 ctrl+f "join")。
【讨论】:
JOIN,你只需在FROM 中列出多个表,并使用WHERE 加入它们。有时,“等连接”一词用于指代这个习语。
当您说多个查询时,您的意思是多个 SQL 语句,如下所示:
UPDATE table1 SET a=b WHERE c;
UPDATE table2 SET a=b WHERE d;
UPDATE table3 SET a=b WHERE e;
或多个查询函数调用如下:
mySqlQuery(UPDATE table1 SET a=b WHERE c;)
mySqlQuery(UPDATE table2 SET a=b WHERE d;)
mySqlQuery(UPDATE table3 SET a=b WHERE e;)
如果您想实现前者,则可以使用单个 mySqlQuery 调用来完成,只需按以下方式调用 mySqlQuery 函数:
mySqlQuery(UPDATE table1 SET a=b WHERE c; UPDATE table2 SET a=b WHERE d; UPDATE table3 SET a=b WHERE e;)
这将通过一次 mySqlQuery() 调用执行所有三个查询。
【讨论】:
这通常是存储过程的用途:按顺序执行多个 SQL 语句。使用回滚,您可以确保将它们视为一个工作单元,即它们要么全部执行,要么都不执行,以保持数据一致。
【讨论】: