plpgsql动态添加select查询到变量

plpgsql dynamically add select query to variable

我正在尝试遍历具有许多模式的 varchar 数组并动态构建大量 select 语句。 1st 2 raise 通知工作正常,但我不知道如何将动态 select 语句附加到一个大的 select.

理想情况下我想要这样的东西

SELECT 
    st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom
    ,parcel_id
FROM schema1.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269))
UNION
SELECT 
    st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom
    ,parcel_id
FROM schema2.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269))

代码

DO
$do$
DECLARE
   a varchar[] := array['schema1','schema2'];
   i integer; 
   slct varchar;
BEGIN
   FOR i IN 1 .. array_upper(a, 1)
   LOOP
      RAISE NOTICE '%', a[i]; 
      RAISE NOTICE 'SELECT st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom,parcel_id
                      FROM %.parcel t join bounds b
                        on st_intersects(t.geom,st_transform(b.geom,4269))',a[i];
      EXECUTE 'SELECT st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom,parcel_id
                      FROM %.parcel t join bounds b
                        on st_intersects(t.geom,st_transform(b.geom,4269))',a[i] into slct;         
   END LOOP;
END
$do$;

错误

ERROR:  query "SELECT 'SELECT st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom,parcel_id
                      FROM %.parcel t join bounds b
                        on st_intersects(t.geom,st_transform(b.geom,4269))',a[i]" returned 2 columns
CONTEXT:  PL/pgSQL function inline_code_block line 17 at EXECUTE
SQL state: 42601

更新了查询和错误

EXECUTE 'SELECT st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom,parcel_id
              FROM .parcel t join bounds b
                on st_intersects(t.geom,st_transform(b.geom,4269))' into slct 
                using a[i];

错误

ERROR:  syntax error at or near ""
LINE 2:        FROM .parcel t join bounds b
                    ^
QUERY:  SELECT st_asmvtgeom(st_transform(t.geom,3857),b.geom) AS geom,parcel_id
                      FROM .parcel t join bounds b
                        on st_intersects(t.geom,st_transform(b.geom,4269))
CONTEXT:  PL/pgSQL function inline_code_block line 17 at EXECUTE
SQL state: 42601

如果您的架构数量有限,那么您可以使用 SQL 之类的

SELECT ...
FROM schema1.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269))
WHERE 'schema1' = any(array['schema1','schema2'])
UNION
SELECT ...
FROM schema2.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269))
WHERE 'schema2' = any(array['schema1','schema2'])
UNION
SELECT ...
FROM schema3.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269))
WHERE 'schema3' = any(array['schema1','schema2'])

如果您想以动态方式构建查询,那么您可以在单个查询中完成:

select
    string_agg(format($$SELECT * FROM %I.parcel t 
JOIN bounds b
    ON st_intersects(t.geom,st_transform(b.geom,4269)
$$, shm), e'UNION\n') as sql
FROM unnest(array['schema1','schema2']) as shm;

┌───────────────────────────────────────────────────────┐
│                          sql                          │
├───────────────────────────────────────────────────────┤
│ SELECT * FROM schema1.parcel t                       ↵│
│ JOIN bounds b                                        ↵│
│     ON st_intersects(t.geom,st_transform(b.geom,4269)↵│
│ UNION                                                ↵│
│ SELECT * FROM schema2.parcel t                       ↵│
│ JOIN bounds b                                        ↵│
│     ON st_intersects(t.geom,st_transform(b.geom,4269)↵│
│                                                       │
└───────────────────────────────────────────────────────┘

使用此查询的结果作为 EXECUTE 语句的参数。

几个笔记。

您可以使用美元引号引起来的字符串来保持语法高亮显示。比较

select 'select
*
from foo';

select $$select
*
from foo$$;

使用 format() 函数和 %I 标识符占位符:

select format('%s %I', 'FooBar', 'FooBar');

┌─────────────────┐
│     format      │
├─────────────────┤
│ FooBar "FooBar" │
└─────────────────┘