Oracle ORA-01427:单行子查询返回多行,但实际上没有行

时间:2014-12-19 22:10:11

标签: sql database oracle sql-update inner-join

我已经可以听到呻吟声看着我的头衔,但请耐心等一下。 :)

我有两个表有一些共同的列,并通过不同的方式更新。给定一个特定的标识符,如果第一个表缺少某些信息,我想用第二个表中的值更新第一个表。

表A看起来像:

Dept_ID  Reviewer  Reviewer_Team  Reviewer_Code
ACM      Null      Null           Null
EOT      Null      Null           Null
QQQ      Joe       Joe's Group    XYZ
ACM      Null      Null           Null
ZZZ      Null      Null           Null

表B看起来像:

Dept_ID  Reviewer  Reviewer_Team  Reviewer_Code
AAA      Al        Al's Group     123
BBB      Bob       Bob's Group    234
ZZZ      Zoe       Zoe's Group    567

如果表A中的Reviewer_Code为空,我们希望在表B中找到表A的Dept_ID,并更新表A的其他字段以匹配表B.注意,表A可能具有多个记录相同的Dept_ID,在这种情况下,我们希望它们具有从表B更新的相同值。

听起来很简单。使用上面的表作为示例,表B中没有匹配项,因此在此步骤中不会更新ACM和EOT记录。表A的ZZZ记录虽然会根据表B的ZZZ记录进行更新。

然而,表B中没有匹配的可能性。因此,假设表A没有ZZZ记录,只有具有Null的ACM和EOT。

我是Oracle的新手(来自SQL Server),所以我可能正在测试这个错误,但我所拥有的是Oracle SQL Developer的.sql窗口中的一堆查询。这对我来说似乎很正常。当它得到这个查询,虽然我得到了可怕的"单行子查询"错误。

以下是我尝试过几种不同方式的查询:

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) =
  (SELECT DISTINCT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   WHERE b.Dept_Id = vchr.Dept_Id)
   WHERE vchr.Reviewer_Code IS NULL
     AND vchr.Business_L1 = 'CF'
     AND vchr.Dept_ID IS NOT NULL; 

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) =
  (SELECT DISTINCT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   inner join VchrImpDetailCombined a
   on b.Dept_Id = a.Dept_Id
   WHERE b.Dept_Id = vchr.Dept_Id)
   WHERE vchr.Reviewer_Code IS NULL
     AND vchr.Business_L1 = 'CF'
     AND vchr.Dept_ID IS NOT NULL; 

我还尝试过其他一些事情,例如做" WHERE EXISTS SELECT blahblah"或" WHERE b.Dept_ID IS NOT NULL"等等。

现在,根据我上面的示例数据,子查询应该有0条记录,请记住,表A中的ZZZ记录实际上并不像我的例子,只有ACM和EOT。表B根本没有表A中匹配的Dept_ID的记录。所以我的期望是0记录更新并愉快地移动到下一个查询。

当我在一串其他查询中运行这些查询时,我收到错误。如果我通过它的寂寞运行查询,我只需更新" 3行"考虑到应该没有匹配,这似乎很奇怪,任何事情都在更新。但更新的3行似乎与3个ACM和EOT记录匹配,即使表B没有根据标准更新任何内容。

我必须遗漏一些明显的东西,但我似乎无法掌握它。这些ORA-01427问题中有很多,所以我很确定我已经找到答案,但似乎无法找到它。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您需要指示Oracle只有在有数据的情况下才会执行更新(我希望SQL Server也需要这样做,但我不确定)。这将克服这一障碍,但代价是执行额外的子查询:

UPDATE VchrImpDetailCombined vchr
SET (Reviewer, Reviewer_Team, Reviewer_Code) = (
  SELECT b.Reviewer, b.Reviewer_Team, b.Reviewer_Code
   FROM GlobPMSDeptIdMapping b 
   WHERE b.Dept_Id = vchr.Dept_Id
)
WHERE vchr.Reviewer_Code IS NULL
  AND vchr.Business_L1 = 'CF'
  AND vchr.Dept_ID IN (
    SELECT Dept_Id
    FROM GlobPMSDeptIdMapping
  );

根据我对该问题的评论,我从(原始)子查询中删除了DISTINCT,因为它不需要或无效。