PostgreSQL:如何在从不可用的外来表中选择数据时忽略它们

uxh89sit  于 2023-03-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(92)

我有一个由多个外部表组成的联合视图(postgres_fdw)。当在此视图中选择时,一些外部服务器可能不可用(没有网络连接),并且选择引发错误。是否可以忽略此类错误并仅返回可用表中的数据?

7lrncoxx

7lrncoxx1#

您可以尝试使用具有错误处理功能的函数或存储过程,沿着所示:

CREATE OR REPLACE FUNCTION union_foreign_tables(ft_info text[][])
RETURNS SETOF record
AS $$
DECLARE
    ft_row text[];
    ft_name text;
    ft_col1 text;
    ft_col2 text;
    ft_col3 text;
    ft_connected boolean;
    first_table boolean := true;
    query text := '';
    i integer;
BEGIN
    FOR i IN 1..array_length(ft_info, 1)
    LOOP
        ft_row := ft_info[i];
        ft_name := ft_row[1];
        ft_col1 := ft_row[2];
        ft_col2 := ft_row[3];
        ft_col3 := ft_row[4];

        ft_connected := true;
        BEGIN
            EXECUTE format('SELECT 1 FROM %I LIMIT 1', ft_name);
        EXCEPTION WHEN others THEN
            ft_connected := false;
        END;

        IF ft_connected THEN
            IF first_table THEN
                query := format('SELECT %I AS col1, %I AS col2, %I AS col3 FROM %I', ft_col1, ft_col2, ft_col3, ft_name);
                first_table := false;
            ELSE
                query := query || format(' UNION SELECT %I AS col1, %I AS col2, %I AS col3 FROM %I', ft_col1, ft_col2, ft_col3, ft_name);
            END IF;
        END IF;
    END LOOP;

    IF query <> '' THEN
        RETURN QUERY EXECUTE query;
    END IF;
END;
$$ LANGUAGE plpgsql;

请注意,由于我不知道当前视图查询是什么样子的,我已经允许多个表和每个表的不同列名序列作为数组的数组传递给该函数:

SELECT union_foreign_tables(ARRAY[
    ARRAY['foreign_table1', 'col1', 'col2', 'col3'],
    ARRAY['foreign_table2', 'col1a', 'col2a', 'col3a'],
    ARRAY['foreign_table3', 'col1b', 'col2b', 'col3b']
]);

参见单元测试:https://dbfiddle.uk/yBRur0Jr(邮政编码15)
注:如果数据量非常大,则使用过程可能更适合。

beq87vna

beq87vna2#

没有一种机制允许视图使用纯SQL忽略丢失的外部表。由于网络连接问题而无法访问的外部表与由于其所在的存储不可用而无法访问的表没有任何不同。默默地忽略无法访问的表似乎不合逻辑。人们如何知道数据丢失?由于表为空而缺少数据t等同于由于表格不可用而缺乏数据。
如果您坚持静默地忽略不可用的表,那么您可以创建表函数,在异常发生时返回查询外部表的结果或空结果集。然后您的视图可以使用这些函数的结果,而不是直接查询外部表。可以这样做并不意味着应该这样做。

相关问题