【问题标题】:How to UPDATE just one record in DB2?如何只更新 DB2 中的一条记录?
【发布时间】:2012-01-04 23:09:29
【问题描述】:

DB2 中,我需要执行 SELECT FROM UPDATE,将更新 + 选择放入单个事务中。
但我需要确保每笔交易只更新一条记录

熟悉MySQL's UPDATE选项中的LIMIT子句

限制可更新的行数

我在DB2's UPDATE reference 中寻找类似的东西,但没有成功。

如何在 DB2 中实现类似的功能?


编辑: 在我的场景中,我必须根据要求提供 1000 个优惠券代码。我只需要选择(任何)尚未给出的。

【问题讨论】:

  • 为什么不添加一个包含要更新的行的主键的WHERE 条件?
  • 我也会怀疑更新(本质上是什么)随机,单个行,并获取它
  • 在我的场景中,我必须按要求提供1k优惠券代码,所以我只需要选择一个尚未提供的。
  • 您可以即时生成它吗?定义一个将其插入表中并将其返回给查询的存储过程?否则,我使用的 DB2 版本(iSeries V6R1)不支持 UPDATE 用于数据更改引用的语句(仅 INSERT),这可以很容易地只获得一行......或者,什么关于让更新选择MAX()MIN() 无人认领的优惠券(可能存在并发问题)?

标签: mysql database transactions db2


【解决方案1】:

该问题使用了一些模棱两可的术语,使我们不清楚需要完成什么。幸运的是,DB2 为各种 SQL 模式提供了强大的支持。

限制UPDATE修改的行数:

UPDATE 
( SELECT t.column1 FROM someschema.sometable t WHERE ... FETCH FIRST ROW ONLY
) 
SET column1 = 'newvalue';

UPDATE 语句永远不会看到基表,只会看到过滤它的表达式,因此您可以控制更新哪些行。


INSERT 有限数量的新行:
INSERT INTO mktg.offeredcoupons( cust_id, coupon_id, offered_on, expires_on )
SELECT c.cust_id, 1234, CURRENT TIMESTAMP, CURRENT TIMESTAMP + 30 DAYS 
FROM mktg.customers c 
LEFT OUTER JOIN mktg.offered_coupons o
ON o.cust_id = c.cust_id
WHERE ....
AND o.cust_id IS NULL
FETCH FIRST 1000 ROWS ONLY;


这就是 DB2 如何通过 UPDATEINSERTDELETE 语句支持 SELECT 的方式:
SELECT column1 FROM NEW TABLE (
    UPDATE ( SELECT column1 FROM someschema.sometable 
             WHERE ... FETCH FIRST ROW ONLY
    ) 
    SET column1 = 'newvalue'
) AS x;

SELECT 将仅从修改后的行返回数据。

【讨论】:

  • 对于 DB2,在第一个代码块中,SET t.column1 = 'newvalue' 部分实际上应该是 SET column1 = 'newvalue',因为别名 t 不在子查询之外。 PS:我什至不知道这样的更新是可能的!赞!
  • 很好,@ADTC。我已经更正了该代码示例。
【解决方案2】:

你有两个选择。正如A Horse With No Name 所指出的,您可以使用表的主键来确保一次更新一行。

如果您使用编程语言并且可以控制游标,则另一种方法是使用带有“FOR UPDATE”选项的游标(尽管这可能是可选的;IIRC,游标默认为“FOR UPDATE”当底层 SELECT 意味着它可以),然后在 UPDATE 语句中使用带有 WHERE CURRENT OF <cursor-name> 的 UPDATE 语句。这将更新游标当前寻址的一行。语法的详细信息因您使用的语言而异,但原始 SQL 如下所示:

DECLARE CURSOR cursor_name FOR
    SELECT *
      FROM SomeTable
     WHERE PKCol1 = ? AND PKCol2 = ?
       FOR UPDATE;

UPDATE SomeTable
   SET ...
 WHERE CURRENT OF cursor_name;

如果你不能用你的宿主语言编写 DECLARE,你必须手动 bashing 来找到等效的机制。

【讨论】:

  • 请注意,如果您的 cusor 被定义为利用阻塞(返回整组行),这将无法按预期工作 - 它只会更新 last当前块中的行(由于行指针位置)。
  • 谢谢,@X-Zero;我什至不知道有办法打破'WHERE CURRENT OF';令人惊讶的是有什么选择。这不是一种非常好的做事方式。我更喜欢通过搜索主键来更新记录,即使这比 WHERE CURRENT OF 等技术“慢”。
猜你喜欢
  • 2018-07-17
  • 2020-01-27
  • 2015-06-02
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 2019-02-18
  • 2016-08-13
  • 1970-01-01
相关资源
最近更新 更多