PL/SQL-一个人只有一个值

PL/SQL-一个人只有一个值,sql,oracle,plsql,Sql,Oracle,Plsql,我有下表 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, C

我有下表

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
);
(此代码缺少一些次要约束)


现在,我需要一种方法来检查每个SSN/每年(一个人的PK)只能有一个“E”(“已注册”)状态。我不能用触发器来做这件事(因为我是从同一个表中选择的),我也不知道我是否可以用check约束来做这件事(我可以在这里使用COUNT()吗?)。感谢您的帮助

我被你的问题弄糊涂了。我猜你要么想:

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;

我被你的问题弄糊涂了。我猜你要么想:

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;

你应该可以用一个简单的方法来做这件事。为了确保每个ssn只有一个注册课程,这应该是可行的:

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

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

您应该可以使用一个。为了确保每个ssn只有一个注册课程,这应该是可行的:

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

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

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

这利用了这样一个事实,即Oracle b-tree索引不为空数据编制索引,因此索引将只包含
studclass\u 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 );

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

这利用了这样一个事实,即Oracle b-tree索引不为空数据编制索引,因此索引将只包含
studclass\u 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 );

我想你可以在插入触发器之前使用
。进行一次
计数
,如果出现问题,则
引发应用程序错误
。你试过了吗?哦,一点也不!!我可以在插入前先插入吗?如果是这样,那么一切都解决了。我去查一下,谢谢!我想你可以在插入触发器之前使用
。进行一次
计数
,如果出现问题,则
引发应用程序错误
。你试过了吗?哦,一点也不!!我可以在插入前先插入吗?如果是这样,那么一切都解决了。我去查一下,谢谢!我想防止每个学生插入一个以上的“E”状态。触发器是合适的,但据我所知,我不能在检查的同一个表上进行选择。我想防止每个学生插入多个“E”状态。触发器是合适的,但据我所知,我不能在我正在检查的同一个表上进行选择。该语法在Oracle中无效,这是问题的标记。这是罪过。我把pl/sql误读为pgsql。不过,解决方案方向仍然有效,我看到Justin Cave提供了一个Oracle-variant。这种语法在Oracle中无效,这是问题的标记。这是罪过。我把pl/sql误读为pgsql。不过,解决方案方向仍然有效,我看到Justin Cave提供了一个Oracle变体。因此,该索引应该取一个人(SSN+年)并检查该人是否已经存在“E”,我说的对吗?@user1231958-它创建了一个唯一的索引,仅当
studclass\u状态为
E
时,它才会索引
每ssn
每一年的
值。这将防止插入两行中的
studclass\u状态为
E
的值相同的
per\u ssn
per\u year
的两行。它在概念上类似于部分唯一索引,Oracle只是不支持部分唯一索引语法。因此,该索引应该取一个人(SSN+年份)并检查该人是否已经存在“E”,我说的对吗?@user1231958-它创建了一个唯一的索引,仅当
studclass\u状态为
E
时,它才会索引
每ssn
每一年的
值。这将防止插入两行中的
studclass\u状态为
E
的值相同的
per\u ssn
per\u year
的两行。它在概念上类似于部分唯一索引,Oracle只是不支持部分唯一索引语法。