2017-09-25 75 views
0

我看到很多像我的帖子,但我没有设法找到一个适当的答案我的情况,这应该是我假设的基本。我使用扩展PostGIS 2.3。这里是我的代码:PostgreSQL 9.5:缺少表“新”的FROM子句条目

CREATE OR REPLACE FUNCTION public.split_cable() 
    RETURNS trigger AS 
$BODY$ 
DECLARE geometrie geometry; 
BEGIN  
geometrie = new.geom;  
create view temp_wire as (
    with brs as (select boite.geom from cablage_pays_gex.boite 
    where st_intersects(boite.geom, new.geom) and boite.geom not in (select st_startpoint(st_linemerge(new.geom))) and boite.geom not in (select st_endpoint(st_linemerge(new.geom))) 
    ) 
    select st_dump(st_split(new.geom, brs.geom)) from brs 
    ); 
RETURN new; 
END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE; 

正如你可以看到我有一个变量“几何学”,我没有用,那是因为我想声明包含我要使用的数据的变量,没有成功。我得到的错误是我的问题,它指向st_intersects()函数(所以我第一次尝试调用new.geom)。我究竟做错了什么?我该如何解决这个问题?

编辑:这里是create table语句上的触发作用是:

CREATE TABLE public.cable2 
(
    id_cable integer NOT NULL DEFAULT nextval('cable2_seq'::regclass), 
    geom geometry(MultiLineString,2154), 
    CONSTRAINT cable2_pkey PRIMARY KEY (id_cable) 
); 
+0

向我们展示触发器表的'create table'语句。但是在触发器中创建一个视图是一个**真的**,真是个坏主意 - 它会在基础表上的第二个DML语句后失败。这意味着您只能运行一次DML语句,然后再也不会再次运行,因为每次后续语句都会出现错误。 –

+0

@a_horse_with_no_name不确定你的意思。我主要使用第三方软件QGIS与数据库交互,所以我没有使用任何语句。你的意思是“创建触发器”声明? –

+0

然后,第三方软件将停止工作,因为在针对该表的第一条DML语句之后触发器将失败。为了找出你的触发器有什么问题,我们需要查看你正在定义触发器的表的'create table'语句。 –

回答

1

TL; DR:动态SQL是必需的CREATE VIEW声明。

在plpgsql中,变量不会在数据定义查询中插值,如 CREATE...查询。

更一般地,PLPGSQL documentation告诉它为:

参数将只局部地被取代,其中一个参数或 柱参考句法允许

而在DDL查询,该位置他们允许的地方是:无处

这就是为什么new.geom引用在您的查询字面上,为什么将它转移到临时变量geometrie不会使它工作得更好。

动态SQL基本上包括构建一个命令字符串,然后执行该字符串作为EXECUTE的语句。该字符串一旦生成就不能再包含任何对变量的引用。 文档中的更多信息:Executing Dynamic Commands

正如在注释中所说的那样,每次在表中影响行时创建一个永久视图似乎在概念层面上是完全错误的。很难理解你为什么想要这样做。

+0

我明白创建视图的坏主意。我的想法是,我通过首先创建一个视图来避免许多CTE,我将为每个INSERT调用触发器将执行的操作,然后在事务结束时将其删除。但事实上,如果在其他情况下同时使用,可能会导致一些问题。所以现在我想知道,创建一个两级CTE(CTE内的一个CTE)是否更好? –

+1

@GuiOmClair:上面的答案是关于为什么触发器中存在语法错误。更糟糕的是,使用嵌套的CTE看起来是一个完全不同的问题,您可能会在不同的Q/A插槽中询问,但与上述触发器代码的文本完全不同。 –

相关问题