在存储过程内可以调用其他多个存储过程或函数,这是支持 存储过程(procedure)的数据库都支持的,近日在做oracle到opengauss系(MogDB)的plsql对象做复审时,发现在一个主存储过程内部调用了其它多个子存储过程,但只执行了其中的第一个子存储过程,Exception捕捉了错误提示SQLERRM is: query has no destination for result data, 后来发现是因为存储过程改写时内部调用子存储过程前加了”call” ,其实用”PERFORM”也没问题,简单记录。
Oracle中存储过程调用其它存储过程
create or replace procedure p1
is
begin
dbms_output.put_line('p1=================');
end;
/
create or replace procedure p2
is
begin
dbms_output.put_line('p2=================');
end;
/
create or replace procedure p3
is
begin
p1;
p2;
end;
/
SQL> exec p1;
p1=================
PL/SQL procedure successfully completed.
SQL> exec p2
p2=================
PL/SQL procedure successfully completed.
SQL> exec p3
p1=================
p2=================
PL/SQL procedure successfully completed.
openGauss调用其它存储过程
MogDB=# CREATE OR REPLACE PROCEDURE p1000()
is
BEGIN
RAISE NOTICE 'p1000=================';
END;
/
MogDB=# CREATE OR REPLACE PROCEDURE p2000()
is
BEGIN
RAISE NOTICE 'p2000=================';
END;
/
MogDB=# CREATE OR REPLACE PROCEDURE p3000()
is
BEGIN
call p1000();
call p2000();
exception
when others then
RAISE notice 'Error SQLERRM is: %',SQLERRM;
END;
/
CREATE PROCEDURE
MogDB=# call p3000();
NOTICE: p1000=================
NOTICE: Error SQLERRM is: query has no destination for result data
p3000
-------
(1 row)
Note:
只执行了第一个procecure, 报错让人摸不到头脑。那执行到了exception部分,把exception去掉直接让他报错。
MogDB=# call p3000(); NOTICE: p1000================= ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function p3000() line 3 at SQL statement
Note
这报错提示了行,但报错对于oracle dba也不是很明显,应该是执行使用perform.
CREATE OR REPLACE PROCEDURE p4001() is BEGIN PERFORM p1000(); PERFORM p2000(); END; / MogDB=# call p4001(); NOTICE: p1000================= NOTICE: p2000================= p4001 ------- (1 row) MogDB=# perform p4001(); ERROR: syntax error at or near "perform"
Note:
在存储过程内部是使用perform调用,可以正常。其实像Oracle一样只写过程名也是正常的,完全多此一举加调用。
CREATE OR REPLACE PROCEDURE p3000() is BEGIN p1000(); p2000(); END; / MogDB=# call p3000(); NOTICE: p1000================= NOTICE: p2000================= p3000 ------- (1 row)
小结:
在Postgresql中调用其它存储过程使用perform或不加调用关键字都是可以的,但不要加call 创建时无提示,而且还不容易发现。