在 Postgresql 中创建一个多列作为参数的函数
Create a function with multiple columns as arguments in Postgresql
我正在尝试创建一个函数,它接受一个 table 和可变数量的列作为参数,然后 returns 一个 table 没有在所有行上都有重复的行那些专栏。我试图弄清楚如何将可变数量的列作为参数,并且我收集到我可能需要一个 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;
举个例子,如果我有一个像这样的 table:
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
你无法通过简单的 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 注入。
编辑:有关具有动态 return 类型的函数的很好解释,请参阅欧文的回答 here。
我正在尝试创建一个函数,它接受一个 table 和可变数量的列作为参数,然后 returns 一个 table 没有在所有行上都有重复的行那些专栏。我试图弄清楚如何将可变数量的列作为参数,并且我收集到我可能需要一个 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;
举个例子,如果我有一个像这样的 table:
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
你无法通过简单的 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 注入。
编辑:有关具有动态 return 类型的函数的很好解释,请参阅欧文的回答 here。