0

我有下表。

CLASS_HAS_STUDENTS (
    PER_SSN INTEGER NOT NULL,
    PER_YEAR INTEGER NOT NULL, /*These two are PKs for a student*/
    SCHOOL_CODE INTEGER NOT NULL, /*PK for a school*/
    CLASS_YEAR INTEGER NOT NULL,
    CLASS_NUMBER INTEGER NOT NULL,
    CLASS_TEACHTYPE CHAR(3) NOT NULL, /*These three are PKs for a class*/
    STUDCLASS_STATUS CHAR(1) NOT NULL
        constraint CKC_STUDCLASS_STATUS_CLASS_TI check (StudClass_Status IN ('E', 'Y', 'T', 'P', 'F')),
    STUDCLASS_LISTNUMBER INTEGER NOT NULL,
    STUDCLASS_ROLLNUMBER INTEGER NOT NULL
);

(此代码缺少一些小约束)

现在,我需要一种方法来检查一个 PER_SSN/PER_YEAR(一个人的 PK)是否只能具有一个“E”(“已注册”)状态。我不能用触发器来做到这一点(假设我是从同一个表中选择的),我不知道我是否可以用检查约束来做到这一点(我可以在这里使用 COUNT() 吗?)。任何帮助表示赞赏。

4

3 回答 3

4

您可以创建一个基于函数的唯一索引来强制执行此类操作。您不能这样创建约束。

这利用了 Oracle b-tree 索引不索引 NULL 数据这一事实,因此该索引将仅包含 is 的行的studclass_status条目E

CREATE UNIQUE INDEX idx_one_enrolled
    ON class_has_students( CASE WHEN studclass_status = 'E'
                                THEN per_ssn
                                ELSE null
                            END,
                           CASE WHEN studclass_status = 'E'
                                THEN per_year
                                ELSE null
                            END );
于 2012-07-29T20:50:26.743 回答
1

我对你的问题有点困惑。我猜你要么想要:

1)防止每个学生插入一个以上的状态(在这种情况下触发将是合适的)

或者

2) 使用 SELECT 语句查找表中已有的学生,在这种情况下,您需要执行以下操作:

SELECT PER_SSN, PER_YEAR, STUDCLASS_STATUS, COUNT(*)
FROM   CLASS_HAS_STUDENTS
WHERE  STUDCLASS_STATUS = 'E'
HAVING COUNT(*) > 1
GROUP BY PER_SSN, PER_YEAR, STUDCLASS_STATUS;
于 2012-07-29T20:48:23.737 回答
1

您应该能够使用部分唯一索引来执行此操作。为确保每个 ssn 只有一个注册课程,这应该有效:

CREATE UNIQUE INDEX ssn_enrollments ON class_has_students(per_ssn) 
WHERE studclass_status='E';

请注意,并非所有 SQL 实现都支持此功能,但 PostgreSQL 至少从版本 8 开始支持。

于 2012-07-29T20:48:56.570 回答