基于选择查询的Oracle Update语句w / Joins不起作用

时间:2017-11-22 21:18:44

标签: sql oracle join sql-update

我正在尝试根据已加入的选择查询应用更新查询,但它无效。

UPDATE (
  SELECT 
    LOCATION_NUM, LOCATION_TYPE, LOCATION_CITY, ACCOUNT_NUM
  FROM 
    TBLSALES T1
    INNER JOIN TBLCENTER  T2 ON T2.LOCATION_ID = T1.LOCATION_ID
    INNER JOIN TBLACCOUNT T3 ON T3.ACCOUNT_ID  = T1.ACCOUNT_ID
  WHERE
    LOCATION_CITY = 'New York' 
    AND LOCATION_NUM LIKE 'NY1%' 
    AND ACCOUNT_NUM IN ('40001','40002','40003')
)
SET 
   LOCATION_TYPE = 'TYPE 1'
;

运行时我收到以下错误:

SQL Error: ORA-01779: cannot modify a column which maps to a non key preserved table

1 个答案:

答案 0 :(得分:2)

当你尝试通过加入更新时,就像你一样,必须有两个条件:

  • 查找表中的查找键(您有两个表,因此location_id中的两个查找键tblcenteraccount_id中的tblaccount)不得有重复项;它必须是"独特的" (在"意义上没有重复的值")。这是一个明显的逻辑要求;如果不满足,基于模糊查找的更新问题是无稽之谈。
  • Oracle需要在分析时知道事先,唯一性将保持不变。也就是说,表必须在这些列上具有唯一约束和/或唯一索引。这不是逻辑要求,而是Oracle实施要求。对于两个查找表中的至少一个(可能是两个),错误消息告诉您不满足第二个条件。

如何解决这个问题?您有几个选择:

  • 最简单:在这些表中的那些列上创建UNIQUE约束(或PRIMARY KEY约束)。很可能他们意味着首先是PK,但他们并非如此。请注意 - "主键"或"独特的"约束在应用程序中维护 - 正如我被告知PeopleSoft所做的那样 - 例如 - 没有帮助

  • 您可以通过MERGE语句进行更新。语法非常相似。不同之处在于MERGE会等到它看到所有数据,并且只有在实际上在实际数据中找到重复项时才会抱怨,其中不应该找到重复数据。

  • 效率稍差,但有一个明显的解决方法:将语句重写为

    更新tblsales 设置location_type =' TYPE 1' 其中(.....)

......直到现在我才意识到我并没有真正进入WHERE子句。如果您说(在UPDATE语句本身!)哪些列来自哪些表,这将有所帮助。我猜想LOCATION_NUM来自SALES表?那么WHERE子句应该类似于

where location_num like 'NY1%'
  and location_num in (select location_num from the three-way join)

(假设这是您原始UPDATE语句的含义)。