我的表格每年都包含相同类型的数据,但收集的数据略有不同,因为它们可能没有相同的字段。尝试在PL/PgSQL中创建动态查询字符串以在PostgreSQL中创建DRY函数9.6
d_abc_2016
d_def_2016
d_ghi_2016
d_jkl_2016
有用于每个表中的某些常数:company_id
,employee_id
,salary
。
但是,每个人可能有也可能没有这些字段用于计算总激励:bonus
,commission
,cash_incentives
。还有很多,但只是以这些为例。全部numeric
我应该注意,在这一点上,用户只有能力运行SELECT
报表。
我希望能够做的是这样的:
- 给用户在
SELECT
调用,并指定自己的领域,除了通话 - 传递表名的能力正在使用进入功能在条件逻辑用于确定查询字符串应该如何构造,为最终
total_incentives
计算除了传递整个表,这样一吨的参数没有被传递到函数
基本上这:
SELECT employee_id, salary, total_incentives(t, 'd_abc_2016')
FROM d_abc_2016 t;
所以被称为将计算total_incentives
这是numeric
该功能employee_id
,也表明他们salary
。但用户可能会选择添加其他字段来查看。
对于函数,因为total_incentives
函数中使用的字段会因表而异,所以我需要创建逻辑来动态构造查询字符串。
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS numeric AS
$$
DECLARE
-- table name lower case in case user typed wrong
tbl varchar(255) := lower($2;
-- parse out the table code to use in conditional logic
tbl_code varchar(255) := split_part(survey, '_', 2);
-- the starting point if the query string
base_calc varchar(255) := 'salary + '
-- query string
query_string varchar(255);
-- have to declare this to put computation INTO
total_incentives_calc numeric;
BEGIN
IF tbl_code = 'abc' THEN
query_string := base_calc || 'bonus';
ELSIF tbl_code = 'def' THEN
query_string := base_calc || 'bonus + commission';
ELSIF tbl_code = 'ghi' THEN
-- etc...
END IF;
EXECUTE format('SELECT $1 FROM %I', tbl)
INTO total_incentives_calc
USING query_string;
RETURN total_incentives_calc;
END;
$$
LANGUAGE plpgsql;
这导致:
ERROR: invalid input syntax for type numeric: "salary + bonus"
CONTEXT: PL/pgSQL function total_incentives(anyelement,text) line 16 at EXECUTE
因为它应该返回一组numeric
值。将其更改为以下内容:
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS SETOF numeric AS
$$
...
RETURN;
获取相同的错误。
好吧,也许它是一个表格,它试图返回。
CREATE OR REPLACE FUNCTION total_incentives(ANYELEMENT, t text)
RETURNS TABLE(tot_inc numeric) AS
$$
...
获取相同的错误。
真的,任何变化都会产生这样的结果。所以真的不知道如何让这个工作。
看RESULT QUERY
,RESULT NEXT
或RESULT QUERY EXECUTE
。
https://www.postgresql.org/docs/9.6/static/plpgsql-control-structures.html
RESULT QUERY
将无法工作,因为它从我可以告诉一个硬编码查询,不会在变量取。
RESULT NEXT
遍历每个记录,我不认为会适合我的需求和看起来这将是很慢...它需要从我可以告诉一个硬编码查询。
RESULT QUERY EXECUTE
听起来很有希望。
-- EXECUTE format('SELECT $1 FROM %I', tbl)
-- INTO total_incentives_calc
-- USING query_string;
RETURN QUERY
EXECUTE format('SELECT $1 FROM %I', tbl)
USING query_string;
并获得:
ERROR: structure of query does not match function result type
DETAIL: Returned type character varying does not match expected type numeric in column 1.
CONTEXT: PL/pgSQL function total_incentives(anyelement,text) line 20 at RETURN QUERY
应该返回numeric
。
最后,我可以得到这个工作,但它不会干。我宁愿不使用重复代码为每个表创建一堆单独的函数。大部分时间我都看到了工作的例子有一个函数整个查询,被称为像这样:
SELECT total_incentives(d_abc_2016, 'd_abc_2016');
因此,任何附加列必须在功能作为指定:鉴于
EXECUTE format('SELECT employee_id...)
用户将只能在查询中运行SELECT
,这实在不是一种选择。他们需要指定他们希望在查询中看到的任何附加列。
我已经发布了一个类似的问题,但被告知它不清楚,所以希望这个更长的版本将更清楚地解释我正在尝试做什么。
很酷,得到了查询运行。谢谢您的帮助!现在整理并防止它将返回的记录数量乘以总记录数量。 – sockpuppet