MySQL 仅在条件为真时更新主字段
Posted
技术标签:
【中文标题】MySQL 仅在条件为真时更新主字段【英文标题】:MySQL update a master field only if condition is true 【发布时间】:2021-11-15 23:02:54 【问题描述】:有没有办法以这种方式更新SQL,例如。
主表有一个名为 INVOICESCOUNT 的列。
成功删除发票后,INVOICESCOUNT 会减少。
例如,这样的 SQL 伪代码语句:
Delete From Invoices where INVOICE=500;
Update Customers SET INVOICECOUNT=INVOICECOUNT-1 WHERE Customer=1 (if prior statement returns 1 affected row);
我需要将它嵌入到同一个 SQL 语句中,而不是让源代码处理分别执行 2 个语句。
感谢您的任何建议。如果有这样的解决方案,也请告诉我是否有最低 mysql 版本要求。
更新更多信息:请注意,我向用户展示的客户列表每次都可能非常不同,例如 CustomerGroupID=?或 CustomerCreated 在特定日期内,因此无法有效缓存客户查询,因此我更喜欢更新 INVOICECOUNT(因为列出不同客户组的不同用户会在一小时内多次点击它)。
【问题讨论】:
您不需要表格来记录您的计数。 SQL可以帮你算 您不应该将 派生数据 存储在 RDBMS 的表中,包括“另一个表中满足某些条件的行数”之类的聚合 - 而是使用VIEW
.有许多 原因不存储这样的派生数据,即因为它过时 并且变得不正确。数据库的设计应使它们永远不会包含可能过时的内部派生数据。
【参考方案1】:
更好的主意:改为使用 VIEW
来显示客户的发票数量:
CREATE VIEW CustomersInfo AS
SELECT
CustomerId,
COUNT(*) AS InvoiceCount
FROM
Invoices
GROUP BY
CustomerId
;
然后你会像这样使用它:
SELECT
c.CustomerId,
COALESCE( ci.InvoiceCount, 0 ) AS InvoiceCount
FROM
Customers AS c
LEFT OUTER JOIN CustomersInfo AS ci ON c.CustomerId = ci.CustomerId
(不要使用INNER JOIN
,否则没有任何发票的客户将不会在输出中)。
【讨论】:
感谢您提供的替代方法。此示例对于其他一些基于客户端的 sql 代码可能很有用。也许我给出的例子不是最好的,因为我们的场景更复杂。但由于性能原因的一些内部原因,每次出现这样的“查询发票计数”时,我都无法计算发票。有没有办法像我原来的问题一样执行条件 SQL 语句? @PeterJones 性能不是借口:MySQL supports cached materialized views。如果您的原始问题不能代表您的实际问题,那么您应该编辑您的问题帖子以描述您的实际问题。 请参阅“更新更多信息”,我每次都需要列出非常不同的客户组,因此缓存可能无法正常工作。我很抱歉没有提到这一点。您的 View 示例是一个好主意,我可以在其他场景中使用它。感谢您的样品。非常感激。我赞成你的回答。【参考方案2】:您可以为此使用触发器
CREATE TABLE Invoices(INVOICE INT)
CREATE TABLe Customers(Customer int,INVOICECOUNT int)
INSERT INTO Customers VALUES (1,1)
CREATE TRIGGER del_after AFTER DELETE ON Invoices FOR EACH ROW Update Customers SET INVOICECOUNT=INVOICECOUNT-1 WHERE Customer=1
Delete From Invoices where INVOICE=500;
客户 |发票计数 --------: | ------------: 1 | 1SELECT * FROM Customers
INSERT INTO Invoices VALUES (400)
Delete From Invoices where INVOICE=500;
客户 |发票计数 --------: | ------------: 1 | 1SELECT * FROM Customers
INSERT INTO Invoices VALUES (500)
Delete From Invoices where INVOICE=500;
客户 |发票计数 --------: | ------------: 1 | 0SELECT * FROM Customers
db小提琴here
【讨论】:
感谢您的指点。我赞成这个答案。看起来 MySQL 有很多选择。【参考方案3】:正如 cmets 中提到的,您可能不需要将发票计数存储在表格列中,但是如果您出于任何原因必须拥有发票计数列,则最好的选择可能是存储过程。
DELIMITER //
CREATE PROCEDURE removeinvoice
BEGIN
DELETE FROM invoices WHERE invoice=500;
UPDATE customers SET invoicecount = (SELECT COUNT(*) FROM invoices);
END//
DELIMITER ;
然后你只需调用那个存储过程。
CALL removeinvoice;
【讨论】:
以上是关于MySQL 仅在条件为真时更新主字段的主要内容,如果未能解决你的问题,请参考以下文章
Javascript:<script src=jquery...仅当条件为真时
如何执行?当某些条件为真时,带有 OR 的 jquery.on 事件?