带有子查询的 SQL 更新

Posted

技术标签:

【中文标题】带有子查询的 SQL 更新【英文标题】:SQL Update with subsubquery 【发布时间】:2011-09-21 13:05:53 【问题描述】:

我在 Oracle 11g 中遇到以下更新查询问题:

update TABLE_A a set COL1 = 
  (SELECT b.COL2 FROM
    (SELECT ROWNUM AS ROW_NUMBER, b.COL2 from TABLE_B b where COL3 = a.COL4) 
   WHERE ROW_NUMBER = 2
  )

ORA-00904:“A”。“COL4”:无效 ID。

所以,a.COL4 在子子查询中是未知的,但我不知道如何解决这个问题。

/编辑。我想做什么?

对于 TABLE_A 中的每条记录,TABLE_B 中都有多条记录。然而,来自客户的新要求:TABLE_A 将获得 2 个新列,而 TABLE_B 将被删除。因此,子查询的第一条记录的表示将被写入第一个新字段,第二个字段也是如此。第一个记录很容易,因为 Mike C 的解决方案可以与 ROW_NUMBER = 1 一起使用。

示例行:

TABLE_A

| col0 | col1 | col2 | col3 | col4 |
------------------------------------
|      |      |dummy2|dummy3|   1  |
------------------------------------
|      |      |dummy4|dummy5|   2  |
------------------------------------

TABLE_B

| col1 | col2 | col3 |
----------------------
|  d   |name1 |   1  |
----------------------
|  d   |name2 |   1  |
----------------------
|  d   |name3 |   1  |
----------------------
|  d   |name4 |   2  |
----------------------


TABLE_A after update

| col0 | col1 | col2 | col3 | col4 |
------------------------------------
| name1| name2|dummy2|dummy3|   1  |
------------------------------------
| name4|      |dummy4|dummy5|   2  |
------------------------------------

【问题讨论】:

“where row_number=2”的目的是什么?你到底想做什么? 正在编辑中。需要将 TABLE_B 中前两条记录的表示形式与 TABLE_A 中的字段匹配到 TABLE_A 中的两个新字段中。 好的,所以是一个数据透视表,将 tableB 中的 2 行转换为 tableA 中的 2 列?可以考虑通过 CTAS 将 2 个表连接到一个数据透视表中来重新创建 tableA。什么 Oracle 版本? 另外,一个简单的表结构示例和一些具有所需输出的测试行会有所帮助 【参考方案1】:
UPDATE TABLE_A a SET COL1 = 
  (SELECT b.COL2 FROM
    (SELECT ROWNUM AS ROW_NUMBER, b.COL2 FROM TABLE_B b, TABLE_A innerA WHERE COL3 = innerA.COL4) 
   WHERE ROW_NUMBER = 2
  )

【讨论】:

内部选择将返回比我在原始查询中预期的更多的记录。它不会从 TABLE_B 返回与正在从 TABLE_A 更新的记录匹配的记录,而是从 TABLE_B 返回与来自 TABLE_A 的任何记录匹配的记录。 嗯,好的。如果您在原始问题中描述您想要通过查询实现的目标,这可能会有所帮助。【参考方案2】:

你能像这样消除其中一个子查询吗?

update TABLE_A a set COL1 = 
(SELECT b.COL2 FROM TABLE_B b where COL3 = a.COL4 AND ROWNUM = 2)

【讨论】:

【参考方案3】:

试试

update TABLE_A a set COL1 = 
  (SELECT b.COL2 FROM
    (SELECT ROWNUM AS ROW_NUMBER, b.COL2 from TABLE_B b, TABLE_A a2 where b.COL3 = a2.COL4) 
   WHERE ROW_NUMBER = 2
  )

我假设 COL3 来自表 b,为什么还要在子查询中选择 ROWNUM? WHERE 子句中只能是 2 个。

【讨论】:

啊,是的,看看rownum的问题。你到底想做什么?【参考方案4】:

我认为这可能是解决您的问题的一个可能的解决方案,但根据您正在处理的数据量,它可能会非常慢,因为内部语句没有限制因素。

update
  table_a upd
set upd.col1 = (
  select
    sub.col2
  from
    (
      select
        rownum as row_number,
        b.col2 as col2,
        b.col3 as col3
      from
        table_a a,
        table_b b
      where b.col3 = a.col4
    ) sub
  where sub.row_number = 2
    and sub.col3       = upd.col4
)

【讨论】:

【参考方案5】:

我使用临时表解决了这个问题,在表 A 填满时从其中删除数据。

【讨论】:

以上是关于带有子查询的 SQL 更新的主要内容,如果未能解决你的问题,请参考以下文章

带有在子查询中生成的值的 Oracle SQL 更新语句

带有子查询的Postgresql更新[重复]

如何在带有子查询的列中“更新选择”某些值?

带有子查询的 SQL 查询缓慢

带有子查询语法错误的红移更新查询

带有子查询的 Oracle 更新 - 性能问题