我有table FOO
,其中col N_RA_ID
中MANUAL%
的值在col V_CUST_NUMBER
中有一些ID值,对于col N_RA_ID
中的非手动值,在col V_CUST_NUMBER
中有一些匹配值{1}}。这是示例数据-
我想在col N_RA_ID
上自行加入,只要有完全匹配的地方,我就想update N_RA_ID
到null WHERE V_CUST_NUMBER LIKE 'MANUAL%'
因此输出应类似于-
我尝试使用合并,但得到ORA-38104。有人可以帮忙吗?
MERGE INTO FOO X
USING (
SELECT T1.V_CUST_NUMBER AS MAN_CUST,T1.N_RA_ID, T2.V_CUST_NUMBER
FROM FOO T1
JOIN FOO T2
ON T1.N_RA_ID = T2.N_RA_ID
AND UPPER(T1.V_CUST_NUMBER) NOT LIKE 'MANUAL%'
) Z
ON (X.N_RA_ID = Z.N_RA_ID)
WHEN MATCHED THEN UPDATE
SET X.N_RA_ID = null
WHERE UPPER(X.V_CUST_NUMBER) LIKE 'MANUAL%'
SQL Error: ORA-38104: Columns referenced in the ON Clause cannot be updated: "X"."N_RA_ID"
38104. 00000 - "Columns referenced in the ON Clause cannot be updated: %s"
*Cause: LHS of UPDATE SET contains the columns referenced in the ON Clause
*Action:
答案 0 :(得分:2)
您可以使用exists ()
进行简单的更新:
update foo f1
set n_ra_id = null
where v_cust_number like 'MANUAL%'
and exists (
select *
from foo f2
where f2.n_ra_id = f1.n_ra_id
and v_cust_number not like 'MANUAL%'
);
主要更新首先在所有以'MANUAL'开头的行上进行过滤,exists()
内的子查询在表中查找具有相同ID但不以'MANUAL'开头的任何行。如果没有这样的非手动行,则该子句为false,手动行保持不变;如果存在匹配项,则更新该行。
演示:
select * from foo;
V_CUST_NU N_RA_ID
--------- ----------
MANUAL033 17024
MANUAL034 589469
MANUAL035 589470
MANUAL036 589478
BHASAD 589478
update foo f1
set n_ra_id = null
where v_cust_number like 'MANUAL%'
and exists (
select *
from foo f2
where f2.n_ra_id = f1.n_ra_id
and v_cust_number not like 'MANUAL%'
);
1 row updated.
select * from foo;
V_CUST_NU N_RA_ID
--------- ----------
MANUAL033 17024
MANUAL034 589469
MANUAL035 589470
MANUAL036
BHASAD 589478
答案 1 :(得分:2)
通常的解决方法是在OUTGOING_TYPE
子句中选择T2.ROWID as RID
,然后匹配USING
,而不是在N_RA_ID
上进行匹配。
像这样:
ON X.ROWID = Z.RID
答案 2 :(得分:0)
从Oracle 18c开始,存在一些变通办法可以应用于此类MERGE
语句which outsmart the parser who checks for ORA-38104 preconditions。例如,您可以将行值表达式与其他虚拟列比较一起使用:
MERGE INTO FOO X
USING (
SELECT T1.V_CUST_NUMBER AS MAN_CUST,T1.N_RA_ID, T2.V_CUST_NUMBER
FROM FOO T1
JOIN FOO T2
ON T1.N_RA_ID = T2.N_RA_ID
AND UPPER(T1.V_CUST_NUMBER) NOT LIKE 'MANUAL%'
) Z
ON ((X.N_RA_ID, 'dummy') = ((Z.N_RA_ID, 'dummy')))
WHEN MATCHED THEN UPDATE
SET X.N_RA_ID = null
WHERE UPPER(X.V_CUST_NUMBER) LIKE 'MANUAL%'