Oracle:根据其他表中的值更新表a中的列

发布于 2024-09-25 09:11:19 字数 1287 浏览 7 评论 0原文

我正在尝试为我正在编写的应用程序支持多个数据库。该应用程序主要使用 Hibernate,但是当 DML 语句可以在一小部分时间内处理它们时,迭代数百万行并单独处理它们的效率非常低。因此,对于某些操作,我需要制定SQL。我更喜欢 MySQL,但到目前为止我的应用程序可以与 SQL Server 和 MySQL 配合使用。有一个操作难倒了我,我似乎无法弄清楚如何为 Oracle 构建一些更新查询。我知道就 Oracle 而言,这可能是一个新手问题,但当我一直在寻找时,我一定错过了明显的答案......

以下是我为 MySQL 编写此类查询的方式:

update table1 t1, table2 t2 set t1.colA = t2.colA where t1.colB = t2.colB and t1.colC = t2.colC

MySQL 有一个很好的构造,您可以在“set”语句之前使用别名指定所有表,这大大简化了声明的其余部分。在 SQL Server 中,我使用 update ... join 来做同样的事情。

在Oracle中,我尝试使用'update table1 set colA = (select ....) where contains (select ....) 语法,但这不起作用 - 它返回一个'子查询返回多于一行' 错误。我还尝试使用 merge ... using ... on 语法,但出现“无法从源表中获取稳定的行集”的错误。

为了进一步解释我想要实现的目标,我需要执行许多查询,其中一些使用 2 个表,一些使用 3 个表。最复杂的需要执行此操作:

使用 tableC.colC 中的值更新 tableA.colB,其中所有匹配行的 tableA.colA = tableB.colA 和 tableB.colB = tableC.colB。从数据角度来看,这看起来像这样(之前和之后):

Before:

Table A
-------
colA     colB
1        NULL
2        NULL
3        NULL
4        NULL

Table B
-------
colA     colB
1        A
2        A
3        B
4        B

Table C
-------
colB     colC
A        15
B        20

After:

Table A
-------
colA     colB
1        15
2        15
3        20
4        20

我希望这足够清楚。谁能解释一下如何为 Oracle 编写这种 DML 查询?对于奖励积分,PostgreSQL 也会一样吗? :)

I'm trying to support multiple databases for an app that I'm writing. The app mostly uses Hibernate, but it's incredibly inefficient to iterate over millions of rows and process them individually when a DML statement can process them in a fraction of the time. Therefore, for certain operations, I need to work out the SQL. I'm more of a MySQL man, but I have the app working with SQL Server and MySQL so far. There's one operation that has stumped me, and I just can't seem to figure out how to construct some of the update queries for Oracle. I'm aware that this is probably a newbie question as far as Oracle goes, but I must have missed the obvious answers when I've been looking....

Here's how I write this type of query for MySQL:

update table1 t1, table2 t2 set t1.colA = t2.colA where t1.colB = t2.colB and t1.colC = t2.colC

MySQL has a nice construct where you can just specify all tables before the 'set' statement with aliases, which greatly simplifies the rest of the statement. In SQL Server, I use update ... join to do the same thing.

In Oracle, I've tried using the 'update table1 set colA = (select ....) where exists (select ....) syntax, but this doesn't work - it returns a 'subquery returns more than one row' error. I've also tried to use the merge ... using ... on syntax, but that errors with 'unable to get a stable set of rows from the source tables'.

To further explain what I'm trying to achieve, I have a number of queries to perform, some of them using 2 tables, some using 3 tables. The most complex needs to do this:

update tableA.colB with the value in tableC.colC where tableA.colA = tableB.colA and tableB.colB = tableC.colB for all matched rows. In data terms, this looks like this (Before and after):

Before:

Table A
-------
colA     colB
1        NULL
2        NULL
3        NULL
4        NULL

Table B
-------
colA     colB
1        A
2        A
3        B
4        B

Table C
-------
colB     colC
A        15
B        20

After:

Table A
-------
colA     colB
1        15
2        15
3        20
4        20

I hope this is clear enough. Can anyone explain how to write this kind of DML query for Oracle? For bonus points, will it be the same for PostgreSQL? :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

困倦 2024-10-02 09:11:19

您可以使用 distinct 忽略同一值的多个副本:

update  TableA
set     ColB = 
        (
        select  distinct ColC
        from    TableC C
        join    TableB B
        on      C.ColB = B.ColB
        where   B.ColA = TableA.ColA
        )

如果找到多个合适的值,这仍然会产生错误。

You can use distinct to ignore multiple copies of the same value:

update  TableA
set     ColB = 
        (
        select  distinct ColC
        from    TableC C
        join    TableB B
        on      C.ColB = B.ColB
        where   B.ColA = TableA.ColA
        )

This still gives an error if more then one suitable value is found.

丑丑阿 2024-10-02 09:11:19

之前

    SQL> select * from A
      2  /

          COLA       COLC
    ---------- ----------
             1
             2
             3
             4

    SQL> select * from B
      2  /

          COLA C
    ---------- -
             1 A
             2 A
             3 B
             4 B

    SQL> select * from C
      2  /

    C       COLC
    - ----------
    A         15
    B         20

    SQL>

查询

    SQL> update A
      2  set colc = ( select c.colc
      3               from c
      4                      join b on ( c.colB = b.colB )
      5               where
      6                  b.colA = A.colA )
      7  where exists
      8      ( select null
      9               from c
     10                      join b on ( c.colB = b.colB )
     11               where
     12                  b.colA = A.colA )
     13  /

    4 rows updated.

    SQL>

之后

    SQL> select * from A
      2  /

          COLA       COLC
    ---------- ----------
             1         15
             2         15
             3         20
             4         20

    SQL>

显然,您已经简化了测试用例中的某些内容,因此它不能代表您的实际情况。关键是,我的查询有效,因为子查询为 A.colA 的每个值返回一行。您需要重新访问您的数据并建立必要的标准。这是一个数据/业务逻辑问题,而不是语法问题。

before

    SQL> select * from A
      2  /

          COLA       COLC
    ---------- ----------
             1
             2
             3
             4

    SQL> select * from B
      2  /

          COLA C
    ---------- -
             1 A
             2 A
             3 B
             4 B

    SQL> select * from C
      2  /

    C       COLC
    - ----------
    A         15
    B         20

    SQL>

The query

    SQL> update A
      2  set colc = ( select c.colc
      3               from c
      4                      join b on ( c.colB = b.colB )
      5               where
      6                  b.colA = A.colA )
      7  where exists
      8      ( select null
      9               from c
     10                      join b on ( c.colB = b.colB )
     11               where
     12                  b.colA = A.colA )
     13  /

    4 rows updated.

    SQL>

After

    SQL> select * from A
      2  /

          COLA       COLC
    ---------- ----------
             1         15
             2         15
             3         20
             4         20

    SQL>

Obviously you have simplified something in your test case so it is not representative of your actual situation. The key thing is, my query works because the sub-query returns a single row for each value of A.colA. You need to re-visit your data and establish the necessary criteria. This is a data/business logic problem, not a syntax problem.

燃情 2024-10-02 09:11:19

尝试以下操作:

UPDATE table_a a
  SET col_b = (SELECT col_c
                 FROM table_b b,
                      table_c c
                 WHERE b.col_a = a.col_a AND
                       c.col_b = b.col_b);

我这台机器上没有安装 Postgresql,所以无法对此发表评论。

分享并享受。

Try the following:

UPDATE table_a a
  SET col_b = (SELECT col_c
                 FROM table_b b,
                      table_c c
                 WHERE b.col_a = a.col_a AND
                       c.col_b = b.col_b);

I don't happen to have Postgresql on this machine so can't comment on that.

Share and enjoy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文