我有一个父表layer_1_
和一些包含一些几何数据的子表layer_1_points
,layer_1_linestrings
等。每个子表都有自己的几何约束。因此,例如,layer_1_points
具有此约束:
CONSTRAINT enforce_geotype_geom_geom CHECK (geometrytype(geom) = 'POINT'::text)
layer_1_linestrings
表有这个约束:
CONSTRAINT enforce_geotype_geom_geom CHECK (geometrytype(geom) = 'LINESTRING'::text)
许多其他图层表具有相似的名称:layer_2_
,layer_3_
,...,layer_N_
。他们都有自己的子桌。我想要实现的是当用户插入父表(layer_N_
)时,应将此insert
语句转发到特定的子表(layer_N_points
等)。所以,例如,当我这样做时:
INSERT INTO layer_1_ (geom) VALUES(ST_GeomFromText('POINT(0 0)', 3857))
我应该插入layer_1_points
,因为geom
类型是POINT
。为了实现这一切,我创建了这个触发器功能和触发器本身:
CREATE OR REPLACE FUNCTION trigger_layer_insert()
RETURNS trigger AS
$$
DECLARE
var_geomtype text;
table_name text;
layer_id text := (TG_ARGV[0])::text;
BEGIN
var_geomtype := geometrytype(NEW.geom);
IF var_geomtype = 'POINT' THEN
table_name := (SELECT concat ('layer_', layer_id, '_points'));
ELSIF var_geomtype = 'MULTIPOINT' THEN
table_name := (SELECT concat ('layer_', layer_id, '_multipoints'));
ELSIF var_geomtype = 'LINESTRING' THEN
table_name := (SELECT concat ('layer_', layer_id, '_linestrings'));
ELSIF var_geomtype = 'MULTILINESTRING' THEN
table_name := (SELECT concat ('layer_', layer_id, '_multilinestrings'));
ELSIF var_geomtype = 'POLYGON' THEN
table_name := (SELECT concat ('layer_', layer_id, '_polygons'));
ELSIF var_geomtype = 'MULTIPOLYGON' THEN
table_name := (SELECT concat ('layer_', layer_id, '_multipolygons'));
END IF;
EXECUTE '
INSERT INTO ' || table_name || '
SELECT * FROM (SELECT NEW.*) AS t
';
RETURN NULL;
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
CREATE TRIGGER trigger_layer_1_ BEFORE INSERT
ON layer_1_ FOR EACH ROW
EXECUTE PROCEDURE trigger_layer_insert(1);
然而,当我做实际插入时:
INSERT INTO layer_1_ (geom) VALUES(ST_GeomFromText('POINT(0 0)', 3857))
我收到错误消息:
ERROR: missing FROM-clause entry for table "new"
LINE 3: SELECT * FROM (SELECT NEW.*) AS t
^
QUERY:
INSERT INTO layer_1_points
SELECT * FROM (SELECT NEW.*) AS t
那么,SELECT NEW.*
有什么问题,我该如何解决?谢谢!
修改
我也试过这个:
EXECUTE '
INSERT INTO ' || table_name || '
SELECT * FROM (SELECT NEW.*) AS t
' USING NEW;
但它没有效果。
答案 0 :(得分:7)
当您使用PLPGSQL语句EXECUTE
执行某些操作时,它会在不同的上下文中运行,因此局部变量在那里不可见。要传递变量,使用EXECUTE '<SQL script>' USING <variables list>;
形式:
EXECUTE 'insert into table(field1, field2) values ($1, $2)' USING var1, var2;
所以声明应该是:
EXECUTE
'INSERT INTO ' || table_name || ' SELECT * FROM SELECT $1.*) AS t'
USING NEW;