MySQL INSERT IF(自定义if语句)

首先,下面是问题的简要总结:

是否有可能有条件地运行INSERT语句? 类似这样的东西:

 IF(expression) INSERT... 

现在,我知道我可以用存储过程来做到这一点。 我的问题是:我可以在我的查询中做到这一点?


现在,我为什么要这样做呢?

假设我们有以下两个表格:

 products: id, qty_on_hand orders: id, product_id, qty 

现在,让我们来说20个巫毒娃娃(产品编号2)的订单进来。
我们首先检查手头是否有足够的数量:

 SELECT IF( ( SELECT SUM(qty) FROM orders WHERE product_id = 2 ) + 20 <= ( SELECT qty_on_hand FROM products WHERE id = 2) , 'true', 'false'); 

然后,如果它评估为真,我们运行一个INSERT查询。
到现在为止还挺好。


但是,并发性有问题。
如果两个订单在同一时间进入,他们可能都会在其中任何一个订单进入之前阅读手头数量。 然后他们会下订单,从而超过qty_on_hand


所以,回到问题的根源:
是否可以有条件地运行INSERT语句,以便我们可以将这两个查询合并为一个?

我search了很多,我能find的唯一一种条件INSERT语句是ON DUPLICATE KEY ,这在这里显然不适用。

 INSERT INTO TABLE SELECT value_for_column1, value_for_column2, ... FROM wherever WHERE your_special_condition 

如果select没有返回行(因为你的特殊条件是false),不会发生插入操作。

从问题中使用你的模式(假设你的id列是auto_increment ):

 insert into orders (product_id, qty) select 2, 20 where (SELECT qty_on_hand FROM products WHERE id = 2) > 20; 

如果没有足够的库存,这将不插入行,否则将创build订单行。

好想法btw!

尝试:

 INSERT INTO orders(product_id, qty) SELECT 2, 20 FROM products WHERE id = 2 AND qty_on_hand >= 20 

如果存在id等于2产品,且此产品的qty_on_hand大于或等于20 ,则插入操作将以product_id = 2qty = 20的值发生。 否则,不会发生插入。

注意 :如果您的产品ID是唯一的注释,您可能需要在SELECT语句的末尾添加一个LIMIT子句。

你可能错误地解决了这个问题。

如果担心两个读操作会同时发生,那么就会使用陈旧的数据,解决scheme是使用锁或事务

有查询这样做:

  • 锁表读取
  • 读表
  • 更新表
  • 释放locking

不确定并发性,你需要阅读关于在MySQL中locking,但是这将让你确保只有20个项目,如果20个项目可用:

 update products set qty_on_hand = qty_on_hand - 20 where qty_on_hand >= 20 and id=2 

然后您可以检查有多less行受到影响。 如果没有影响,你没有足够的股票。 如果1行受到影响,您已经有效地消耗了股票。