postgresql - PSQL 强制唯一性,但在表的子集内,而不是通过整个事物
问题描述
我正在为使用 PostgreSQL 的课程创建评估数据库。
我希望评估名称在课程中是唯一的,但两门课程可以有相同名称的评估。
-- assessment contains the different assignments & labs that
-- students may submit their code to.
CREATE TABLE assessment (
id SERIAL PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL,
comments TEXT NOT NULL,
type ASSESSMENT_TYPE NOT NULL,
course_id SERIAL NOT NULL,
FOREIGN KEY (course_id) REFERENCES courses(id)
);
-- courses contains the information about a course. Since
-- the same course can run multiple times, a single course
-- is uniquely identified by (course_code, year, period)
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL, -- Unique within all courses. Wrong!
course_code VARCHAR(20) NOT NULL,
period PERIOD NOT NULL,
year INTEGER NOT NULL
);
两个要点:
我可以在不更改架构的情况下执行此操作吗?
如果是这样,是否有可能包括架构更改的更惯用的解决方案?
解决方案
1. 我可以在不改变架构的情况下做到这一点吗?
不,因为您在这里有多个问题。
- 您的评估在名称上是全球唯一的,而不是在课程中。
assessment.course_id
有自己的无用序列(SERIAL
只是INTEGER
+SEQUENCE
)- 表
courses
定义了一个不存在的列数据类型:(PERIOD
至少到版本 11 不)
2. 如果是这样,是否有可能包括架构更改的更惯用的解决方案?
应该执行您想要的修改的架构如下所示:
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
course_code VARCHAR(20) NOT NULL,
period tstzrange NOT NULL
);
-- the following is required to build the proper unique constraint...
CREATE EXTENSION IF NOT EXISTS btree_gist;
-- the unique constraint: no two courses with same name at any point in time
ALTER TABLE courses
ADD CONSTRAINT idx_unique_courses
EXCLUDE USING GIST (name WITH =, period WITH &&);
CREATE TABLE assessment (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
comments TEXT NOT NULL,
type ASSESSMENT_TYPE NOT NULL,
course_id INTEGER NOT NULL REFERENCES courses(id),
UNIQUE (course_id, name)
);
推荐阅读
- swift - 如何修复:您有 macOS 10.14.6。应用程序需要 macOS 11.0 或更高版本?
- amazon-web-services - AWS 命令行 - 无法找到凭证 - 指定配置文件时
- mysql - MySQL 8.0.23 在 Select 查询上出现 Segfault 崩溃
- sql-server - 限制 SQL 全文索引
- android - 下载目录中的列表文件仅限于图像
- android - 在 Android Studio 中生成签名 APK 时出现 Gradle 错误
- python - Networkx 中的自动签约节点
- javascript - 种类(); Javascript中的方法
- r - 为什么 `levels<-` 的行为会根据命名参数的顺序而有所不同?
- python - Crontab python 脚本不运行(在 linux 服务器上使用 anaconda)