此查询出现错误“ ORA-01779:无法修改映射到非键保留表的列”
UPDATE
(SELECT P.SERVICE_DATE_OUT AS P_DATEOUT, P.SERVICE_DATE_IN AS P_DATEIN
FROM TRANSLOG TL JOIN PMEQMT P ON TL.ITEMNO = P.EQNO
WHERE TL.LOC_DESC = 'E-IN SERVICE')
SET P_DATEOUT = NULL, P_DATEIN = NULL
经过研究,我相信此错误是由于创建了一个内联视图而该更新试图更新两个表而不是我想要的表吗?有人可以确认吗?有解决方法吗?
为进一步说明我的情况,我建立了另外两个查询,这些查询每天都会运行,然后再运行上面的一个查询(如果可以使某些功能正常运行)。
第一:
UPDATE PMEQMT P
SET SERVICE_DATE_OUT = (SELECT MAX(TL.TRANS_DATE)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE' AND
TL.TRANS_DATE >= SYSDATE - 1 AND
TL.TRANS_IN_OUT = 'IN'
)
WHERE P.CLASS = 'TL' AND
P.SERVICE_DATE_OUT IS NULL
第二:
UPDATE PMEQMT P
SET SERVICE_DATE_IN =
CASE
WHEN SERVICE_DATE_IN IS NULL THEN (SELECT MAX(TL.TRANS_DATE)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-IN SERVICE' AND
TL.TRANS_DATE >= SYSDATE - 1 AND
TL.TRANS_IN_OUT = 'IN'
)
WHEN (TRUNC(SERVICE_DATE_IN)) <= (TRUNC(SYSDATE)) THEN (SELECT ((TRUNC(SYSDATE))+1)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE'
)
WHEN (TRUNC(SERVICE_DATE_IN)) > (TRUNC(SYSDATE)) THEN (SELECT SERVICE_DATE_IN
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE'
)
END
WHERE CLASS = 'TL'
有没有办法将它们结合起来?如果第一个查询开始运行,则这三个查询都可以运行;如果不运行,则最后两个查询都可以运行?合并它们是否有意义,还是我最好将它们分开?
非常感谢任何输入。
答案 0 :(得分:2)
关于您的第一个查询。为了更新联接视图(嵌套选择在内部变成视图),必须满足以下条件:
INSERT
,UPDATE
或DELETE
操作一次只能修改一个基础表。 (您的查询可以,您只更新PMEQMT
表。)第二个条件意味着表的每一行在联接表中必须只有一个对应的行(一对一关系)。
您可以详细了解here。
要解决此错误,您可以将更新语句重写为合并语句:
merge into PMEQMT t
using (SELECT P.EQNO
FROM TRANSLOG TL JOIN PMEQMT P ON TL.ITEMNO = P.EQNO
WHERE TL.LOC_DESC = 'E-IN SERVICE') u
on (u.EQNO = t.EQNO)
when matched then update set t.P_DATEOUT = NULL, t.P_DATEIN = NULL;
关于最后两个查询,您可以将它们合并为一个查询:
UPDATE PMEQMT P
SET SERVICE_DATE_OUT = case when P.SERVICE_DATE_OUT IS NULL then(SELECT MAX(TL.TRANS_DATE)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE' AND
TL.TRANS_DATE >= SYSDATE - 1 AND
TL.TRANS_IN_OUT = 'IN'
)
else P.SERVICE_DATE_OUT end,
SERVICE_DATE_IN =
CASE
WHEN SERVICE_DATE_IN IS NULL THEN (SELECT MAX(TL.TRANS_DATE)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-IN SERVICE' AND
TL.TRANS_DATE >= SYSDATE - 1 AND
TL.TRANS_IN_OUT = 'IN'
)
WHEN (TRUNC(SERVICE_DATE_IN)) <= (TRUNC(SYSDATE)) THEN (SELECT ((TRUNC(SYSDATE))+1)
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE'
)
WHEN (TRUNC(SERVICE_DATE_IN)) > (TRUNC(SYSDATE)) THEN (SELECT SERVICE_DATE_IN
FROM TRANSLOG TL
WHERE P.EQNO = TL.ITEMNO AND
TL.LOC_DESC = 'E-OUT OF SERVICE'
)
END
WHERE P.CLASS = 'TL';
对数据库的单个请求总是比连续几个更好。您还可以考虑重写内部重复查询,这样一来就可以得到结果,而不必一次又一次击中TRANSLOG
表。