【问题标题】:How to delete a particular label from ltree in Postgres table?如何从 Postgres 表中的 ltree 中删除特定标签?
【发布时间】:2012-12-26 05:06:52
【问题描述】:

如何从 Postgres 表中的 ltree 中删除特定标签?我有桌子吗?

测试表:

CREATE TABLE tbl (sno int, path ltree, userid int);

INSERT INTO tbl (sno, path, userid)
VALUES
  (1, '123',             123)
, (2, '123.101',         123)
, (3, '123.101.103',     123)
, (4, '123.101.103.105', 123)
, (5, '123.101.103.107', 123)
, (6, '123.102.104.106', 123)
, (7, '123.102.104.108', 123)
, (8, '123.102.104',     123)
, (9, '123.102',         123);

我想将 userid 传递给查询,以将其从表中的每个 path 中删除。例如,如果我通过101,那么123.101.103 应该更新为123.103

是否可以直接执行此操作?还是我应该使用路径替换功能更新path

我从 PHP 中尝试了以下选择查询,但它返回以下错误。相同的查询在 phpPgAdmin 中正常工作!?

查询:

$selectPathq=pg_query($con,"select path from myschema.test where path @ '101'")
             or die('could not connect: '. pg_last_error($con));

错误:

could not connect:
ERROR: operator does not exist: myschema.ltree @ unknown at character 63
HINT: No operator matches the given name and argument type(s).
      You might need to add explicit type casts.

【问题讨论】:

  • 供读者阅读。 解决丑陋的“运算符不存在”错误(为什么PostgreSQL没有修复它??)的魔法是使用替换运算符@ operator(public.@) (或@> 等)如答案中所述。不需要对您的代码进行其他更改。

标签: sql postgresql tree sql-update postgresql-9.1


【解决方案1】:

修复错误

要使用数据类型ltree 和相关函数,您需要安装附加模块ltree

默认情况下,附加模块安装到架构public。如果search_path 的当前设置不包括架构public,则找不到ltree 运算符。您的错误消息暗示了这个方向:

ERROR: operator does not exist: myschema.ltree @ unknown at character 63 

为了验证,对 ltree 运算符 @ 进行模式限定:

SELECT path FROM tbl WHERE path operator(public.@) '101';

现在可以用了吗?
如果这是问题的根源,您还可以正确设置您的search_path。检查:

SHOW search_path;

设置为:

SET search_path = public; -- add more schemas as needed

The manual about search_path.

更新路径

如果我没看错您的问题,并且您想从 所有 行的路径中删除某个项目:

UPDATE tbl t
SET    path = nu.path
FROM  (
   WITH x AS (
      SELECT sno, path, index(path, '101') AS i
      FROM   tbl
      WHERE  path ~ '*.101.*'
      )
   SELECT sno
        , subpath(path, 0, i)
          || CASE WHEN nlevel(path) > i+1 THEN subpath(path, i+1)
                  ELSE '' END AS path
   FROM x
   ) nu
WHERE nu.sno = t.sno;

(请注意,由于pathltree类型,表达式path ~ '*.101.*'中的运算符~不是一个正则表达式匹配运算符,而是一个特殊的ltree匹配运算符,并且正确的术语被认为是lquery 类型。它匹配任何包含标签101 的标签路径。)

这会给你留下一个空路径,你只有101。您可以将其放入触发器 AFTER DELETE 以从所有行中清除某个项目。

【讨论】:

  • 我尝试了以下查询,UPDATE test t SET path = nu.path FROM (WITH x AS (SELECT sno, path, index(path, '123') AS i FROM test WHERE path ~ '.104.') SELECT sno,subpath(path, 0, i) || CASE WHEN nlevel(path) > i+1 THEN subpath(path, i+1) ELSE '' END AS path FROM x) nu WHERE nu.sno = t.sno;但它从“102.104.102.104.106”更新为“102.104.102.104.102.104.102.104.106”
  • @Ram:在我的示例中,您好像忘记将第二次出现的“123”替换为“104”?
  • 是的,非常感谢 Erwin Brandstetter。我接受并投票了答案。
  • 嗨,对于“操作员不存在”错误,有一个“优雅的解决方案”吗? 替换为operator(public.@) 是一个丑陋的解决方法...我试试@ 987654346@ 与 pg9.5 但WITH 似乎被忽略了。
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
相关资源
最近更新 更多