【发布时间】:2011-12-29 16:34:20
【问题描述】:
我有一个执行简单 sql 选择语句的 sql 函数:
CREATE OR REPLACE FUNCTION getStuff(param character varying)
RETURNS SETOF stuff AS
$BODY$
select *
from stuff
where col = $1
$BODY$
LANGUAGE sql;
现在我像这样调用这个函数:
select * from getStuff('hello');
如果我需要使用order by 和limit 子句对结果进行排序和限制,我有哪些选择?
我猜是这样的查询:
select * from getStuff('hello') order by col2 limit 100;
效率不会很高,因为表 stuff 中的所有行都将由函数 getStuff 返回,然后才按限制排序和切片。
但即使我是对的,也没有简单的方法如何通过 sql 语言函数的参数传递顺序。只能传递值,不能传递部分 sql 语句。
另一种选择是以plpgsql 语言创建函数,可以在其中构造查询并通过EXECUTE 执行它。但这也不是一个很好的方法。
那么,还有其他方法可以实现吗? 或者你会选择什么选项?函数外的排序/限制,还是plpgsql?
我使用的是 postgresql 9.1。
编辑
我像这样修改了 CREATE FUNCTION 语句:
CREATE OR REPLACE FUNCTION getStuff(param character varying, orderby character varying)
RETURNS SETOF stuff AS
$BODY$
select t.*
from stuff t
where col = $1
ORDER BY
CASE WHEN $2 = 'parent' THEN t.parent END,
CASE WHEN $2 = 'type' THEN t."type" END,
CASE WHEN $2 = 'title' THEN t.title END
$BODY$
LANGUAGE sql;
这会抛出:
错误:CASE 类型字符不同且整数无法匹配 ŘÁDKA 13:当 $1 = 'parent' THEN t.parent
stuff 表如下所示:
CREATE TABLE stuff
(
id integer serial,
"type" integer NOT NULL,
parent integer,
title character varying(100) NOT NULL,
description text,
CONSTRAINT "pkId" PRIMARY KEY (id),
)
编辑2
我读错了 Dems 代码。我已将其更正为问题。这段代码对我有用。
【问题讨论】:
-
为什么使用 PL/pgSQL 和
EXECUTE不是一个好方法?在性能方面应该不会有太大的不同,是我能想到的唯一解决方案。 -
使用
EXECUTE会慢一些(因为正在进行额外的解析),但我怀疑你是否能够衡量差异。 -
@JoshuaBoshi:猜测性能影响通常不会奏效。
-
好的:-) 随意写一个答案,我会接受,如果没有人会想出其他解决方案:-)
-
@JoshuaBoshi - 您必须针对您的特定情况对其进行测试。数据量、排序字段的允许组合、可用索引、数据碎片等都会产生影响。带有 EXECUTE 的动态 SQL 总是会产生一个执行等于或优于单个基于 CASE 的表达式的计划。但它感觉更混乱,因此更难维护。测试将显示性能差异。我经常重视维护而不是性能如果没有标记性能差异。
标签: sql database postgresql dynamic-sql plpgsql