【问题标题】:PostgreSQL 9.5: missing FROM-clause entry for table "new"PostgreSQL 9.5:缺少表“新”的 FROM 子句条目
【发布时间】:2018-03-06 02:42:28
【问题描述】:

我看到很多类似我的帖子,但我没有找到适合我的情况的正确答案,这应该是我认为的基本答案。我使用扩展 PostGIS 2.3。这是我的代码:

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;

如您所见,我有一个未使用的变量“geometrie”,这是因为我试图声明一个包含我要使用的数据的变量,但未成功。我得到的错误是我的问题的标题,它指向 st_intersects() 函数(所以我第一次尝试调用 new.geom)。我究竟做错了什么?我该如何解决这个问题?

编辑:这是触发器正在执行的创建表语句:

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)
);

【问题讨论】:

  • 向我们展示触发器表的create table 语句。但是在触发器中创建视图是一个真的,非常糟糕的主意 - 它会在基础表上的第二个 DML 语句之后失败。这意味着您只能运行一次 DML 语句,然后再也不能运行,因为您将收到每个后续语句的错误。
  • @a_horse_with_no_name 不确定您的意思。我主要使用第三方软件 QGIS 与数据库交互,所以我没有使用任何语句。你的意思是create trigger 声明吗?
  • 那么第三方软件将停止工作,因为您的触发器将在针对该表的第一个 DML 语句之后失败。要找出您的触发器出了什么问题,我们需要查看您要在其上定义触发器的表的 create table 语句。
  • @a_horse_with_no_name 它在其他场合工作得很好。是什么让 NEW 不被识别?
  • 我编辑了我的问题,是你要的吗?

标签: postgresql postgis plpgsql


【解决方案1】:

TL;DR:CREATE VIEW 语句需要 动态 SQL

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

更一般地说,plpgsql documentation 告诉它:

参数只会在参数或 列引用在语法上是允许的

而在 DDL 查询中,它们被允许的地方是:nowhere

这就是为什么您的查询中的 new.geom 引用按字面意思理解的原因,以及为什么将其转移到临时变量 geometrie 不会使它工作得更好。

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

独立于此,正如 cmets 中所说,每次在表中的一行受到影响时创建一个永久视图似乎在概念层面上是完全错误的。很难理解你为什么要首先这样做。

【讨论】:

  • 我理解创建视图的坏主意。我的想法是通过首先创建一个视图来避免许多 CTE,我将为触发器将在其上执行的每个 INSERT 调用该视图,然后在事务结束时将其删除。但实际上,在其他情况下并发使用时可能会导致一些问题。所以现在我想知道,创建两级 CTE(CTE 内的 CTE)是不是更好?
  • @GuiOmClair:上面的答案是关于为什么触发器中有语法错误。使用嵌套 CTE 是否是个好主意,这看起来像是一个完全不同的问题,您可能会在不同的 Q/A 插槽中提出这个问题,但文本与上面的触发代码完全不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多