【问题标题】:Create a function with multiple columns as arguments in Postgresql在 Postgresql 中创建一个具有多列作为参数的函数
【发布时间】:2017-05-16 16:05:39
【问题描述】:

我正在尝试创建一个函数,该函数将一个表和可变数量的列作为参数,然后返回一个没有在所有这些列上有重复的行的表。我试图弄清楚如何将可变数量的列作为参数,并且我已经收集到我可能需要一个 VARIADIC 参数,但我不确定如何实现它。到目前为止我所拥有的:

CREATE FUNCTION remove_duplicates(orig_table, VARIADIC sel_columns column)
RETURNS table AS $$
    SELECT * FROM 
        (SELECT *,
            count(*) over (partition by sel_columns) AS count
        FROM orig_table)
    WHERE count = 1;
$$ LANGUAGE SQL;

例如,如果我有一个这样的表:

cola | colb | colc
-------------------
a    | b    | 1
a    | b    | 2
a    | c    | 3
a    | d    | 4

我想运行SELECT * FROM remove_duplicates(mytable, cola, colb) 并得到这个结果:

cola | colb | colc
-------------------
a    | c    | 3
a    | d    | 4

感谢您的帮助。我正在使用 postgresql 9.4.9

【问题讨论】:

    标签: postgresql window-functions variadic-functions


    【解决方案1】:

    您无法通过简单的 SQL 函数获得所需的内容,您需要过程语言的强大功能。一个可能的解决方案是:

    CREATE OR REPLACE FUNCTION remove_duplicates(orig_table anyelement, VARIADIC sel_columns text[])
    RETURNS SETOF anyelement AS $$
    DECLARE
        orig_table_columns TEXT;
    BEGIN
        SELECT array_to_string(array_agg(quote_ident(column_name)),',') INTO orig_table_columns FROM information_schema.columns WHERE table_name = CAST(pg_typeof(orig_table) AS TEXT);
        RETURN QUERY EXECUTE 'SELECT ' || orig_table_columns || ' FROM '
            || '(SELECT *, '
            || '    count(*) over (partition by ' || array_to_string(sel_columns, ',') || ') AS count '
            || 'FROM ' || pg_typeof(orig_table) || ') AS tmp '
            || ' WHERE count = 1 ';
    END
    $$ LANGUAGE PLPGSQL;
    
    SELECT * FROM remove_duplicates(NULL::tests, 'cola', 'colb');
    

    不要忘记进行更改以避免 SQL 注入。

    编辑:有关具有动态返回类型的函数的很好解释,请参阅 Erwin 的回答 here

    【讨论】:

    • 谢谢,这行得通!我有点困惑为什么有必要将orig_table 输入anyelement,以及为什么表参数必须是NULL,它被强制转换为特定的表。
    • @AmadouKone anyelement 因为我们正在利用Polymorphic Types。强制转换为 null 只是传递所需表类型的技巧。
    • @AmadouKone 另请注意,返回类型也是 anyelement。这使得函数具有多态性。
    猜你喜欢
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多