我有一张类似
的表格MyTable (
Student ID,
Exam)
我想放置一个触发器/约束来描述:
学生ID可以多次出现,而不必是唯一的。但是,该对(学生ID,“法语”)只能出现一次。因此每个学生只能有一个“法国”条目。法语是硬编码的
ID Exam 0001 German 0001 History 0001 French 0001 French <-- This insert should fail.
注意将“德语”字段更新为法语也应该失败
到目前为止,我已经尝试了
CREATE OR REPLACE TRIGGER MyTrigger BEFORE INSERT OR UPDATE ON MyTable
FOR EACH ROW
DECLARE
rowsCount INTEGER;
BEGIN
select count(*)
INTO rowsCount
from MyTable sc
where SC.SC_TYPE = 'FRENCH' and :new.StudentID = sc.StudentID;
IF rowsCount > 1
THEN
raise_application_error('-20098','You cannot have more than one French record per student.');
END IF;
end;
但是这会抛出一个Mutate错误。无论如何,这与诚信有关,所以我确定一个约束会更好,但是会对如何实现这一点提出一些建议。
答案 0 :(得分:3)
是的,法语每个学生只能出现一次,但其他一切都可以出现多次。
我想也许用索引最好解决这个问题?类似于:Oracle SQL Constraint where clause
CREATE UNIQUE INDEX MyIndex ON MyTable(
CASE WHEN Exam= 'French'
THEN StudentID
ELSE NULL
END
);
答案 1 :(得分:1)
由于限制的特殊性(只限法语)我不认为这可以用约束来做(虽然我很乐意另外学习)。解决问题的一种方法是使用语句触发器:
CREATE OR REPLACE TRIGGER NO_DUPLICATE_FRENCH_TRIGGER
BEFORE INSERT OR UPDATE
ON MY_TABLE
-- NOTE: NO 'FOR EACH ROW', which means this is fired once for each
-- statement executed, rather than once for each row modified.
DECLARE
nMax_count NUMBER;
BEGIN
SELECT MAX(COUNT_VAL)
INTO nMax_count
FROM (SELECT STUDENTID, COUNT(*) AS COUNT_VAL
FROM MY_TABLE
WHERE EXAM = 'FRENCH'
GROUP BY STUDENTID);
IF nMax_count > 1 THEN
RAISE SOME_EXCEPTION;
END IF;
END NO_DUPLICATE_FRENCH_TRIGGER;
语句触发器的优点是它们不像行触发器那样受“变异表”问题的影响。但是,这有点像kluge,引入了全表扫描,如果表很大可能是性能问题,但至少它是一个解决方案。
分享并享受。
答案 2 :(得分:0)
我建议你创建3个触发器和一个包来处理这个验证。
您只能将带有Exam ='French'的记录添加到PL / SQL表中,并检查该学生是否已对该数据库进行法语考试。
答案 3 :(得分:0)
这个怎么样?
alter table MyTable add constraint std_exam unique(Student ID,Exam);