【问题标题】:Using a self join to update a table with Oracle SQL使用自联接通过 Oracle SQL 更新表
【发布时间】:2021-06-03 17:33:44
【问题描述】:

我正在尝试在 Oracle 中重写 MySQL 更新语句。我用的是Oracle SQL Developer 20.4.1版本,MySQL代码是:

UPDATE A
SET propertyaddress = ISNULL(A.propertyaddress, B.propertyaddress)
FROM nash_housing A
JOIN nash_housing B 
    ON A.parcelid = B.parcelid
    AND A.uniqueid_ <> B.uniqueid_
WHERE A.propertyaddress IS NULL;

我尝试了以下代码变体:

MERGE INTO nash_housing A
USING nash_housing B
ON (
    A.parcelid = B.parcelid
    AND A.uniqueid_ <> B.uniqueid_
    )
WHEN MATCHED THEN UPDATE
SET A.propertyaddress = B.propertyaddress
WHERE A.propertyaddress IS NULL;

错误 ORA-30926:无法在源表中获得一组稳定的行

UPDATE nash_housing A
    SET A.propertyaddress = (SELECT DISTINCT B.propertyaddress
                                FROM nash_housing B
                                WHERE A.parcelid = B.parcelid
                                AND A.uniqueid_ <> B.uniqueid_)
WHERE A.propertyaddress IS NULL
AND EXISTS (SELECT 1
            FROM nash_housing B
            WHERE A.parcelid = B.parcelid
            AND A.uniqueid_ <> B.uniqueid_);

错误 ORA-01427:单行子查询返回多于一行

UPDATE
(SELECT A.propertyaddress AS OLD, B.propertyaddress AS NEW
    FROM nash_housing A
    JOIN nash_housing B
    ON A.parcelid = B.parcelid
    AND A.uniqueid_ <> B.uniqueid_
    WHERE A.propertyaddress IS NULL
    ) C
SET C.OLD = C.NEW;

错误 SQL 错误:ORA-01779:无法修改映射到非键保留表的列

感谢您对此提供的任何帮助。

【问题讨论】:

  • 前两个错误都是因为A.parcelid = B.parcelid AND A.uniqueid_ &lt;&gt; B.uniqueid_匹配多行,至少有一个源行; &lt;&gt; 检查可能并不令人惊讶。当有多个地址时,您需要一些标准来决定使用哪个地址;比如最近的时间戳,或者最高的 ID 等等。
  • 请提供示例数据、期望的结果以及代码应该做什么的清晰解释。
  • 更新语句背后的想法是当两个 parcelid 值相同时,替换 propertyaddress 的 NULL 值,uniqueid 将有所不同,因为它是唯一标识符。因此,据我了解,这个想法是使用自连接来获取所需的 propertyaddress 来替换 NULL 值。
  • @JohnK - 问题是获取 所需的值来替换空值;正如 Gordon 所说,您正在寻找 a 值,当存在​​多种可能性时,该值是不确定的。

标签: sql oracle


【解决方案1】:

我认为第二个最接近。您只需将子查询限制为一行:

UPDATE nash_housing n
    SET propertyaddress = (SELECT n2.propertyaddress
                           FROM nash_housing n2
                           WHERE n2.parcelid = n.parcelid AND
                                 n2.uniqueid_ <> n.uniqueid_ AND
                                 rownum = 1
                          )
    WHERE n.propertyaddress IS NULL AND
          EXISTS (SELECT n2.propertyaddress
                  FROM nash_housing n2
                  WHERE n2.parcelid = n.parcelid AND
                        n2.uniqueid_ <> n.uniqueid_
                 );

注意:您的表格显然有重复项。 MySQL 版本正在使用 任意 匹配行进行更新。 Oracle 也会这样做,尽管您可能希望在子查询中使用 ORDER BY 来指定哪一行提供值(例如最新的或最旧的)。

另外,我修复了表别名,以便它们有意义。

【讨论】:

  • 谢谢你,修复它并按预期工作。也用于更新和更改@Gordon
猜你喜欢
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
  • 2021-03-25
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
相关资源
最近更新 更多