使用动态 SQL 的参数化 PostgreSQL 函数的语法
Syntax for parameterized PostgreSQL function using dynamic SQL
此代码:
ALTER TABLE myschema.mytable add column geom geometry (point,4326);
CREATE INDEX mytable_idx on myschema.mytable using GIST(geom);
UPDATE myschema.mytable set geom = st_setsrid(st_point(mytable.long, mytable.lat), 4326);
这在更新单个 table 时工作正常。您如何将其转换为动态 SQL 函数,以架构和 table 作为参数?
将您的查询作为 SQL 模板并使用 format
函数作为标识符:
CREATE OR REPLACE FUNCTION public.create_geom(sch text, tab text)
RETURNS void language plpgsql AS $body$
DECLARE
DYNSQLA constant text := 'ALTER TABLE %I.%I add column geom geometry (point,4326)';
DYNSQLB constant text := 'CREATE INDEX %I_idx on %I.%I using GIST(geom);';
DYNSQLC constant text := 'UPDATE %I.%I set geom = st_setsrid(st_point(%I.long, %I.lat), 4326)';
BEGIN
execute format(DYNSQLA, sch, tab);
execute format(DYNSQLB, tab, sch, tab);
execute format(DYNSQLC, sch, tab, tab, tab);
END;
$body$;
SELECT create_geom('myschema','mytable');
由于函数输入必须是现有的 table,最简单的 安全 方法是使用 regclass
输入参数,如下所示:
- Table name as a PostgreSQL function parameter
但是,您还需要连接索引名称的裸 table 名称,因此我将坚持使用 text
作为架构,并分别使用 table:
CREATE OR REPLACE FUNCTION create_geom(_sch text, _tab text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format(
'ALTER TABLE %1$I.%2$I ADD COLUMN geom geometry(POINT,4326);
UPDATE %1$I.%2$I SET geom = st_setsrid(st_point(long, lat), 4326);
CREATE INDEX %3$I ON %1$I.%2$I USING gist(geom);'
, _sch, _tab
, _tab || '_geom_gist_idx');
END
$func$;
通话:
SELECT create_geom('myschema', 'mytable');
使用单个 EXECUTE
,无需多次调用。
只需省略 table-对 UPDATE
中列的限定。虽然不加入额外的 table,但列名是明确的。否则,使用 table 别名,它可以是常量。喜欢:
UPDATE %1$s AS x SET geom = st_setsrid(st_point(x.long, x.lat), 4326);
但是在构建索引之前填充列会更明智。这要快得多,并且会产生一个没有膨胀的平衡索引。所以我切换了命令。
请注意我是如何先连接索引名称 (_tab || '_geom_gist_idx'
),然后 然后 根据需要使用 %3$I
双引号。这是安全的方法。 %I_idx
之类的东西因非标准名称而失败。
就是说,将具有冗余信息的列添加到 table 通常是错误的。 (是什么阻止你改变一个或另一个?为什么要膨胀 table?)要么只使用表达式索引而不是以上所有内容:
CREATE INDEX ON myschema.mytable USING gist (st_setsrid(st_point(long, lat), 4326));
或者从 table 中删除现在多余的 long
& lat
。这些可以从新的 geom
中廉价地即时提取。
或者,如果您需要所有列(出于特殊性能原因?),请考虑使用生成的列。参见:
- Computed / calculated / virtual / derived columns in PostgreSQL
此代码:
ALTER TABLE myschema.mytable add column geom geometry (point,4326);
CREATE INDEX mytable_idx on myschema.mytable using GIST(geom);
UPDATE myschema.mytable set geom = st_setsrid(st_point(mytable.long, mytable.lat), 4326);
这在更新单个 table 时工作正常。您如何将其转换为动态 SQL 函数,以架构和 table 作为参数?
将您的查询作为 SQL 模板并使用 format
函数作为标识符:
CREATE OR REPLACE FUNCTION public.create_geom(sch text, tab text)
RETURNS void language plpgsql AS $body$
DECLARE
DYNSQLA constant text := 'ALTER TABLE %I.%I add column geom geometry (point,4326)';
DYNSQLB constant text := 'CREATE INDEX %I_idx on %I.%I using GIST(geom);';
DYNSQLC constant text := 'UPDATE %I.%I set geom = st_setsrid(st_point(%I.long, %I.lat), 4326)';
BEGIN
execute format(DYNSQLA, sch, tab);
execute format(DYNSQLB, tab, sch, tab);
execute format(DYNSQLC, sch, tab, tab, tab);
END;
$body$;
SELECT create_geom('myschema','mytable');
由于函数输入必须是现有的 table,最简单的 安全 方法是使用 regclass
输入参数,如下所示:
- Table name as a PostgreSQL function parameter
但是,您还需要连接索引名称的裸 table 名称,因此我将坚持使用 text
作为架构,并分别使用 table:
CREATE OR REPLACE FUNCTION create_geom(_sch text, _tab text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format(
'ALTER TABLE %1$I.%2$I ADD COLUMN geom geometry(POINT,4326);
UPDATE %1$I.%2$I SET geom = st_setsrid(st_point(long, lat), 4326);
CREATE INDEX %3$I ON %1$I.%2$I USING gist(geom);'
, _sch, _tab
, _tab || '_geom_gist_idx');
END
$func$;
通话:
SELECT create_geom('myschema', 'mytable');
使用单个 EXECUTE
,无需多次调用。
只需省略 table-对 UPDATE
中列的限定。虽然不加入额外的 table,但列名是明确的。否则,使用 table 别名,它可以是常量。喜欢:
UPDATE %1$s AS x SET geom = st_setsrid(st_point(x.long, x.lat), 4326);
但是在构建索引之前填充列会更明智。这要快得多,并且会产生一个没有膨胀的平衡索引。所以我切换了命令。
请注意我是如何先连接索引名称 (_tab || '_geom_gist_idx'
),然后 然后 根据需要使用 %3$I
双引号。这是安全的方法。 %I_idx
之类的东西因非标准名称而失败。
就是说,将具有冗余信息的列添加到 table 通常是错误的。 (是什么阻止你改变一个或另一个?为什么要膨胀 table?)要么只使用表达式索引而不是以上所有内容:
CREATE INDEX ON myschema.mytable USING gist (st_setsrid(st_point(long, lat), 4326));
或者从 table 中删除现在多余的 long
& lat
。这些可以从新的 geom
中廉价地即时提取。
或者,如果您需要所有列(出于特殊性能原因?),请考虑使用生成的列。参见:
- Computed / calculated / virtual / derived columns in PostgreSQL