是否可以创建一个包含 ltree 字段的整个路径的唯一约束?

Tra*_*vis 5 postgresql ltree

我使用 Postgres 中的 ltree 扩展来管理树的路径。我想确保名称字段对于树上的任何给定路径都是唯一的。我可以使用约束来完成此操作还是必须将其构建到查询中?

  demo table
------------------------------
| name (text) | path (ltree) |
------------------------------
| a           | 1            |
------------------------------
| b           | 1.2          |
------------------------------
| b           | 1.3          |
------------------------------
| b           | 1.2.4        | <-- this should fail on insert
------------------------------
Run Code Online (Sandbox Code Playgroud)

如果我必须将其构建到查询中,如果我使用 READ COMMITTED,这是否可能存在竞争条件?

CREATE TABLE demo (
    name text NOT null,
    path ltree NOT null
);
CREATE INDEX path_gist_idx ON demo USING GIST (path);
INSERT INTO demo (name, path)
SELECT 'a', '1'
WHERE NOT EXISTS (
    SELECT * FROM demo WHERE name = 'a' AND (path <@ '1' OR path @> '1')
);
INSERT INTO demo (name, path)
SELECT 'b', '1.2'
WHERE NOT EXISTS (
    SELECT * FROM demo WHERE name = 'b' AND (path <@ '1.2' OR path @> '1.2')
);
INSERT INTO demo (name, path)
SELECT 'b', '1.3'
WHERE NOT EXISTS (
    SELECT * FROM demo WHERE name = 'b' AND (path <@ '1.3' OR path @> '1.3')
);
INSERT INTO demo (name, path)
SELECT 'b', '1.2.4'
WHERE NOT EXISTS (
    SELECT * FROM demo WHERE name = 'b' AND (path <@ '1.2.4' OR path @> '1.2.4')
);
SELECT * FROM demo;
Run Code Online (Sandbox Code Playgroud)

jja*_*nes 1

如果您使用已提交读,则会出现竞争条件。

原则上您可以使用 EXCLUDE 约束,但没有可以使用的单个自交换运算符。这意味着您必须发明一个新的运算符(可能称为 <@>),并将其添加到 ltree 中。我认为这是可能的,但不是您可能期待做的事情。

你可以只使用序列化吗?