【问题标题】:Combine update statement and select statement结合更新语句和选择语句
【发布时间】:2016-07-06 15:02:09
【问题描述】:

我正在使用 Oracle SQL Developer,我正在尝试将更新和选择语句合并为一个。我知道 Oracle 不直接在更新语句中支持 FROM 或 JOINS,因此我将选择放在子查询中,但它仍然不起作用。

我有两张桌子;可操作且可测试。

MASTERTABLE 包含一个 ID_NUMBER 列和一个 TESTTABLE_ID 列。

TESTTABLE 包含一个 TESTTABLE_ID 列和一个 TEST_COLUMN 列。

我想做的是在只知道 ID_NUMBER 的同时更新 TEST_COLUMN 值。

我的陈述是这样的:

UPDATE TESTTABLE
SET TEST_COLUMN= 'Testvalue'
WHERE TESTTABLE.TESTTABLE_ID IN (SELECT MASTERTABLE.TESTTABLE_ID
FROM MASTERTABLE
WHERE ID_NUMBER=11);

但我陷入了某种循环。我哪里做错了?

【问题讨论】:

  • 是什么让您认为自己“陷入了某种循环”?查询永远不会完成吗?您是否收到错误消息?你的桌子有多大?
  • 我尝试在 Oracle SQL Developers Worksheet 脚本运行程序中运行查询,它会一直持续下去,看起来好像查询没有完成。我正在使用几个只有 3 行的小型试验表。
  • 对于这么小的表,它确实应该几乎立即返回。希望其中一位 Oracle 专家可以在这里为您指出解决方案,因为查询本身对我来说看起来不错。是否有可能您正在运行另一个线程,该线程在表上具有锁定并且正在阻止更新?这可能会帮助您追踪:oraclerecipes.com/monitoring/find-blocking-sessions
  • 我在 MASTERTABLE 上运行一个简单的更新查询没有问题,所以至少那部分不应该被阻止。

标签: sql oracle


【解决方案1】:

我也遇到过同样的问题。解决方案是使用MERGE 操作而不是UPDATE。

        MERGE INTO TESTTABLE t
        USING 
        (
          SELECT m.ID_NUMBER num,
                 m.TESTTABLE_ID id
          FROM MASTERTABLE m
        ) newnum ON (t.TESTTABLE_ID = newnum.id)
        WHEN MATCHED THEN UPDATE 
        SET t.TEST_COLUMN = newnum.num;

【讨论】:

  • 虽然这是一个可行的解决方案(而且我“过度使用”自己太多:) - 我只是发现 MERGE 更容易阅读).. 我不会完全称它为“解决方案” ”。他的 UPDATE 似乎非常好 - 所以其他东西可能导致他的“问题”;)
  • 这个解决方案仍然让 ScriptRunner 无限期地运行。没有错误消息,查询永远不会完成:(
【解决方案2】:

您可以在 Oracle 中尝试任何一种方法

正常更新

UPDATE
      TESTTABLE
SET
      TEST_COLUMN= 'Testvalue'
WHERE
      EXISTS
          (SELECT MASTERTABLE.TESTTABLE_ID 
           FROM MASTERTABLE 
           WHERE ID_NUMBER=11);

使用内联视图(如果 Oracle 认为可更新)

注意:如果您遇到非键保留行错误,请添加索引以解决相同问题,使其可更新

UPDATE
      (SELECT
            TESTTABLE.TEST_COLUMN AS OLD,
            'Testvalue' AS NEW
       FROM
                TESTTABLE
            INNER JOIN
                MASTERTABLE
            ON TESTTABLE.TESTTABLE_ID = MASTERTABLE.TESTTABLE_ID
       WHERE ID_NUMBER=11) T
SET
      T.OLD     = T.NEW;

使用合并

MERGE INTO
      TESTTABLE
USING
      (SELECT
            T1.ROWID AS RID,
            T2.TESTTABLE_ID
       FROM
                TESTTABLE T1
            INNER JOIN
                MASTERTABLE T2
            ON TESTTABLE.TESTTABLE_ID = MASTERTABLE.TESTTABLE_ID
       WHERE ID_NUMBER=11)
ON
      ( ROWID = RID )
WHEN MATCHED
THEN
    UPDATE SET TEST_COLUMN= 'Testvalue';

【讨论】:

  • 解决方案#1 和#2 显示了与我最初尝试解决方案相同的问题。第三个抛出错误:SQL Error: ORA-00904: "ASSERTION"."VOCABULARY_ID": invalid identifier
  • 这个 assertion.vocabulary_id 是从哪里来的?
  • 呸,应该是 SQL 错误:ORA-00904:“MASTERTABLE”。“TESTTABLE_ID”:标识符无效
  • 您提到“MASTERTABLE 包含一个 ID_NUMBER 列和一个 TESTTABLE_ID 列。”这意味着有这样的表和列??
  • 是的,有这样一个表和列,但它仍然在解决方案#3 上返回一个无效的标识符错误
【解决方案3】:

问题在于 Tom H 写了一个阻塞问题。当我今天开始从事这个项目时,所有的解决方案都奏效了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2023-01-28
    • 1970-01-01
    • 2020-04-03
    • 2018-01-22
    • 1970-01-01
    相关资源
    最近更新 更多