动态构建变量并在plpgsql函数的查询中使用它

时间:2017-06-12 19:29:02

标签: sql postgresql date plpgsql

我在Postgres 9.6数据库中有一个函数,我想根据收到的输入动态设置月累计。

CREATE OR REPLACE FUNCTION test(
    IN p_fiscal_year integer,
    IN p_month text,
    IN pid integer,
    IN fid integer)   RETURNS TABLE(col1 text , col2 text, col3 text, col4 text, col5 text)

AS $BODY$
DECLARE user_sel_month TEXT;
BEGIN

 CASE WHEN p_month ='October' Then 'October'         WHEN p_month = 'November' Then '(' ||'October' || ',' || 'November' || ')'     END;
 RETURN QUERY select 
                col1,
                col2,
                col3,
                col4,
                col5 
                from testtable 
                WHERE testtable.year = p_fiscal_year  
                AND trim(testtable.month) IN (user_sel_month) 
                AND testtable.pgmid = pid 
                and testtable.fun_id = fid )

但我无法在Postgres功能中执行此操作 传递给'十一月'时它没有返回任何数据,我确实获得了'十月'的数据。

select * from test(2016,'November',11,6);

我想动态构建变量以使其累积,因此当“11月”传递时我希望查询使用:

WHERE trim(testtable.month) IN ('October','November')

2 个答案:

答案 0 :(得分:0)

这里不需要动态变量 - 使用普通的SQL - 会更便宜。

尝试改变:

AND trim(testtable.month) IN (user_sel_month) 

简单:

AND CASE 
  WHEN p_month = 'October' Then trim(testtable.month) in ('October')         
  WHEN p_month = 'November' Then trim(testtable.month) in ('October','November') 
END 

答案 1 :(得分:0)

如果p_month唯一允许的输入是'十月'或者' 11月',您可以进一步简化:

SELECT col1, col2, col3, col4, col5 
FROM   testtable
WHERE  year = p_fiscal_year  
AND   (trim(month) = 'October'
    OR trim(month) = 'November' AND p_month = 'November')
AND    pgmid = pid 
AND    fun_id = fid;

但这是一个奇怪的用例。而且它只是在口红上涂上口红。

请勿在{{1​​}}中将yearmonth保存为integertext。而是使用单个testtable列(4个字节)代替月份。 (更快,更清洁。)日期的日期部分与您的情况无关。只需允许任何一天,忽略它或强制执行日期' 1'在表中:

date

添加的CREATE TABLE testtable ( fiscal_month date NOT NULL CHECK (EXTRACT('day' FROM fiscal_month) = 1) -- more columns ); 约束是可选的 要像以前一样查看数据,请添加VIEW

CHECK

您的功能现在简单快捷:

CREATE VIEW test_table_pretty AS 
SELECT EXTRACT('year' FROM fiscal_month)::int AS year
     , to_char(fiscal_month, 'Month')         AS month
       --  more columns
FROM   testtable;

这是实际累积,因为你可以在10月之后的任何月份通过(在你的例子中只剩下12月)。

使用make_date()(Postgres 9.4或更高版本)方便地从CREATE OR REPLACE FUNCTION test( p_fiscal_year integer, p_month integer, -- integer! pid integer, fid integer) RETURNS TABLE(col1 text, col2 text, col3 text, col4 text, col5 text) AS $func$ SELECT t.col1, t.col2, t.col3, t.col4, t.col5 FROM testtable t WHERE fiscal_month >= make_date(p_fiscal_year, 10 , 1) -- hard coded Oct. AND fiscal_month < make_date(p_fiscal_year, p_month + 1, 1) AND t.pgmid = pid AND t.fun_id = fid; $func$ LANGUAGE sql; 输入建立日期。