首先交代一个概念,在PostgreSQL中,函数、存储过程都是一回事,创建语法都是create function。之所以本文标题使用存储过程的叫法,是为了方便其他数据库的使用者容易理解。
先来看看PostgreSQL默认支持的创建数据库函数的写法,如:

-- 把系统生成的uuid中的-替换成_
create function uuid()
returns text
language sql
as $$
SELECT replace(uuid_generate_v4()::text,'-','_');
$$;

注意其中的language关键字,后面指明了该数据库函数所使用的语言,上面这个函数很简单,用纯SQL就能搞定,更多的时候,我们遇到的会复杂很多,就得用上过程化的SQL,也就是plpgsql(类似Oracle中的PL/SQL),具体可以查看官方文档plpgsql
不过今天的主题不是plpgsql,而是plv8——基于V8引擎的在PostgreSQL中运行的过程化语言,其实就是用JavaScriptPostgreSQL中写数据库函数。
那么为什么要用Javascript来写数据库函数呢?在我看来,至少有下面几个好处:

  1. 熟悉的配方,熟悉的味道。JavaScript作为Web世界的一等公民,其教众众多。能用JavaScript来实现高级的数据库开发,可以大幅拉低数据库的学习曲线,进而降低人力成本
  2. 获得SQL世界本身不具备的库函数,像这样:
    还有这样:

    可以极大丰富数据库层面的功能实现,进而影响一个软件的架构设计。
  3. 更快的性能,众所周知Google主推的V8引擎是业界公认的顶尖性能怪兽。有它配合你的数据库使用真是如虎添翼。尤其是在业务系统的开发采用了并不是以性能为卖点的语言时(比如RubyPHP),把部分业务逻辑通过JavaScript在数据库中重构一边,说不定会有意想不到的效果。这比伤筋动骨地单纯在业务层摸索改进要容易得多。

说了这么多,怎么才能在PostgreSQL中用上JavaScript呢?

一切就绪之后,按照官方文档上举例的,先来个带for循环和生成JSON的耍耍,SQL如下:

CREATE FUNCTION plv8_test(keys TEXT[], vals TEXT[]) RETURNS JSON AS $$
var o = {};
for(var i=0; i<keys.length; i++){
o[keys[i]] = vals[i];
}
return o;
$$ LANGUAGE plv8 IMMUTABLE STRICT;

尝试调用刚刚创建的plv8_test函数:

SELECT plv8_test(ARRAY['name', 'age'], ARRAY['Tom', '29']);

获得结果
是不是美妙极了?☺️

放大招

是不是看了上面的介绍,有点心痒难耐了。🤪其实PostgreSQL在内部可调用的过程化语言的支持远不仅于此。你完全可以用你心爱的PythonJavaPHP甚至是RLua从事PostgreSQL中的数据库函数开发。
尤其是PythonJava,这两个语言几乎在PostgreSQLPL环境下有最大的权限空间。想象这样一个场景:
一个别人做的项目(你没有源码,或者有源码跟没有也没啥区别),领导说要加个需求,当一个数据到达某种阀值时,要发短信给一个人(比如考试成绩低于60的时候,发个短信给学生家长)。这个时候,你不需要再打开开发环境,在别人的代码里面流离失所,久久不能自拔。你需要做的,就是打开这个项目的PostgreSQL(谢天谢地,它用了世界上最先进的开源数据库,尽管它的代码跟翔没什么区别),然后用JavaPostgreSQL中写个数据库函数(请求一个短信网关的http接口或者别的什么东西),最后套一个触发器(3行SQL)就什么都完成了。
这画面太美,我不敢想象啊,哈哈。