PL/pgSQL 整数数组的函数语法
PL/pgSQL function syntax with integer arrays
我正在尝试启动一个 SQL 函数,以便我可以收集我不希望在另一个查询中使用的零件 ID 列表。我已经尝试使用 PGAdmin 的函数构建器来开始,但我有一个语法错误,所以它不会创建函数。有人可以告诉我我在这里做错了什么吗?一旦我可以启动该功能,我想我就可以解决剩下的问题了。只需要弄清楚正确的声明语法(我更习惯 MSSQL 的 Transaction SQL 语法)
到目前为止,这是我的代码:
CREATE FUNCTION get_unused_part_ids() RETURNS integer[] AS
$BODY$DECLARE
part_ids integer ARRAY;
BEGIN
set part_ids = '{1,2,3,4}'
select part_ids
END;$BODY$
LANGUAGE sql VOLATILE;
我期待的是一个整数数组,值为 1、2、3 和 4。
具有正确语法的示例函数:
CREATE FUNCTION get_unused_part_ids() RETURNS integer[] AS
$BODY$
DECLARE
part_ids integer ARRAY;
BEGIN
part_ids = '{1,2,3,4}';
return part_ids;
END;
$BODY$ LANGUAGE plpgsql;
select * from get_unused_part_ids();
get_unused_part_ids
---------------------
{1,2,3,4}
(1 row)
请注意,您需要 plpgsql 函数才能拥有局部变量。
@klin 的回复是正确的,我有一个建议。请改用 SQL 语言。在描述的情况下 PostgreSQL 规划器可以使用更好的规划。 PLpgSQL 函数是规划器的黑盒:
CREATE OR REPLACE FUNCTION public.foo1()
RETURNS integer[]
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN ARRAY[1,2,3,4];
END;
$function$
CREATE OR REPLACE FUNCTION public.foo2()
RETURNS integer[]
LANGUAGE sql
AS $function$
SELECT ARRAY[1,2,3,4];
$function$
CREATE TABLE boo(a int);
INSERT INTO boo SELECT random()*10 FROM generate_series(1,10000);
ANALYZE boo;
postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(foo1());
QUERY PLAN
═════════════════════════════════════════════════════════════════════════════════════════════════════
Seq Scan on boo (cost=0.00..2770.00 rows=6145 width=4) (actual time=0.118..49.949 rows=4104 loops=1)
Filter: (a = ANY (foo1()))
Rows Removed by Filter: 5896
Planning time: 0.096 ms
Execution time: 50.900 ms
(5 rows)
Time: 51.771 ms
postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(foo2());
QUERY PLAN
═══════════════════════════════════════════════════════════════════════════════════════════════════
Seq Scan on boo (cost=0.00..195.00 rows=4104 width=4) (actual time=0.036..4.700 rows=4104 loops=1)
Filter: (a = ANY ('{1,2,3,4}'::integer[]))
Rows Removed by Filter: 5896
Planning time: 0.193 ms
Execution time: 5.254 ms
(5 rows)
使用SQL函数是更好的结果估计。 SQL函数是一个宏——如果你使用SQL函数,那么它相当于直接写查询:
postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(ARRAY[1,2,3,4]);
QUERY PLAN
═══════════════════════════════════════════════════════════════════════════════════════════════════
Seq Scan on boo (cost=0.00..195.00 rows=4104 width=4) (actual time=0.032..4.782 rows=4104 loops=1)
Filter: (a = ANY ('{1,2,3,4}'::integer[]))
Rows Removed by Filter: 5896
Planning time: 0.122 ms
Execution time: 5.325 ms
(5 rows)
在这种情况下,优化器有更多的信息,可以使用它。对于结果恒定的函数,SQL 函数通常更好。
我正在尝试启动一个 SQL 函数,以便我可以收集我不希望在另一个查询中使用的零件 ID 列表。我已经尝试使用 PGAdmin 的函数构建器来开始,但我有一个语法错误,所以它不会创建函数。有人可以告诉我我在这里做错了什么吗?一旦我可以启动该功能,我想我就可以解决剩下的问题了。只需要弄清楚正确的声明语法(我更习惯 MSSQL 的 Transaction SQL 语法)
到目前为止,这是我的代码:
CREATE FUNCTION get_unused_part_ids() RETURNS integer[] AS
$BODY$DECLARE
part_ids integer ARRAY;
BEGIN
set part_ids = '{1,2,3,4}'
select part_ids
END;$BODY$
LANGUAGE sql VOLATILE;
我期待的是一个整数数组,值为 1、2、3 和 4。
具有正确语法的示例函数:
CREATE FUNCTION get_unused_part_ids() RETURNS integer[] AS
$BODY$
DECLARE
part_ids integer ARRAY;
BEGIN
part_ids = '{1,2,3,4}';
return part_ids;
END;
$BODY$ LANGUAGE plpgsql;
select * from get_unused_part_ids();
get_unused_part_ids
---------------------
{1,2,3,4}
(1 row)
请注意,您需要 plpgsql 函数才能拥有局部变量。
@klin 的回复是正确的,我有一个建议。请改用 SQL 语言。在描述的情况下 PostgreSQL 规划器可以使用更好的规划。 PLpgSQL 函数是规划器的黑盒:
CREATE OR REPLACE FUNCTION public.foo1()
RETURNS integer[]
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN ARRAY[1,2,3,4];
END;
$function$
CREATE OR REPLACE FUNCTION public.foo2()
RETURNS integer[]
LANGUAGE sql
AS $function$
SELECT ARRAY[1,2,3,4];
$function$
CREATE TABLE boo(a int);
INSERT INTO boo SELECT random()*10 FROM generate_series(1,10000);
ANALYZE boo;
postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(foo1()); QUERY PLAN ═════════════════════════════════════════════════════════════════════════════════════════════════════ Seq Scan on boo (cost=0.00..2770.00 rows=6145 width=4) (actual time=0.118..49.949 rows=4104 loops=1) Filter: (a = ANY (foo1())) Rows Removed by Filter: 5896 Planning time: 0.096 ms Execution time: 50.900 ms (5 rows) Time: 51.771 ms postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(foo2()); QUERY PLAN ═══════════════════════════════════════════════════════════════════════════════════════════════════ Seq Scan on boo (cost=0.00..195.00 rows=4104 width=4) (actual time=0.036..4.700 rows=4104 loops=1) Filter: (a = ANY ('{1,2,3,4}'::integer[])) Rows Removed by Filter: 5896 Planning time: 0.193 ms Execution time: 5.254 ms (5 rows)
使用SQL函数是更好的结果估计。 SQL函数是一个宏——如果你使用SQL函数,那么它相当于直接写查询:
postgres=# EXPLAIN ANALYZE SELECT * FROM boo WHERE a = ANY(ARRAY[1,2,3,4]); QUERY PLAN ═══════════════════════════════════════════════════════════════════════════════════════════════════ Seq Scan on boo (cost=0.00..195.00 rows=4104 width=4) (actual time=0.032..4.782 rows=4104 loops=1) Filter: (a = ANY ('{1,2,3,4}'::integer[])) Rows Removed by Filter: 5896 Planning time: 0.122 ms Execution time: 5.325 ms (5 rows)
在这种情况下,优化器有更多的信息,可以使用它。对于结果恒定的函数,SQL 函数通常更好。