PostgreSQL 8.4及以上版,新增特性中包括支持 VARIADIC 函数, 是指函数支持不定数量的参数,只要靠后的参数的数据类型(除数组外)一致即可识别。在函数内部,这些一致类型的参数,会被当作一个数组来处理。但如果其中有一个类型和前后不一致,就无法支持。
这个特性可以让处理集合类的参数变得更灵活。
应用实例:商品表和标签(Tag)的多对多关系。存储过程如下:
CREATE OR REPLACE FUNCTION goods_tag_add(a_goods_id int, VARIADIC a_tags text[], OUT t_id INT8)
RETURNS SETOF INT8 AS $$
DECLARE
t_rec record;
i int4;
BEGIN
FOR i IN SELECT generate_subscripts(a_tags, 1) LOOP
-- RAISE NOTICE 'tag: %', a_tags[i]; // debug
SELECT id FROM goods_tag WHERE name = a_tags[i] INTO t_rec;
IF FOUND THEN
t_id := t_rec.id;
ELSE
INSERT INTO goods_tag(name)
VALUES (a_tags[i]);
t_id := CURRVAL('goods_tag_id_seq');
END IF;
IF NOT EXISTS(SELECT created FROM goods_tag_map
WHERE goods_id = a_goods_id AND tag_id = t_id) THEN
INSERT INTO goods_tag_map(goods_id, tag_id)
VALUES(a_goods_id, t_id);
END IF;
RETURN NEXT;
END LOOP;
RETURN;
END;
$$ LANGUAGE 'plpgsql';
调用此函数的PHP代码示例:
$goods_id = 1; // 目标(这里以商品为例)ID,整数类型
$tags = array('上衣', '夏季', '休闲'); // 不定数量的 tag 文字
$tag_ids = Da_Wrapper::getAll(DB_NS,
"SELECT goods_tag_add(?,".implode(',',str_split(str_repeat('?', count($tags)))).")",
array_merge(array($goods_id),$tags));
// Da_Wrapper 类是对PDO的封装,DB_NS 是连接串定义,SQL语句之所以这样写是不管 $tags元素有多少,都可以拼成参数传给存储过程
* PostgreSQL 约定了 函数参数最多为100个,如果确实超过这个数,可以分拆成多次调用。不过,多数应用里应该没这么多吧。
参考:
What is new in PostgreSQL 8.4
Waiting for 8.4 – variadic functions
在PostgreSQL中模拟MySQL的ORDER BY FIELD()
RSS