SQL 如何在一个命令中为 int 列增加或减少一个

我有一个 Orders 表,它有一个 Quantity 列。在签入或签出期间,我们需要将 Quantity 列更新一个。有没有一种方法可以在一个动作中做到这一点,或者我们必须得到现有的值,然后在它上面加或减一?

另一个问题是,当我们插入一个新行时,我们是否需要检查是否存在相同的数据,然后插入(如果没有) ,这是两个步骤,还是有更好的方法来做到这一点?

谢谢,

338094 次浏览

回答第一个问题:

UPDATE Orders SET Quantity = Quantity + 1 WHERE ...

回答第二个问题:

有几种方法可以做到这一点。因为您没有指定一个数据库,我将假设 MySQL。

  1. INSERT INTO table SET x=1, y=2 ON DUPLICATE KEY UPDATE x=x+1, y=y+2
  2. REPLACE INTO table SET x=1, y=2

他们都能回答你的问题。但是,第一种语法允许更灵活地更新记录,而不是像第二种语法那样只是替换记录。

请记住,为了两者都存在,必须定义一个 UNIQUE 键..。

UPDATE Orders Order
SET Order.Quantity =  Order.Quantity - 1
WHERE SomeCondition(Order)

据我所知,SQL 中没有对 INSERT-OR-UPDATE 的内置支持。我建议创建一个存储过程或使用条件查询来实现这一点。您可以找到不同数据库的解决方案集合。

回答第二个问题:

使列唯一,并在异常设置为相同值时捕获异常。

如果我的理解是正确的,更新应该非常简单。

UPDATE TABLE SET QUANTITY = QUANTITY + 1 and
UPDATE TABLE SET QUANTITY = QUANTITY - 1 where QUANTITY > 0

您可能需要额外的筛选器来更新一行而不是所有行。

对于插入,您可以在本地缓存一些与记录相关的惟一 id,然后检查这个缓存并决定是否插入。另一种方法是始终插入和检查 PK 违规错误,并忽略它,因为这是一个冗余的插入。

@ dotjoe 更新并检查@@ rowcount,然后执行事后插入操作会更便宜。

例外是昂贵的 & & 更新更频繁

建议: 如果您想在 DAL 中获得优异的性能,那么如果空插入,那么让前端为要更新的行传递一个惟一的 ID。

DAL 应该是 CRUD,不需要担心是无状态的。

如果您使它成为无状态的,使用好的索引,您不会看到下面的 SQL vs 1语句有什么不同。 IF (选择 top 1 * form x where PK =@ID) 插入 别的 更新

第一个问题的单步回答是:

update TBL set CLM = CLM + 1 where key = 'KEY'

这是一种非常单指令的方法。

至于第二个问题,您不应该求助于特定于 DBMS 的 SQL 体操(如 UPSERT)来获得您想要的结果。有一种不需要特定 DBMS 的标准方法来执行更新或插入操作。

try:
insert into TBL (key,val) values ('xyz',0)
catch:
do nothing
update TBL set val = val + 1 where key = 'xyz'

也就是说,你先尝试创造。如果它已经存在,忽略错误。否则创建的值为0。

然后进行更新,无论是否正常工作:

  • 最初存在的行。
  • 有人在你的插入和更新之间更新了它。

这不是一个单一的指令,但是,令人惊讶的是,这是我们如何成功地做了很长一段时间。