簡體   English   中英

動態生成變量並在plpgsql函數的查詢中使用它

[英]Dynamically build a variable and use it in a query in a plpgsql function

我在Postgres 9.6 DB中有一個函數,我想根據收到的輸入動態地設置要累積的月份。

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函數中做到這一點。
傳遞“ 11月”時不返回任何數據,我確實獲得“ 10月”的數據。

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

我想動態地構建變量以使其累積,因此當傳遞“ 11月”時,我希望查詢使用:

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

您在這里不需要動態變量-改為使用普通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 

如果p_month唯一允許的輸入是“ October”或“ November”,則可以進一步簡化:

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;

但這是一個奇怪的用例。 首先,只是在豬上塗口紅。

不要將yearmonth另存為testtable integertext 請使用一個date列(4個字節)代替月份。 (更快,更干凈。)在您的情況下,日期的天部分與您無關。 只需允許任何一天,然后忽略它或在表中將日期強制為“ 1”即可:

CREATE TABLE testtable (
   fiscal_month date NOT NULL CHECK (EXTRACT('day' FROM fiscal_month) = 1)
   --  more columns
);

添加的CHECK約束是可選的。
要像以前一樣查看數據,請添加一個VIEW

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;

現在,您的功能既簡單又快速:

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;

實際上 ,這是累積的,從某種意義上說,您可以在十月之后的任何月份(在示例中僅剩十二月)通過。

使用make_date() (Postgres 9.4或更高版本)可以根據integer輸入方便地構建日期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM