具有多个联接的子选择的Oracle Update

时间:2019-05-30 13:58:17

标签: sql oracle

我正在尝试编写一个包含Oracle查询的脚本,以将项目的计划完成日期更新为通过变更请求提交的修订结束日期,但是在运行脚本时不会更新该日期。

我不确定这是我的查询问题还是其他问题。在深入探讨之前,此查询看起来应该可以工作吗? (我目前无法针对数据库本身测试查询。)

UPDATE Project pr
SET pr.ScheduledFinish = (SELECT ch.RevisedEndDate
                          FROM Change ch
                          JOIN ChangeRequests cr ON cr.ID = ch.ID
                          JOIN RisksAndIssues ri ON ri.ID = cr.ID
                          JOIN Project pr ON pr.ID = ri.PK_ID
                          WHERE pr.ID = ?)
WHERE pr.ID = (SELECT ID
               FROM Change ch
               WHERE ch.ID = ?)

注意:?查询中的绑定变量将采用当前正在处理的记录的值。即。如果操作的变更请求的ID为1214,则?脚本运行后将为1214。

谢谢。

更新:

我相信这是正确的逻辑:

UPDATE Project pr
SET pr.ScheduledFinish = (SELECT ch.RevisedEndDate
                          FROM Change ch
                          JOIN ChangeRequests cr ON cr.ID = ch.ID
                          JOIN RisksAndIssues ri ON ri.ID = cr.ID
                          JOIN Project pr ON pr.ID = ri.PK_ID
                          WHERE pr.ID = ?)
WHERE pr.ID = (SELECT ID
               FROM RisksAndIssues ri
               JOIN ChangeRequests cr ON cr.ID = ri.ID
               JOIN Change ch ON ch.ID = cr.ID
               JOIN Project pr ON pr.ID = ri.PK_ID
               WHERE pr.ID = ?)

戈登,你是正确的。我试图将变更ID与项目ID匹配,但是它们没有关联。因此,此更新的WHERE子句中的新子选择应该可以解决链接问题。

2 个答案:

答案 0 :(得分:0)

可能没有change.id与您的项目ID匹配。将所有JOIN列都称为ID是非常可疑的。我希望有更多这样的东西:

这不是表达你想要的逻辑吗?

UPDATE Project pr
SET pr.ScheduledFinish = (SELECT ch.RevisedEndDate
                          FROM Change ch JOIN
                               ChangeRequests cr
                               ON cr.ID = ch.ChangeID JOIN
                               RisksAndIssues ri
                               ON ri.ID = cr.RiskID
                          WHERE ri.ProjectID = pr.ID
                         )
WHERE pr.ID = (SELECT ch.projectID
               FROM Change ch
               WHERE ch.ID = ?
              )

但是,我不知道表中各列的实际名称,所以这只是一个猜测。

请注意,这会删除子查询中的Project引用。

答案 1 :(得分:0)

UPDATE Project pr
SET pr.ScheduledFinish = (SELECT ch.RevisedEndDate
                          FROM Change ch
                          JOIN ChangeRequests cr ON cr.ID = ch.ID
                          JOIN RisksAndIssues ri ON ri.ID = cr.ID
                          JOIN Project pr ON pr.ID = ri.PK_ID
                          WHERE pr.ID = ?)
WHERE pr.ID = (SELECT ID
               FROM RisksAndIssues ri
               JOIN ChangeRequests cr ON cr.ID = ri.ID
               JOIN Change ch ON ch.ID = cr.ID
               JOIN Project pr ON pr.ID = ri.PK_ID
               WHERE pr.ID = ?);

您的查询存在一些问题-首先,您没有在第二个子查询中为ID列加上别名-您要使用哪个ID? pr,ch,ri,...? 另外,您在子查询中还没有必要加入project;您可以将其与要更新的表相关联,因为它是同一张表。

您可以将其重写为:

UPDATE Project pr
SET pr.ScheduledFinish = (SELECT ch.RevisedEndDate
                          FROM Change ch
                          INNER JOIN ChangeRequests cr ON cr.ID = ch.ID
                          INNER JOIN RisksAndIssues ri ON ri.ID = cr.ID
                          WHERE ri.PK_ID = pr.ID)
WHERE pr.ID = ?
AND   EXISTS (SELECT NULL
               FROM RisksAndIssues ri
               JOIN ChangeRequests cr ON cr.ID = ri.ID
               JOIN Change ch ON ch.ID = cr.ID
               WHERE ri.pk_id = pr.ID);

或者,甚至更好的是,您可以避免使用MERGE语句来重复子查询,例如:

MERGE INTO project tgt
  USING (SELECT ri.pk_id,
                ch.revisedenddate
         FROM   CHANGE ch
         INNER JOIN ChangeRequests cr ON cr.ID = ch.ID
         INNER JOIN RisksAndIssues ri ON ri.ID = cr.ID
         WHERE  ri.pk_id = ?) src
    ON (tgt.id = src.pk_id)
WHEN MATCHED THEN
  UPDATE SET tgt.scheduledfinish = src.revisedenddate;