Mat*_*jaž 4 postgresql foreign-key range-types postgresql-9.6
是否可以在 PostgreSQL 9.6 中对范围(在我的情况下为整数)的下限和上限应用外键约束?
目前我将下限和上限保留在两列中,但希望将它们统一到一个范围列中,同时保留外键引用。
我有一个包含会话列表的表,例如:
CREATE TABLE sessions (
session_id SERIAL PRIMARY KEY,
session_start TIMESTAMPTZ NOT NULL,
description TEXT
);
Run Code Online (Sandbox Code Playgroud)
然后是这些会议的组表,目前表示为:
CREATE TABLE session_groups (
group_id SERIAL PRIMARY KEY,
first_session INTEGER NOT NULL UNIQUE,
last_session INTEGER NOT NULL UNIQUE,
description TEXT,
FOREIGN KEY (first_session)
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
FOREIGN KEY (last_session)
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT last_session_after_first
CHECK (last_session >= first_session)
);
Run Code Online (Sandbox Code Playgroud)
我想要什么:
CREATE TABLE session_groups (
group_id SERIAL PRIMARY KEY,
session_range INT4RANGE NOT NULL UNIQUE,
description TEXT,
FOREIGN KEY (lower(session_range))
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
FOREIGN KEY (upper(session_range))
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
-- Dropped last_session_after_first constraint since
-- the INT4RANGE type checks it automatically.
);
Run Code Online (Sandbox Code Playgroud)
这是抛出语法错误。
不允许在FOREIGN KEY约束中有任意表达式,只有列。这就是为什么当您尝试第二种方法时会出现错误的原因。
但是,您可以使用 aVIEW访问该表:
CREATE VIEW v_session_groups
(group_id, session_range, description) AS
SELECT
group_id,
int4range(first_session, last_session, '[)'),
description
FROM
session_groups ;
Run Code Online (Sandbox Code Playgroud)
您甚至可以添加触发器,然后能够从视图中插入/更新/删除,就好像它是一个普通表一样。
旁注:
UNIQUE约束,on(first_session)和(last_session),而第二个设计有 1 个UNIQUE约束,on (first_session, last_session)。这些不是等效的设计,因此请重新检查您的要求。'[)'为该int4range列使用了默认(包含-排除)参数。您可能希望将其更改为'[]'(all-inclusive),具体取决于您希望如何保存范围。int4range(1,1)andint4range(1,1,'[)')是空范围,而int4range(1,1,'[]')是[1,2)范围。如果你想强制/避免重叠范围,那么你根本不需要UNIQUE约束,而是一个EXCLUDE约束:
CREATE TABLE session_groups (
group_id SERIAL PRIMARY KEY,
first_session INTEGER NOT NULL,
last_session INTEGER NOT NULL,
description TEXT,
FOREIGN KEY (first_session)
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
FOREIGN KEY (last_session)
REFERENCES sessions (session_id)
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT non_overlapping_sessions
EXCLUDE USING gist
( int4range(first_session, last_session, '[)') WITH && )
);
Run Code Online (Sandbox Code Playgroud)
另请参阅有关范围类型约束的文档。您可能还需要添加扩展名:
CREATE EXTENSION btree_gist;
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
831 次 |
| 最近记录: |