【问题标题】:Saving a query result into a temp table with unknown number of columns将查询结果保存到列数未知的临时表中
【发布时间】:2021-11-09 13:40:46
【问题描述】:

我正在尝试在 plpgsql 中创建以下函数:

CREATE OR REPLACE FUNCTION pg_temp.select_all(query text)
RETURNS VOID AS $$
DECLARE
    schemasT RECORD;
BEGIN
    FOR schemasT IN (
        SELECT schema_name
        FROM information_schema.schemata
        WHERE schema_name IN (
            SELECT login 
            FROM cdu.nc_tenant
        )
    ) LOOP
        SET SEARCH PATH TO schemasT;
    
        EXECUTE query INTO something;
    END LOOP;
END; $$
LANGUAGE plpgsql;

因此,任何传入函数的查询都会运行到所有可用的模式中并返回查询结果。使用该函数将是这样的:

pg_temp.select_all('SELECT count(1) FROM sku')

会返回:

Schema count
Schema1 58
Schema2 42

另一个例子是:

pg_temp.select_all('SELECT * FROM cdu.nc_tenant_variables where variable = ''theme''')

会返回:

Schema variable value
Schema1 theme dark
Schema2 theme light

为什么?

有时我需要跨架构查询事物,我正在寻找一种更好的方法来执行此操作而不是这样做:

SELECT 'schema1' AS schema, count(1) FROM schema1.sku
UNION ALL
SELECT 'schema2' AS schema, count(1) FROM schema2.sku
UNION ALL
SELECT 'schema3' AS schema, count(1) FROM schema3.sku;

【问题讨论】:

  • 您可以创建报表架构模型,然后您可以从现有架构中填充此模型。然后您可以在该报告架构中进行选择。

标签: postgresql plpgsql


【解决方案1】:

我已经让它工作了,但是它返回一个 JSON 对象而不是一个普通的表:

DROP FUNCTION pg_temp.select_all;
CREATE OR REPLACE FUNCTION pg_temp.select_all(query TEXT, whole int DEFAULT 0)
RETURNS table (j json) AS $$
DECLARE
    schemasT RECORD;
    counter int := 1;
    test RECORD;
BEGIN
    DROP TABLE IF EXISTS resultquery;

    FOR schemasT IN (
        SELECT schema_name
        FROM information_schema.schemata
        WHERE schema_name IN (
            SELECT login 
            FROM cdu.nc_tenant
        )
    ) LOOP
        EXECUTE format('SET SEARCH_PATH TO %I', schemasT.schema_name);
        
        IF counter = 1 THEN
            EXECUTE 'CREATE TEMP TABLE resultquery AS '|| query;
            ALTER TABLE pg_temp.resultquery ADD COLUMN tenant varchar;
            TRUNCATE TABLE resultquery;
        END IF;
    
        DROP TABLE IF EXISTS temptemp;
        EXECUTE 'CREATE TEMP TABLE temptemp AS '|| query;
        ALTER TABLE pg_temp.temptemp ADD COLUMN tenant varchar;
        
        UPDATE pg_temp.temptemp SET tenant = schemasT.schema_name;
        EXECUTE 'INSERT INTO pg_temp.resultquery SELECT * FROM pg_temp.temptemp';
    
        counter := counter + 1;
    END LOOP;
    
    IF whole = 0 THEN
        RETURN QUERY  SELECT to_json(a) FROM (SELECT * FROM pg_temp.resultquery) a;
    ELSE 
        RETURN QUERY  SELECT json_agg(a) FROM (SELECT * FROM pg_temp.resultquery) a;
    END IF;
END; $$
LANGUAGE plpgsql;

使用函数:

SELECT pg_temp.select_all('select count(1) from sku', 1);

返回一个单行 JSON 对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 2015-11-12
    相关资源
    最近更新 更多