Java Oracle:基于选择结果的条件更新

Java Oracle:基于选择结果的条件更新,java,oracle,oracle11g,java-8,Java,Oracle,Oracle11g,Java 8,我只想在select语句返回特定值时执行更新 例如: 给定表格: ItemId | CheckIn 0 0 1 0 2 1 3 1 4 1 我将操作大量的ItemId,例如itemid1,2,3 如果所有选定的ItemId的签入值为0,则我应该将ItemId的签入更新为1。否则,如果至少一个选定的ItemId为1,则不应执行更新 这在一个SELECT/UPDATE语句中可能吗 背景: 签入值的检查和随后的更新必须是线程安全的

我只想在select语句返回特定值时执行更新

例如:

给定表格:

ItemId | CheckIn
0        0
1        0
2        1
3        1
4        1
我将操作大量的ItemId,例如itemid1,2,3

如果所有选定的ItemId的签入值为0,则我应该将ItemId的签入更新为1。否则,如果至少一个选定的ItemId为1,则不应执行更新

这在一个SELECT/UPDATE语句中可能吗

背景:

签入值的检查和随后的更新必须是线程安全的Java 8

有效的方法是在实际的UPDATE语句之前为UPDATE单独选择一个SELECT语句,但我希望避免这样做

因此,我认为唯一的其他选择是将SELECT with UPDATE放入单个条件查询中,我不确定这是否可行,因此我提出了问题


顺便说一句,我正在使用Java 8,因此如果您知道如何实现这一点,基于Java的解决方案也可以。

您可能希望这样做:

MySQL查询:

Oracle查询:

我已经创建了一个派生表,并使用了一个组函数sum来处理这个场景。我已经测试过了,它按照问题中的描述工作。

试试这个:

UPDATE YOUR_TABLE TOUT
SET
    TOUT.CHECKIN = (
        SELECT
            CASE
                WHEN SUM(T.CHECKIN) = 0 THEN 1
                ELSE TOUT.CHECKIN
            END
        FROM
            YOUR_TABLE T
        WHERE
            T.ITEMID IN (
                1,
                2,
                3
            )
    )
WHERE
    TOUT.ITEMID IN (
        1,
        2,
        3
    );

干杯

您可以在merge语句中执行此操作,例如:

MERGE INTO your_table tgt
  USING (SELECT itemid,
                checkin,
                overall_checkin
         FROM   (SELECT itemid,
                        checkin,
                        MAX(CASE WHEN checkin = 0 THEN 0 ELSE 1) OVER () overall_checkin
                 FROM   your_table
                 WHERE  itemid IN (1, 2, 3))
         WHERE  overall_checkin = 0) src
   ON (tgt.itemid = src.itemid) -- assuming that itemid is a primary/unique column
WHEN MATCHED THEN
  UPDATE tgt.checkin = 1;

并演示合并语句。

为什么不使用select语句作为子查询?类似这样的内容:updatesome_table set some_field=some_value其中select some_field=some_value from some_table其中some_list中的some_field我不需要条件更新,在条件更新中我只更新某些值的行,我需要条件更新,在条件更新中我只在子查询返回特定结果时执行更新。因此,我只想在所选ItemId的签入值均不为1的情况下执行更新。在这种情况下,您可能希望将select查询的结果存储在变量中。然后根据该结果执行更新查询。这不是线程安全的,如原始问题中所述。我想避免锁定行,如前所述,如果可以在rowid上合并,为什么要假设?此查询比where子句中使用sum的版本更糟糕,因为它可能会生成更多的undo。将值更新到自身与根本不更新值不同。WHERE子句中只有3项。我认为它不会产生太多撤销数据。对,在这种情况下,除非执行查询,比如说,1000 000次,否则它不会产生太多撤销数据。但是,不管项目的数量如何,这永远都不是一个好的做法。另外,如果有新的要求按项删除筛选器,那么您的查询必须完全重构。当然,您是正确的,但在这种情况下,我认为我们甚至不应该考虑撤消
UPDATE YOUR_TABLE TOUT
SET
    TOUT.CHECKIN = (
        SELECT
            CASE
                WHEN SUM(T.CHECKIN) = 0 THEN 1
                ELSE TOUT.CHECKIN
            END
        FROM
            YOUR_TABLE T
        WHERE
            T.ITEMID IN (
                1,
                2,
                3
            )
    )
WHERE
    TOUT.ITEMID IN (
        1,
        2,
        3
    );
MERGE INTO your_table tgt
  USING (SELECT itemid,
                checkin,
                overall_checkin
         FROM   (SELECT itemid,
                        checkin,
                        MAX(CASE WHEN checkin = 0 THEN 0 ELSE 1) OVER () overall_checkin
                 FROM   your_table
                 WHERE  itemid IN (1, 2, 3))
         WHERE  overall_checkin = 0) src
   ON (tgt.itemid = src.itemid) -- assuming that itemid is a primary/unique column
WHEN MATCHED THEN
  UPDATE tgt.checkin = 1;