温馨提示:本文中部分描述仅为个人理解,存在描述偏差或错误,内容仅供参考
某些其它数据库系统所定义活动数据库规则,通常是存储过程和触发器。在PostgreSQL中,这些规则可以通过函数和触发器来实现。
PostgreSQL函数也称为PostgreSQL存储过程。
首先我们简要介绍函数这个概念。PostgreSQL存储过程具有以下优点
减少应用与数据库服务器通信开销,提升网络性能。在某些大型业务系统中,大多需要使用多个存储过程等,存储过程等降低网络通信开销就具有明显优势
存储过程存于数据库服务器中,首次被调用后即被编译,再调用时无需二次编译,直接被服务器执行,可以提高性能
存储过程可以重复使用,能够减少数据库开发人员和管理人员工作量
保护数据库元信息。如果应用程序直接使用SQL语句查询数据库,会将数据库表结构等信息暴露给应用程序,不利于数据库访问控制
细粒度权限管理。直接控制用户调用存储过程,存储过程可以增强数据安全性
将业务实现与应用程序解耦。当业务需求更新时,只需更新存储过程,无需要变动应用程序
可以通过其它语言并可及其它系统交互。PostgreSQL官方支持PL/pgSQL,PL/Tcl,PL/Perl,PL/Python,PL/Java,PL/PHP, PL/R,PL/Ruby,PL/Scheme,PL/sh等(编程)语言。
当然,PostgreSQL存储过程也有调试不便和可移植性差等缺点。
变更存储过程时,应用程序内需要同步加以修改,不同数据库的存储过程定义方式不同,支持的语言及语法不同,存在一定移植成本。
存储过程可选声明指定数据库,函数主体functionbodyvariablename名称可为空。返回类型returndatatype 可以是复合型数据。中括号部分为可选部分。|为二选一条件选择,输入结果要和指定返回结果数据类型相同,所有关键字都不区分大小写,标识符被隐含地转换成小写字符,除非使用英文双引号""。
---不完整存储过程示例代码
CREATE OR REPLACE FUNCTION functionname (arguments,[optionalparameters],[...])
RETURNS returndatatype AS $functionbodyvariablename$
[DECLARE
declarations]
BEGIN
funcation body
END;
RETURN functionbodyvariablename | value,
LANGUAGE plsupportlanguage;
下面贴出1个简单示例函数
CREATE OR REPLACE FUNCTION add(a INTEGER, b NUMERIC)
RETURNS NUMERIC
AS $$
SELECT a+b;
$$ LANGUAGE SQL;
下面我们演示一个完整示例。我们以余额转出为例编写代码
---创建余额表
create table accounts(owner text,balance numeric);
--插入两条测试数据
insert into accounts values('Bob',100);
insert into accounts values('Mary',200);
select owner,balance from accounts;
---
---查询结果
postgres=# \c test
您现在已经连接到数据库 "test",用户 "postgres".
test=# select owner,balance from accounts;
owner | balance
-------+---------
Mary | 256.00
Bob | 44.00
(2 行记录)
test=#
创建函数
---余额函数(存储过程)
CREATE OR REPLACE FUNCTION transfer(
i_payer TEXT,
i_recipient TEXT,
i_amount NUMERIC(15,2))
RETURNS TEXT
AS
$$
DECLARE
payer_bal NUMERIC;
BEGIN
SELECT balance INTO payer_bal
FROM accounts
WHERE "owner" =i_payer FOR UPDATE;
IF NOT FOUND THEN RETURN '转出账号不存在,请检查!';
END IF;
IF payer_bal <i_amount THEN RETURN '账号余额不足!';
END IF;
UPDATE accounts
SET balance = balance + i_amount
WHERE "owner" =i_recipient;
IF NOT FOUND THEN RETURN '转入账号不存在,请检查!';
END IF;
UPDATE accounts
SET balance =balance - i_amount
WHERE "owner" =i_payer;
RETURN '转账操作成功!';
END;
$$LANGUAGE plpgsql;
执行一个册数查询。
---转出余额14.00
test=# SELECT * FROM transfer('Bob','Mary',14.00);
transfer
----------------
转账操作成功!
(1 行记录)
test=#
再次执行查询余额操作。
test=# select owner,balance from accounts;
owner | balance
-------+---------
Mary | 214.00
Bob | 86.00
(2 行记录)
test=#
如果我们输入账号有问题呢?比如转账人信息错误,这里假设转账人是Green,执行操作
test=# SELECT * FROM transfer('Green','Mary',14.00);
transfer
--------------------------
转出账号不存在,请检查!
(1 行记录)
--转入账号不存在
test=# SELECT * FROM transfer('Bob','Bill',14.00);
transfer
--------------------------
转入账号不存在,请检查!
(1 行记录)
test=#
---余额不足
test=# SELECT * FROM transfer('Bob','Mary',10000.00);
transfer
----------------
账号余额不足!
(1 行记录)
test=#
多个函数可以共用一个名词,但需要指定不同参数用以区分不同函数,也就是函数可以重载。
删除函数
---删除函数列表
DROP FUNCTION transfer(i_payer TEXT,i_recipient TEXT,i_amount NUMERIC(15,2));
PostgreSQL函数支持重载,因此在删除函数时,必须指定参数列表。
参考文献与链接
http://www.cnblogs.com/lottu/p/7404722.html
http://www.jasongj.com/2015/12/27/SQL4_存储过程_Store Procedure/
http://panyongzheng.iteye.com/blog/2194815
PostgreSQL修炼之道 从小工到专家
注意:第二个参考链接中文和空格,建议复制地址到浏览器访问
来源:oschina
链接:https://my.oschina.net/u/1011130/blog/1558144