你可能想了解:PostgreSQL的Function和Procedure是一个东西吗?有什么区别?分别用于什么场景?如何更好的理解与记忆?有没有什么注意事项?
函数(Function)和存储过程(Stored Procedure)都是数据库中的可重用代码块,用于执行特定的任务。
函数是一段预编译的代码,接受输入参数并返回一个值。函数可以是内置的系统函数,也可以是用户自定义的函数。
函数主要用于计算和返回一个值,而不是执行一系列的SQL语句。它可以在SELECT语句、WHERE子句、ORDER BY子句等中使用。
函数通常在SQL语句中嵌套使用,可以用于计算列值、过滤数据等。
一般情况下,函数不包含事务控制语句,因为它们的目标是计算而不是执行修改数据库结构的操作。
CREATE [ OR REPLACE ] FUNCTION
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
[ RETURNS rettype
| RETURNS TABLE ( column_name column_type [, ...] ) ]
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| WINDOW
| { IMMUTABLE | STABLE | VOLATILE }
| [ NOT ] LEAKPROOF
| { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
| { [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER }
| PARALLEL { UNSAFE | RESTRICTED | SAFE }
| COST execution_cost
| ROWS result_rows
| SUPPORT support_function
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| AS 'definition'
| AS 'obj_file', 'link_symbol'
| sql_body
} ...
-- 简单点,常用结构
CREATE OR REPLACE FUNCTION FUNCTION_NAME(IN PARA1 INT,INOUT PARA2 INT, OUT PARA3)
RETURNS [TYPE|RECORD] LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
[RETURN TYPE]
END;
$$;
argmode:IN、INOUT、OUT(其中IN类参数类型可以将IN省略不写)
RETURNS TYPE + return xxx 按标准方式处理即可
CREATE OR REPLACE FUNCTION f01(IN a INT,IN b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
return a+b;
END;
$$;
select f01(1,2);
FUNCTION的sql_body中不能出现return行,否则报错;
正确写法
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
-- return b;
END;
$$;
select f01(2,3);
有INOUT、OUT,function内有return会报错
--ERROR: RETURN cannot have a parameter in function with OUT parameters
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
return b;
END;
$$;
有INOUT、OUT,RETURNS TYPE不匹配会报错
--ERROR: function result type must be integer because of OUT parameters
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS VARCHAR
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
END;
$$;
有OUT参数时,调用时OUT参数位不需要输入信息的,否则报错-
-- HINT: No function matches the given name and argument types. You might need to add explicit type casts.
CREATE OR REPLACE FUNCTION f01(IN a INT,OUT b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
END;
$$;
select f01(2,3);
有INOUT参数时,INOUT参数位必须输入信息,否则报错
-- HINT: No function matches the given name and argument types. You might need to add explicit type casts.
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
END;
$$;
select f01(2);
正确写法
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT,OUT c INT) RETURNS record
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
c := b*b;
END;
$$;
select f01(1,2);
未调整为RETURNS record,将会报错
--ERROR: function result type must be record because of OUT parameters
CREATE OR REPLACE FUNCTION f01(IN a INT,INOUT b INT,OUT c INT) RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
c := b*b;
END;
$$;
多INOUT、OUT参数其它错误与1个INOUT、OUT基本一致,不再举例。
存储过程是一组预编译的SQL语句集,被保存在数据库中,可以在需要时调用执行。存储过程通常由数据库管理员或有特殊权限的用户创建。
存储过程主要用于封装和执行一系列的SQL语句,以完成特定的任务。它可以接受参数,并可以包含条件逻辑、循环等程序控制结构。
存储过程可以被应用程序或其他存储过程调用。一旦创建,它们可以在数据库中被重复使用,提高了代码的可维护性和可重用性。
存储过程可以包含事务控制语句,允许进行复杂的事务处理。
CREATE [ OR REPLACE ] PROCEDURE
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| AS 'definition'
| AS 'obj_file', 'link_symbol'
| sql_body
} ...
-- 简单点,常用结构
CREATE OR REPLACE PROCEDURE PROCEDURE_NAME(IN/INOUT PARA1,...)
AS $$
Declare
BEGIN
END;
$$ Language plpgsql;
基本用法与Function一致,只是Procedure参数中不能使用OUT类型,且不能使用Returns返回数据。
CREATE OR REPLACE PROCEDURE p01(IN a INT, INOUT b INT, INOUT c INT) Language plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
c := b*b;
END;
$$;
call p01(2,3,4);
如果使用OUT参数将报错
--ERROR: procedures cannot have OUT arguments
--HINT: INOUT arguments are permitted.
CREATE OR REPLACE PROCEDURE p01(IN a INT, INOUT b INT, OUT c INT) Language plpgsql
AS $$
DECLARE
BEGIN
b := a+b;
c := b*b;
END;
$$;
函数和存储过程是否都可以执行DDL?
答案是:在PG中都可以
执行,不过函数一般用来计算结果,最好不要夹带DDL语句;
CREATE OR REPLACE FUNCTION f01() RETURNS VOID Language plpgsql
AS $$
DECLARE
BEGIN
CREATE TABLE IF NOT EXISTS t1(id int);
DROP TABLE t1;
END;
$$;
select f01();
CREATE OR REPLACE PROCEDURE p01() Language plpgsql
AS $$
DECLARE
BEGIN
CREATE TABLE IF NOT EXISTS t1(id int);
DROP TABLE t1;
END;
$$;
call p01();
为什么说PG中 函数 与 存储过程 广义上可以理解为一个东西?
我们来看一个报错,通过报错提示我们发现,函数与存储过程在报错中都被叫做function
。
CREATE OR REPLACE FUNCTION f01() RETURNS VOID Language plpgsql
AS $$
DECLARE
BEGIN
-- 不存在这张表,会报错;
DROP TABLE t123;
END;
$$;
select f01();
CREATE OR REPLACE PROCEDURE p01() Language plpgsql
AS $$
DECLARE
BEGIN
-- 不存在这张表,会报错;
DROP TABLE t456;
END;
$$;
call p01();
SQL - CREATE FUNCTION
SQL - CREATE PROCEDURE
Procedures Vs. Functions in PostgreSQL
如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了
【点赞】⭐️⭐️⭐️⭐️⭐️
【关注】⭐️⭐️⭐️⭐️⭐️
【收藏】⭐️⭐️⭐️⭐️⭐️
Thanks for watching.
–Kenny