mik*_*utu 4 sql oracle plsql oracle12c
我正在尝试将WITH 子句中声明的函数使用到MERGE 语句中。这是我的代码:
create table test
(c1 varchar2(10),
c2 varchar2(10),
c3 varchar2(10));
insert into test(c1, c2) values ('a', 'A');
insert into test(c1, c2) values ('b', 'A');
select * from test;
begin
with function to_upper(val varchar2) return varchar is
begin
return upper(val);
end;
merge into test a
using (select * from test) b
on (upper(a.c1) = upper(b.c2))
when matched then
update set a.c3 = to_upper(a.c1);
end;
Run Code Online (Sandbox Code Playgroud)
但我收到此错误:
错误报告 - ORA-06550:第 2 行,第 15 列:PL/SQL:ORA-00905:缺少关键字 ORA-06550:第 2 行,第 1 列:PL/SQL:忽略 SQL 语句 ORA-06550:第 6 行,第 1 列: PLS-00103:遇到符号“MERGE”06550。00000 -“行 %s,列 %s:\n%s” *原因:通常是 PL/SQL 编译错误。*行动:
有人可以解释一下为什么它不起作用吗?
谢谢你,
该with子句是select语法的一部分。正如铁路图所示,该子句之后唯一有效的with是select关键字 - 您没有该关键字,因此您会看到错误。
正如文档还说的那样:
plsql_declarations子句允许您声明和定义 PL/SQL 函数和过程。然后,您可以在指定此子句的查询中引用 PL/SQL 函数及其子查询(如果有)。
和
如果指定此子句的查询不是顶级 SELECT 语句,则以下规则适用于包含该查询的顶级 SQL 语句:
- 如果顶级语句是 SELECT 语句,则它必须具有WITH plsql_declarations子句或WITH_PLSQL 提示。
- 如果顶级语句是 DELETE、MERGE、INSERT 或 UPDATE 语句,则它必须具有WITH_PLSQL 提示。
因此,您不能将该with子句应用于整个merge语句,只能将其用作该语句中查询的一部分,即在子句中using:
merge /*+ WITH_PLSQL */ into test a
using (
with function to_upper(val varchar2) return varchar is
begin
return upper(val);
end;
select to_upper(c2) as c2 from test
) b
on (upper(a.c1) = b.c2)
when matched then
update set a.c3 = upper(a.c1);
Run Code Online (Sandbox Code Playgroud)
如果没有/*+ WITH_PLSQL */提示,则会出现“ORA-32034:不支持使用WITH子句”的错误(尽管只有当您实际调用该函数时,否则编译器似乎会删除未使用的函数并且不会抱怨它)。
但该函数仍然仅在该using子句的范围内;您不能在onorupdate子句中引用它。您需要在using子句中执行任何函数调用;如果您需要将相同的函数应用于目标表中的任何内容,则需要重复该函数并使用子句调用该函数into,例如:
merge /*+ WITH_PLSQL */ into (
with function to_upper(val varchar2) return varchar is
begin
return upper(val);
end;
select to_upper(c1) as c1, c3 from test
) a
using (
with function to_upper(val varchar2) return varchar is
begin
return upper(val);
end;
select to_upper(c2) as c2 from test
) b
on (a.c1 = b.c2)
when matched then
update set a.c3 = a.c1;
Run Code Online (Sandbox Code Playgroud)
db<>fiddle显示有效和无效的内容。
这是一个非常人为的示例,因此如果有更真实的场景,它可能会更清晰。
| 归档时间: |
|
| 查看次数: |
1997 次 |
| 最近记录: |