我是Oracle 11g和这个论坛的新手。我只需要使用Oracle Merge语句运行一个简单的更新语句,因为我的SQL开发人员不会采用任何其他方式。
奇怪的是,无论我如何尝试更正声明,即使在此论坛中阅读了许多条目后,我仍然会收到完全相同的错误消息。
有两种不同的错误消息,取决于我在SQL Developer中运行语句的方式。如果我将我的语句作为存储过程运行(更新语句是存储过程中的一小部分。我注释掉了其他SQL语句,只是在存储过程中保留了此更新语句)我收到此错误:
create or replace
PROCEDURE ADDR_UPDATE_2
AS
/* other sql statements are commented out */
MERGE INTO (SELECT id,xseq,line_1,line_2,zip,tax FROM ADDR ) b
USING (SELECT id,xseq,line_1, line_2,NVL(zip, '') AS pos_10 , NVL(tax, '') AS pos_11
FROM TEMP_ADDR ) v
ON(b.id = v.id
AND b.xseq = v.xseq)
WHEN MATCHED THEN UPDATE SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11
WHERE b.line_1 <> v.line_1
OR b.line_2 <> v.line_2
OR b.zip <> v.pos_10;
/* other sql statements are commented out */
END;
错误(23,9):PLS-00103:遇到以下其中一项时遇到符号“INTO”:常量异常表long double ref char time timestamp interval date二进制国家字符nchar
(我到处都是,但没有找到任何答案)
第23行是指“INTO”一词
create or replace
PROCEDURE ADDR_UPDATE_2
AS
/* other sql statements are commented out */
MERGE INTO ADDR b
USING (SELECT id,xseq, line_1, line_2, NVL(zip, '') AS pos_10,
NVL(tax, '') AS pos_11
FROM TEMP_ADDR) v
ON(b.id = v.id
AND b.xseq = v.xseq
AND b.line_1 <> v.line_1
OR b.line_2 <> v.line_2
OR b.zip <> v.pos_10)
WHEN MATCHED THEN UPDATE SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11;
/*
other sql statements are commented out
*/
END;
错误(23,9):PLS-00103:遇到以下其中一项时遇到符号“INTO”:常量异常表long double ref char time timestamp interval date二进制国家字符nchar
第23行是指“INTO”一词
命令行错误:9列:8
错误报告:
SQL错误:ORA-38104:无法更新ON子句中引用的列:“B”。“LINE_2”
38104. 00000 - “无法更新ON子句中引用的列:%s”
*原因:UPDATE SET的LHS包含ON子句中引用的列
*操作:
我在2天前尝试过寻找答案而没有结果,有没有人可以帮忙解决这个问题?
答案 0 :(得分:2)
正如我在上面引用的问题中所解释的那样,'ON子句中引用的列无法更新'意味着如果它们包含在ON条件中,我们就无法更新MATCHED子句中的列。
您处于这个位置是因为您正在尝试使用MERGE执行不打算执行的操作。现在你说
“我只需要使用Oracle Merge运行一个简单的更新语句 声明,因为我的SQL开发人员不会采取任何其他方式。“
Fnord。如果您获得正确的语法,SQL Developer绝对不会阻止您运行更新语句。遗憾的是,Oracle不支持DML语句中的ANSI连接语法(与RDBMS的其他flovours不同),并且Oracle语法不直观:
update
(
select v.id
, v.xseq
, v.line_1
, v.line_2
, nvl(v.zip, '') AS pos_10
, nvl(v.tax, '') AS pos_11
from addr b
,temp_addr v
where ( b.id = v.id
and b.xseq = v.xseq )
and ( b.line_1 <> v.line_1
or b.line_2 <> v.line_2
or b.zip <> v.pos_10)
)
set b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11
;
答案 1 :(得分:0)
以下MERGE语句至少应该正确编译和执行,虽然我同意@APC,这里做的正确的事情是使用UPDATE(因为那是你真正想要做的):
MERGE INTO ADDR b
USING TEMP_ADDR v
ON (b.id = v.id AND
b.xseq = v.xseq)
WHEN MATCHED THEN
UPDATE
SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.zip,
b.tax = v.tax;
我消除了您正在进行的NVL
操作,因为在Oracle中,零长度字符串(例如''
)与NULL相同,因此NVL调用相当于说“如果此字段是不是NULL,返回它 - 否则返回NULL“这有点无意义。
祝你好运。