高效更新SQL,使用一条SQL语句更新多行,避免循环
我试图避免在我正在处理的项目中的循环中访问数据库。对SQL不太好,我不确定解决这个问题的最好方法。高效更新SQL,使用一条SQL语句更新多行,避免循环
我正在更新具有多个库存位置/拣配位置的销售过程中的库存水平数据库。
因此,这就是我正在做的。
通过产品ID循环,然后通过每个产品的选秀位置循环和更新数量,因为它去,如:
当然这个工作,但它是开放的每一个股票的新的数据库连接位置,为每个项目。
那么我如何将这个工作变成一个更新声明?
这种联系让我非常接近我所后,我想,但我不是100%确定如何动态地构建SQL语句,以及如何将两个条件添加到CASE。
我需要建立一个SQL语句是这样的:
UPDATE stockLevels
SET stockLevel= CASE id
WHEN '"& wProductId &"' AND stockLocation='"& thisLocation &"' THEN `stockLevel` - '" & thisQty & "'
WHEN '"& NEXTwProductId &"' AND stockLocation='"& NEXTthisLocation &"' THEN `stockLevel` - '" & NEXTthisQty & "'
END
但是,这不是正确的地方我加入的第二个参数的CASE!
我像往常一样使用MySQL和VB.NET,非常感谢。
您的CASE表达式在语法上根本不正确。
CASE
表达式有两种,几乎相同,但语法略有不同。
一个人的
CASE expr
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE result_else
END
形式向对方这个样子的:
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE result_else
END
你基本上试图将这两种混合的CASE
。
你可能只需要使用第二个(也称为搜索CASE,如果我没有弄错):
...
CASE
WHEN id = '"& wProductId &"' AND stockLocation='"& thisLocation &"' THEN ...
WHEN id = '"& NEXTwProductId &"' AND stockLocation='"& NEXTthisLocation &"' THEN ...
...
需要注意的是,如果没有匹配和CASE
没有ELSE
部分,其结果将是NULL
,所以一定要确保你已经覆盖了所有的情况下,否则使用ELSE
部分是这样的:
ELSE `stocklevel`
即CASE
将评估为正在更新的列的原始值,最终不会对其进行更新。
在您的示例中,在set子句中使用case语句并不理想,原因很多。
- 没有where子句,以帮助数据库执行查询有效
- 查询的大量更新的的尺寸过大(考虑更新1000行这样)
- 要手动实施加入 - 数据库几乎可以肯定比你更有效地做到这一点。
- 调试这样的查询也很困难。
相反,你应该先衡量一个更新的性能在时间的方法,看看你是否真的需要做出改进。
如果需要提高性能,那么我会建议一种方法,首先将更新插入到临时表中。一种合适的表将具有以下列:
wProductID, stockLocation, newStockLevel
这些更新可以批量使用以下的MySQL语法插入:
INSERT INTO temp_stock_updates
(wProductID, stockLocation, newStockLevel)
VALUES
(?,?,?), (?,?,?), (?,?,?), ...
然后单个更新运行来更新主表。此查询看起来是这样的:
UPDATE stockLevels s
JOIN temp_stock_updates u USING (wProductID, stockLocation)
SET
s.stockLevel = u.newStockLevel
好的,谢谢你的建议。在这种情况下,我不能100%确定每次采用哪种方法都很糟糕,但我之前也遇到类似情况的问题。在这个应用程序中,我们不太可能一次处理超过10-20行,最多3/4个位置,因此可能会有80个循环......您可以扩展您建议的临时表方法吗?我不确定那里发生了什么事情? – 2012-01-09 11:09:48
@JamieHartnoll,我已经为临时表方法添加了一些额外的查询。 – 2012-01-09 11:26:49
a'r我认为你可能在这里得到了最好的解决方案,但是我接受的解决方案直接回答了问题,并且我能够立即实施。但是,您的解决方案长期看起来会更好。我从来没有使用过临时表,也不知道如何去做一个临时表,所以我坚持我现在知道的!不管怎么说,还是要谢谢你! – 2012-01-09 18:12:32
哦,我明白了,所以它实际上只是一个没有在'case开头指定列名的情况'声明。然后我可以用两个参数运行'case'?这很简单!我知道我的语法错了,但不知道如何使它正确!谢谢!虽然SQL语句可能会变得很长,但是来自a'r的回答中的评论是有效的。就我而言,我们可能不会处理超过20个产品线,在大多数情况下,可能不会超过10个,您认为使用这种'case'声明是否是应对这种情况的最佳方式? – 2012-01-09 12:03:26
如果不超过20行,CASE解决方案对我来说似乎可行。尽管如此,我还是喜欢@ a'r的想法。您似乎并不十分确定您将来是否会处理更多的产品线,因此,至少,您可能需要考虑'a'r'的建议(或考虑在此实施点)。 – 2012-01-09 12:13:41
谢谢。我会接受这个答案,因为这是我最初想要的,但我认为@ a'r有更好的长期解决方案。虽然我从来没有使用过临时表,所以我现在要回避这个问题! – 2012-01-09 18:11:15