我正在建立一个PostgreSQL数据库,并希望创建一个约束来检查值(来自单个表中不同行的值)是否连续。
该表如下所示:
+-------------+---------+-------+
| waypoint_id | path_id | order |
+-------------+---------+-------+
| 89 | 1 | 1 |
| 16 | 1 | 2 |
| 17 | 1 | 3 |
| 19 | 1 | 4 |
| 4 | 1 | 5 |
| 75 | 2 | 1 |
| 28 | 2 | 2 |
| 2 | 2 | 3 |
+-------------+---------+-------+
这是一个表,用于存储特定路径的路点顺序。
约束必须检查order列(具有相同的path_id)中的值是否连续。
这是一个无效示例:(该顺序不连续,因为缺少3个)
+-------------+---------+-------+
| waypoint_id | path_id | order |
+-------------+---------+-------+
| 21 | 1 | 1 |
| 29 | 1 | 2 |
| 104 | 1 | 4 |
+-------------+---------+-------+
我希望约束不允许允许该行的插入:
| 104 | 1 | 4 |
请向我展示类似问题的解决方案示例,或向我介绍有关如何解决该问题的文档。
答案 0 :(得分:1)
您在这里:https://dbfiddle.uk/?rdbms=postgres_11&fiddle=b67be9527e86fd444d158f9ab93bf600
对于急躁的人:
CREATE OR REPLACE FUNCTION consecutive_check()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF NEW."order" = 1 OR EXISTS (SELECT 1 FROM my_table WHERE path_id = NEW.path_id AND "order" = (NEW."order" - 1)) THEN
RETURN NEW;
END IF;
RAISE EXCEPTION 'Previous waypoint not available for path_id = %', NEW.path_id;
END;
$function$;
CREATE TRIGGER no_holes_path
BEFORE INSERT
ON my_table
FOR EACH ROW
EXECUTE PROCEDURE consecutive_check()
;
警告:这将导致查询表,因此您必须在path_id
和order
上有一个索引,并且您必须注意以下事实:该解决方案无法很好地扩展。
答案 1 :(得分:0)
(track_id, "order")
; waypoint_id
不需要包括在内。(track_id, waypoint_id)
上添加一个额外的唯一约束,以防止在单个轨道上两次访问点)order
ORDER
是关键字;最好避免将其用作标识符。CREATE TABLE tracks
(track_id INTEGER NOT NULL
, step INTEGER NOT NULL
, waypoint_id INTEGER -- REFERENCES waypoints(id)
, PRIMARY KEY (track_id,step)
);
INSERT INTO tracks(track_id, step, waypoint_id)VALUES
(1,1,89) , (1,2,16) , (1,4,17), (1,5,19), (1,6,4) -- mind the gap!
, (2,11,75) , (2,22,28) , (2,44,2) -- Large gaps!
;
CREATE VIEW tracks_ordered AS
SELECT track_id
, rank() OVER (PARTITION BY track_id ORDER BY step) AS "Order!"
, waypoint_id
FROM tracks;
SELECT *FROM tracks_ordered;
结果:
track_id | Order! | waypoint_id
----------+--------+-------------
1 | 1 | 89
1 | 2 | 16
1 | 3 | 17
1 | 4 | 19
1 | 5 | 4
2 | 1 | 75
2 | 2 | 28
2 | 3 | 2
(8 rows)