PLPGSQL如何使用函数参数?

PLPGSQL how to use function parameters?

最后的工作代码

我正在尝试与 plpgsql 相处,但它让我很难过。我正在尝试在数据库上创建一个函数,我的服务器将调用该函数来扩展或创建我的地形。我无法使其编译,无论我尝试什么,它都会在函数具有的两个参数之一的第一次使用时阻塞。

我尝试了几种声明参数的方式(将它们称为 ALIAS FOR 或使用名称声明它们,如下面的代码所示)我还尝试将参数类型更改为 INTEGERNUMERIC.

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