【问题标题】:How do we perform multiple updates in Oracle我们如何在 Oracle 中执行多个更新
【发布时间】:2016-05-05 19:07:03
【问题描述】:
Table:T1 (key, numval, state) and T2(key, foreignkey:T1.key, type)

我有两个表 T1 和 T2,每个 T1 有多个值 T2。对于 T2 中的每个值,T1 中都有一个值。

考虑到我在 T2 中有两种类型('A','B'),我必须计算映射到每个 T1 键的 T2 的数量,状态为“A”和“B”并将其设置为 T1 .state 分别

如何在 Oracle 中完成此操作?

类似于下面的帖子(但解决方案不起作用): how to update a column in a table with unique values, but not all the rows, not incremented

使用上面的源代码 - 我使用了以下脚本:

UPDATE T1
SET VALUE =
   CASE
     WHEN (SELECT STATE FROM T1 WHERE KEY = EACH_KEY) = 'S1' 
                THEN 
                    (SELECT COUNT(*) FROM T2 
                                    WHERE KEY = EACH_KEY AND TYPE = 'A' 
     WHEN (SELECT STATE FROM T1 WHERE KEY = EACH_KEY) = 'S2' 
                THEN 
                    (SELECT COUNT(*) FROM T2 
                                    WHERE KEY = EACH_KEY AND TYPE = 'B' 
   END
WHERE  EACH_KEY in (select distinct KEY from T1);

但是oracle抛出如下错误:

Error at Command Line : 13 Column : 8
Error report -
SQL Error: ORA-00904: "EACH_KEY": invalid identifier
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

编辑#1:

表格中的样本数据

执行前

T1
key    numval    state
1      0         S1
2      0         S2
3      0         S1
4      0         S1

T2
key    t1key     type
1      1         A
2      1         B
3      1         B
4      2         A
5      2         B
6      2         B
7      3         B
8      4         A
9      4         A
10      4         B

执行后(预期结果)

T1
key    numval    state
1      1         S1
2      2         S2
3      0         S1
4      2         S2

编辑#2:

是的,未定义标识符。我想知道如何在 Oracle SQL 中定义这样的标识符,以便执行上述计算。

【问题讨论】:

  • 如果您可以更新您的问题以在两个表中显示一些示例数据以及您期望的输出,将会很有帮助。类似于this question 会很好。
  • 另外,“each_key”是从哪里来的? Oracle 消息是正确的;它不是 t1 中的列(至少,根据您提供的表的描述)。

标签: oracle oracle11g oracle-sqldeveloper


【解决方案1】:

这是支持@jva 答案的测试用例:

使用数据创建表:

create table t1 as
select 1 key, 0 numval, 'S1' state from dual union all
select 2 key, 0 numval, 'S2' state from dual union all
select 3 key, 0 numval, 'S1' state from dual union all
select 4 key, 0 numval, 'S1' state from dual;

create table t2 as
select 1 key, 1 t1key, 'A' type from dual union all
select 2 key, 1 t1key, 'B' type from dual union all
select 3 key, 1 t1key, 'B' type from dual union all
select 4 key, 2 t1key, 'A' type from dual union all
select 5 key, 2 t1key, 'B' type from dual union all
select 6 key, 2 t1key, 'B' type from dual union all
select 7 key, 3 t1key, 'B' type from dual union all
select 8 key, 4 t1key, 'A' type from dual union all
select 9 key, 4 t1key, 'A' type from dual union all
select 10 key, 4 t1key, 'B' type from dual;

检查t1中的初始值:

select * from t1 order by key;

       KEY     NUMVAL STATE
---------- ---------- -----
         1          0 S1   
         2          0 S2   
         3          0 S1   
         4          0 S1   

执行更新:

update t1
set    numval = case when state = 'S1' then (select count(*) from t2 where t2.t1key = t1.key and t2.type = 'A')
                     when state = 'S2' then (select count(*) from t2 where t2.t1key = t1.key and t2.type = 'B')
                end;

commit;

检查 t1 中的新值:

select * from t1 order by key;

       KEY     NUMVAL STATE
---------- ---------- -----
         1          1 S1   
         2          2 S2   
         3          0 S1   
         4          2 S1   

如您所见,这就是您想要的输出。

从您在评论@jva 的答案中提到的“缺陷”来看,我认为您对此感到困惑:

  1. 在答案中使用相关子查询,以及
  2. 更新如何与相关子查询一起使用。

我强烈建议您查看the documentation,具体来说:

当嵌套子查询引用表中的列时,Oracle 执行相关子查询,该表引用了子查询上一级的父语句。父语句可以是嵌套子查询的 SELECT、UPDATE 或 DELETE 语句。从概念上讲,相关子查询对父语句处理的每一行进行一次评估。

【讨论】:

    【解决方案2】:
    UPDATE T1
    SET numval = CASE WHEN t1.state = 'S1' THEN (SELECT COUNT(*) 
                                                 FROM t2
                                                 WHERE t1.key = t2.t1key
                                                   AND type = 'A')
                      WHEN t1.state = 'S2' THEN (SELECT COUNT(*) 
                                                 FROM t2
                                                 WHERE t1.key = t2.t1key
                                                   AND type = 'B')
                 END
    

    【讨论】:

    • @NaveenDennis 你是从哪里知道要引用值 t2.t1key 必须执行连接的? Jva 的更新语句中使用的子查询类型称为相关子查询。如果你不确定那是什么,你应该研究一下。从我所看到的来看,Jva 的答案是正确的 - 我将在单独的答案中发布一个测试用例来演示,但我想出了与这个完全相同的解决方案,所以你应该接受这个答案。
    • @Boneist 是的,我刚刚发现了这一点。请务必为我演示。谢谢。
    猜你喜欢
    • 2019-04-14
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 2019-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多