簡體   English   中英

如何在PostgreSQL中聲明和使用臨時表作為游標源?

[英]How to declare and use a temporary table as a cursor source in PostgreSQL?

標准化(主要是2NF和一些3NF表)后,我現在需要類似下面的查詢來上下移動我的表結構以獲得所需的信息。 (PostgreSQL 9.3)

CREATE TEMPORARY TABLE test  AS
With charts_on_date_of_service AS ( 
    SELECT t.service_recid, t.tservice, t.chart_recid           
    FROM  ( select s.recid as service_recid, s.tservice, p.chart_recid
        from doctorservices d                   
        join services s on (s.recid = d.service_recid)      
        join patients p on (p.recid = s.patient_recid)      
        where s.tservice::date = _tservice::date        
        ) as t 
)
select s.recid as service_recid, s.tservice, c.chart_recid, c.tservice as time_of_service
from charts_on_date_of_service  c                   
join patients p on (p.chart_recid = c.chart_recid)          
join services s on (s.patient_recid = p.recid)              
join doctorservices d  on ( d.service_recid = s.recid)          
where s.tservice::date <= _tservice::date               
order by c.chart_recid, s.tservice;                                    

由於涉及到此查詢,我希望不必在plpgsql函數中重復該查詢。 也就是說,我想做類似的事情:

CREATE OR REPLACE FUNCTION test(_tservice timestamp)            
  RETURNS TABLE (service_recid bigint, chart_recid int, tservice timestamp, ct int) AS
$func$ 

DECLARE 

CREATE TEMPORARY TABLE test AS ....   <--THIS FAILS

cur CURSOR FOR
    SELECT t.service_recid, t.tservice, t.chart_recid   
    FROM   test t

BEGIN
      ... some processing commands on the temp table test and cursor cur....
END

我有幾個相關的問題:

  • 在plpgsql中如何“聲明”臨時表?
  • 臨時表可以用作游標的源嗎?
  • 性能會更好嗎?創建一個臨時表並在多個地方使用它,還是在多個地方重新創建相同的查詢?

我似乎找不到Google的答案。 任何幫助或想法是最贊賞的。

您必須使用不同的方法。 在PL / pgSQL內部,任何CREATE語句都不能位於DECLARE部分。 與其他任何語句一樣,它應該在函數主體部分中。 如果可以在動態創建的表上進行迭代,則必須使用未綁定的游標,並且必須在OPEN語句中指定查詢(或者更好的方法是-使用FOR循環):

CREATE OR REPLACE FUNCTION test(a int)
RETURNS TABLE (b int, c int, d int) AS $$
BEGIN
  DROP TABLE IF EXISTS foo; 
  CREATE TEMP TABLE foo(col int);
  INSERT INTO foo SELECT generate_series(1,a);
  FOR b, c, d IN SELECT col, col + 1, col + 2 FROM foo
  LOOP
    RETURN NEXT;
  END LOOP;
END; $$ LANGUAGE plpgsql;

該示例可以工作,但是它非常昂貴,並且僅在必要時才使用此模式。 臨時表很昂貴,如果不需要,請不要使用它(有充分的理由:性能,復雜性,但通常不是必需的)。 T-SQL某些模式未在Postgres中使用,而某些工作則需要不同的思考。 您可以使用數組RETURN NEXTRETURN QUERY語句:

CREATE OR REPLACE FUNCTION test(a int)
RETURNS table (b int, c int, d int) AS $$
BEGIN
  RETURN QUERY SELECT col, col+1, col+2
                  FROM generate_series(1,a)
  RETURN;
END; $$ LANGUAGE plpgsql;

對於類似的瑣碎函數,最好使用SQL語言:

CREATE OR REPLACE FUNCTION test(a int)
RETURNS table (b int, c int, d int) AS $$
  SELECT col, col+1, col+2
     FROM generate_series(1,a)
$$ LANGUAGE sql;

您可以在Postgres中使用數組:

CREATE OR REPLACE FUNCTION test(a int)
RETURNS TABLE (b int, c int, d int) AS $$
DECLARE cols int[];
BEGIN
  cols := ARRAY(SELECT generate_series(1,a));
  RETURN QUERY 
    SELECT col, col + 1, col + 2 
       FROM unnest(cols) g(col);
  RETURN;
END; $$ LANGUAGE plpgsql;

暫無
暫無

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

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