postgresql - 输入末尾的 PL/pgSQL 语法错误

标签 postgresql plpgsql

我是 PL/pgSQL 的新手,所以这对我来说是一种试错。我正在尝试创建一个空白函数,该函数在调用时将填充一个表。这是我目前所拥有的:

create or replace function counties()
returns table(code varchar(16), county varchar(50), count int) as $$
DECLARE
    new_version varchar(50) := concat('sometext', max(REGEXP_REPLACE(COALESCE(schema_name, '0'), '[^0-9]*' ,'0')::integer), 'sometext') from information_schema.schemata where schema_name like 'gcversa%';
    old_version varchar(50) := concat('sometext', max(REGEXP_REPLACE(COALESCE(schema_name, '0'), '[^0-9]*' ,'0')::integer)-2, 'sometext') from information_schema.schemata where schema_name like 'gcversa%';
BEGIN RETURN QUERY
    with cte_current as (select distinct a.code as code, b.countyname as county from old_version a, public.counties b 
                 where st_intersects(a.geom,b.geom) = True group by a.code, b.countyname),

         cte_new     as (select distinct a.code as code, b.countyname as county from new_version a, public.counties b 
                 where st_intersects(a.geom,b.geom) = True group by a.code, b.countyname),


        cte_union as (select code, county from cte_current
        union all
        select code, county from cte_new)

    select code,county, count(*) as count
    from cte_union
    group by code, county
    Having count (*) <> 2;
END;
$$
LANGUAGE plpgsql;

我声明的两个变量引用并连接了两个 PostgreSQL 模式,然后我试图将这些变量插入到 CTE 中,以便将它们联合在一起。我得到了正确执行的函数,但是当我调用 select counties() 时,我得到了这个错误:

ERROR:  relation "old_version" does not exist
LINE 1: ...tinct a.code as code, b.countyname as county from old_versio...

所以,它没有获取我声明的变量,有什么建议吗?

更新 根据 Vao Tsun 的建议,我使用了动态 SQL 和 format() 函数。最终的工作模型如下所示:

drop function counties();

create or replace function counties()
returns table(code varchar(16), county varchar(50), count bigint) as $$
DECLARE
    new_version_number varchar(50) := concat('gcversa00', MAX("versionnumber")) from "gcdefault"."versionhistory";
    old_version_number varchar(50) := concat('gcversa00', MAX("versionnumber"-2)) from "gcdefault"."versionhistory";
BEGIN RETURN QUERY EXECUTE
format(
    'with cte_current as (select distinct a.code as code, b.countyname as county from %I.servicearea a, public.counties b 
                 where st_intersects(a.geom,b.geom) = True group by a.code, b.countyname),

         cte_new     as (select distinct a.code as code, b.countyname as county from %I.servicearea a, public.counties b 
                 where st_intersects(a.geom,b.geom) = True group by a.code, b.countyname),


        cte_union as (select code, county from cte_current
        union all
        select code, county from cte_new)

    select code,county, count(*) as count
    from cte_union
    group by code, county
    Having count (*) <> 2', new_version_number, old_version_number
    );
END;
$$
LANGUAGE plpgsql;

最佳答案

这里需要动态sql,例如:

t=# create or replace function ds() returns table (i int) as
$$
declare
tn text := 'pg_database';
begin
return query execute format('select oid::int from %I',tn);
end;
$$language plpgsql
;
CREATE FUNCTION
t=# select * from ds();
     i
-----------
         1
     12945
     12950
  12963038
 111274822
  32059515
  26947889
 173381559
  32061155
  32061156
  82287221
 203004236
 214018521
(13 rows)

关于postgresql - 输入末尾的 PL/pgSQL 语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47316740/

相关文章:

sql - 重写函数以不返回记录类型

postgresql - 如何在 PostgreSQL 存储过程中使查询成为原子查询?

postgresql - 获取多个排行榜中的用户排名

performance - 为什么一个快速的函数在 ANY 内部会变慢?

PostgreSql - 将 YEar 和 Month 添加到表中

postgresql - 如何将游标的表名作为函数参数传递?

postgresql - plpgsql 函数中选择的数据类型并访问其字段

ruby-on-rails - 让 Rails 应用程序使用相同的信息更新两个 POSTGRES 数据库

postgresql - AFTER INSERT PostgreSQL 触发器的意外行为

postgresql - 在 PL/pgSQL 过程中使用临时表来清理表