簡體   English   中英

Postgresql 函數返回多個選擇語句

[英]Postgresql function return multiple select statements

你們中的任何人都可以告訴我如何解決這個問題:

CREATE OR REPLACE FUNCTION name()
  RETURNS ????? AS
$func$
BEGIN

 SELECT * FROM tbl_a a;

 SELECT * FROM tbl_b b;

END
$func$ LANGUAGE plpgsql;

兩個表具有不同的結構。

您可以使用游標,但我很難想象為什么您需要這樣的功能。

CREATE OR REPLACE FUNCTION my_multiselect(refcursor, refcursor) RETURNS VOID AS
  $func$
BEGIN
  OPEN $1 FOR SELECT * FROM information_schema.routines;
  OPEN $2 FOR SELECT * FROM information_schema.sequences;
END
$func$ LANGUAGE plpgsql;

BEGIN;
SELECT my_multiselect('first_cursor_to_routines', 'second_cursor_to_sequences');
FETCH ALL IN first_cursor_to_routines;
FETCH ALL IN second_cursor_to_sequences;
COMMIT;

我不確定你在做什么,但聽起來你只想返回這些不同結果集的聯合。 您可以使用動態查詢來做到這一點。 我正在使用 Postgres 9.4。

CREATE OR REPLACE FUNCTION make_query(IN p_tables text[])
  RETURNS void AS
$BODY$
DECLARE
    v_qry text;
    v_cols text;
    v_types text;
    v_as text;
BEGIN
EXECUTE format('
    WITH sub AS (
        SELECT 
            table_name, 
            column_name, 
            data_type 
        FROM 
            information_schema.columns 
        WHERE 
            table_name = ANY(%L)
        ORDER BY 
            table_name, 
            ordinal_position)
    ,sub2 AS(
        SELECT
            DISTINCT ON (column_name, data_type)
            column_name || '' '' || data_type AS def
        FROM
            sub
    )
    SELECT
        string_agg(def, '','')
    FROM
        sub2;
',
    p_tables
) INTO v_types;

v_qry := '
        CREATE OR REPLACE FUNCTION name()
          RETURNS TABLE(' || v_types || ') AS
        $func$';

FOR i IN 1..array_upper(p_tables, 1)    
LOOP

    v_as := 'tbl' || i;

    EXECUTE format('
        WITH sub AS (
            SELECT 
                table_name, 
                column_name, 
                data_type 
            FROM 
                information_schema.columns 
            WHERE 
                table_name = ANY(%L)
            ORDER BY 
                table_name, 
                ordinal_position)
        ,sub2 AS(
            SELECT
                DISTINCT ON (column_name, data_type)
                CASE WHEN table_name = ''%I'' 
                    THEN %L || ''.'' || column_name 
                    ELSE ''NULL::'' || data_type 
                END AS cols
            FROM
                sub
        )
        SELECT
            string_agg(cols, '','')
        FROM
            sub2;
    ',
        p_tables,
        p_tables[i],
        v_as
    ) INTO v_cols;

    IF i > 1 THEN
        v_qry := v_qry || '
UNION ALL'; 
    END IF;

    v_qry := v_qry || '
SELECT ' || v_cols || ' FROM ' || p_tables[i] || ' AS ' || v_as;

    IF i = array_upper(p_tables, 1) THEN 
        v_qry := v_qry || ';'; 
    END IF;

END LOOP;
v_qry := v_qry || '
$func$ LANGUAGE sql;
';

EXECUTE v_qry;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

抱歉,這里看起來很丑,但這種格式有助於最終產品看起來更好。 如果您EXECUTE v_qry;執行這樣的動態查詢,只需替換EXECUTE v_qry; 使用RAISE INFO 'v_qry: %', v_qry; 並且它會簡單地在消息中打印動態查詢而不執行它,因此您可以查看它一旦執行將執行的操作。

然后使用要顯示的表列表執行 make_query() ,如下所示:

SELECT make_query(ARRAY['tbl_a', 'tbl_b']);

結果是您現在將擁有一個名為 name() 的函數,您可以調用該函數以同時查看兩個表的結果,並且所有聯合詳細信息都已整理完畢:

SELECT * FROM name();

暫無
暫無

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

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