PLPGSQL如何使用函数参数?
PLPGSQL how to use function parameters?
最后的工作代码
我正在尝试与 plpgsql 相处,但它让我很难过。我正在尝试在数据库上创建一个函数,我的服务器将调用该函数来扩展或创建我的地形。我无法使其编译,无论我尝试什么,它都会在函数具有的两个参数之一的第一次使用时阻塞。
我尝试了几种声明参数的方式(将它们称为 ALIAS FOR
或使用名称声明它们,如下面的代码所示)我还尝试将参数类型更改为 INTEGER
或 NUMERIC
.
CREATE FUNCTION public.generate_terrain (
inner NUMERIC,
outer NUMERIC
)
RETURNS void AS
$body$
DECLARE
q NUMERIC;
r NUMERIC;
BEGIN
q := -outer;
r := -outer;
WHILE q < outer DO
WHILE r < outer DO
IF(r > -inner AND r < inner AND q > -inner AND q > inner) THEN
r := inner;
END IF;;
--insert into public.t_cell (coo_q, coo_r) values (q,r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END WHILE;
q := q + 1;
END WHILE;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
PARALLEL UNSAFE;
我在尝试编译时收到此错误消息:
ERROR: syntax error at end of input
LINE 8: q := -outer;
^
我不能让我的客户端执行循环,然后将结果推送到数据库,这会产生大量流量我想让我的数据库自己执行此操作,因此需要能够编译它。请帮忙!
编辑 1
我忘了解释我想要这个函数做什么:我需要一个函数,它用笛卡尔网格图(q = x 轴,r = y 轴,因为实际上它是六边形的)的连贯“单元格”填充我的数据库地图)。必须能够调用此函数来扩展它们的地图,因此如果我的初始调用是 generate_terrain(0,2)
,它必须生成以下地形:
#####
#####
##0##
#####
#####
(0
是网格的中心(0,0))
其中坐标范围从左下角的 (-2,-2) 到右上角的 (2,2)。稍后,当我需要扩展地图时,我必须能够调用 generate_terrain(3,4)
来生成我的地形的以下单元格:
#########
#########
## ##
## ##
## 0 ##
## ##
## ##
#########
#########
(0
是网格的中心(0,0))
坐标范围从左下角的 (-4,-4) 到右上角的 (4,4) 但数据库中已经存在内部“正方形”
我最终使用的功能如下:
CREATE OR REPLACE FUNCTION public.generate_terrain (
_inner integer,
_outer integer
)
RETURNS integer AS
$body$
DECLARE
q integer = 0;
r integer = 0;
BEGIN
q := q - _outer;
r := r - _outer;
WHILE q <= _outer
LOOP
WHILE r <= _outer
LOOP
-- This condition is to skip the inner square that is already
-- present in the database.
IF r > -_inner
AND r < _inner
AND q > -_inner
AND q < _inner THEN
r := _inner;
END IF;
--insert into public.t_cell (coo_q, coo_r) values (q, r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END LOOP;
q := q + 1;
r := - _outer;
END LOOP;
RETURN 1;
END;
$body$
LANGUAGE 'plpgsql'
除了使用 a_horse 指出的保留字外,您还存在一些语法违规问题。这会起作用:
CREATE OR REPLACE FUNCTION public.generate_terrain (_inner NUMERIC, _outer NUMERIC)
RETURNS void AS
$func$
DECLARE
q NUMERIC := -_outer;
r NUMERIC := -_outer;
BEGIN
WHILE q < _outer
LOOP -- !
WHILE r < _outer
LOOP -- !
IF r > -_inner
AND r < _inner
AND q > -_inner
AND q > _inner THEN -- ??
r := _inner;
END IF; -- !
--insert into public.t_cell (coo_q, coo_r) values (q,r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END LOOP; -- !
q := q + 1;
END LOOP; -- !
END
$func$ LANGUAGE plpgsql;
但这似乎是不必要的扭曲。 _inner
从未被使用过。您是不是想写 q < _inner
? (仍然很奇怪。)
否则你可以用这个代替:
CREATE OR REPLACE FUNCTION public.generate_terrain_simple (_outer int)
RETURNS void AS
$func$
INSERT INTO public.t_cell (coo_q, coo_r)
SELECT -_outer, g FROM generate_series (-_outer, _outer -1) g
$func LANGUAGE sql;
对 Erwin Last Query 的小优化。
create or replace function
public.generate_terrain_simple_1(_outer int)
returns void as $$
declare _x int; _y int;
begin
<<test>>
for _x, _y in
select -_outer, g from generate_series(-_outer,_outer - 1) g
loop
raise info 'test % %', _x,_y;
end loop test;
end
$$ language plpgsql;
select * from generate_terrain_simple_1(4);
_x
将与 -4 相同,_y
将从 -4 到 3
最后的工作代码
我正在尝试与 plpgsql 相处,但它让我很难过。我正在尝试在数据库上创建一个函数,我的服务器将调用该函数来扩展或创建我的地形。我无法使其编译,无论我尝试什么,它都会在函数具有的两个参数之一的第一次使用时阻塞。
我尝试了几种声明参数的方式(将它们称为 ALIAS FOR
或使用名称声明它们,如下面的代码所示)我还尝试将参数类型更改为 INTEGER
或 NUMERIC
.
CREATE FUNCTION public.generate_terrain (
inner NUMERIC,
outer NUMERIC
)
RETURNS void AS
$body$
DECLARE
q NUMERIC;
r NUMERIC;
BEGIN
q := -outer;
r := -outer;
WHILE q < outer DO
WHILE r < outer DO
IF(r > -inner AND r < inner AND q > -inner AND q > inner) THEN
r := inner;
END IF;;
--insert into public.t_cell (coo_q, coo_r) values (q,r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END WHILE;
q := q + 1;
END WHILE;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
PARALLEL UNSAFE;
我在尝试编译时收到此错误消息:
ERROR: syntax error at end of input
LINE 8: q := -outer;
^
我不能让我的客户端执行循环,然后将结果推送到数据库,这会产生大量流量我想让我的数据库自己执行此操作,因此需要能够编译它。请帮忙!
编辑 1
我忘了解释我想要这个函数做什么:我需要一个函数,它用笛卡尔网格图(q = x 轴,r = y 轴,因为实际上它是六边形的)的连贯“单元格”填充我的数据库地图)。必须能够调用此函数来扩展它们的地图,因此如果我的初始调用是 generate_terrain(0,2)
,它必须生成以下地形:
#####
#####
##0##
#####
#####
(0
是网格的中心(0,0))
其中坐标范围从左下角的 (-2,-2) 到右上角的 (2,2)。稍后,当我需要扩展地图时,我必须能够调用 generate_terrain(3,4)
来生成我的地形的以下单元格:
#########
#########
## ##
## ##
## 0 ##
## ##
## ##
#########
#########
(0
是网格的中心(0,0))
坐标范围从左下角的 (-4,-4) 到右上角的 (4,4) 但数据库中已经存在内部“正方形”
我最终使用的功能如下:
CREATE OR REPLACE FUNCTION public.generate_terrain (
_inner integer,
_outer integer
)
RETURNS integer AS
$body$
DECLARE
q integer = 0;
r integer = 0;
BEGIN
q := q - _outer;
r := r - _outer;
WHILE q <= _outer
LOOP
WHILE r <= _outer
LOOP
-- This condition is to skip the inner square that is already
-- present in the database.
IF r > -_inner
AND r < _inner
AND q > -_inner
AND q < _inner THEN
r := _inner;
END IF;
--insert into public.t_cell (coo_q, coo_r) values (q, r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END LOOP;
q := q + 1;
r := - _outer;
END LOOP;
RETURN 1;
END;
$body$
LANGUAGE 'plpgsql'
除了使用 a_horse 指出的保留字外,您还存在一些语法违规问题。这会起作用:
CREATE OR REPLACE FUNCTION public.generate_terrain (_inner NUMERIC, _outer NUMERIC)
RETURNS void AS
$func$
DECLARE
q NUMERIC := -_outer;
r NUMERIC := -_outer;
BEGIN
WHILE q < _outer
LOOP -- !
WHILE r < _outer
LOOP -- !
IF r > -_inner
AND r < _inner
AND q > -_inner
AND q > _inner THEN -- ??
r := _inner;
END IF; -- !
--insert into public.t_cell (coo_q, coo_r) values (q,r);
RAISE NOTICE 'Cell %,%', q,r;
r := r + 1;
END LOOP; -- !
q := q + 1;
END LOOP; -- !
END
$func$ LANGUAGE plpgsql;
但这似乎是不必要的扭曲。 _inner
从未被使用过。您是不是想写 q < _inner
? (仍然很奇怪。)
否则你可以用这个代替:
CREATE OR REPLACE FUNCTION public.generate_terrain_simple (_outer int)
RETURNS void AS
$func$
INSERT INTO public.t_cell (coo_q, coo_r)
SELECT -_outer, g FROM generate_series (-_outer, _outer -1) g
$func LANGUAGE sql;
对 Erwin Last Query 的小优化。
create or replace function
public.generate_terrain_simple_1(_outer int)
returns void as $$
declare _x int; _y int;
begin
<<test>>
for _x, _y in
select -_outer, g from generate_series(-_outer,_outer - 1) g
loop
raise info 'test % %', _x,_y;
end loop test;
end
$$ language plpgsql;
select * from generate_terrain_simple_1(4);
_x
将与 -4 相同,_y
将从 -4 到 3