我的存储过程定义为
create or replace procedure TEST(
name IN table1.col_name%type,
price IN table1.col_price%type
)
is
begin
update table1 t set t.name =name where t.price = price;
commit;
end TEST;
我正在尝试执行
exec TEST(name => 'John', price => 1000);
然而,它给出无效的SQL错误。我错过了什么?
输入参数%type
语句声明列名是col_name
和col_price
。但这不是您在存储过程(name
和price
)中引用它们的方式。
在列名之后命名变量可能会发生不好的事情。AskTom建议使用有限的变量命名约定:
- 本地变量以
L_
开头 - 参数以
P_
开头 - 全局包变量以
G_
开头
这个链接对PL/SQL命名约定进行了很好的讨论。我个人只对大多数变量使用V_
(除了索引和其他明显的东西),但这只是我。
最后,列名称中的col_
似乎是多余的;仅使用name
和price
作为列名。
所以,这就是说,我认为这是你想要的:
create table table1 (
name varchar2(30),
price number
);
create or replace procedure TEST(
p_name IN table1.name%type,
p_price IN table1.price%type
)
is
begin
update table1
set name = p_name
where price = p_price;
commit;
end TEST;
/
insert into table1 values ('John', 500);
commit;
select * from table1;
exec TEST(p_name => 'Bob', p_price => 500);
select * from table1;
-- Clean up test artifacts
drop procedure test;
drop table table1;
给出输出:
table TABLE1 created.
PROCEDURE TEST compiled
1 rows inserted.
committed.
NAME PRICE
------------------------------ ----------
John 500
anonymous block completed
NAME PRICE
------------------------------ ----------
Bob 500
procedure TEST dropped.
table TABLE1 dropped.
我真的不明白变量前缀的方法。Oracle没有使用他们自己的API,如果他们这样做,那将是非常令人恼火的。这似乎总是一个变通,而不是一个修复。
对我来说,解决方法是用过程名命名变量。它使参数名称保持"干净",并使您的代码100%防止捕获:
create or replace procedure TEST(
name IN table1.col_name%type,
price IN table1.col_price%type)
is
begin
update table1 t
set name = test.name
where t.price = price;
commit;
end TEST;