错误:缺少FROM-clause条目表#34; new"

时间:2016-06-30 15:42:55

标签: postgresql

我有一个父表layer_1_和一些包含一些几何数据的子表layer_1_pointslayer_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;

但它没有效果。

1 个答案:

答案 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;