2014-02-06 2 views
0

У меня есть таблица, которая выглядит какTrigger/Constraint ограничить вставки или обновления

MyTable (
Student ID, 
Exam) 

Я хочу, чтобы поместить триггер/ограничение, которое описывает:

Студент ID может появиться много раз и не должны быть уникальными. Однако пара (идентификатор студента, «французский») может появляться только один раз. Поэтому каждый студент может иметь только одну «французскую» запись. Французский зашиты

 
ID Exam 

0001 German 
0001 History 
0001 French 
0001 French <-- This insert should fail. 

Attemting обновить «Немецкий» поле Французский должен также не

До сих пор я пытался

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; 

Это бросает мутировать ошибку, хотя. Во всяком случае, это связано с целостностью, поэтому я уверен, что ограничение будет лучше, но будет признателен за некоторые советы о том, как это сделать.

+0

Таким образом, ограничение на 'French' специфично, и им должно быть разрешено иметь несколько строк с' German'? –

ответ

3

Да, французский язык может появляться только один раз на одного учащегося, но все остальное может появляться несколько раз.

Я думаю, что это лучше всего решить с помощью индекса? Аналогично: Oracle SQL Constraint where clause

CREATE UNIQUE INDEX MyIndex ON MyTable(
    CASE WHEN Exam= 'French' 
     THEN StudentID 
     ELSE NULL 
    END 
); 
+0

Это тоже не сработает.Если у вас один и тот же экзамен, сделанный несколько раз любым учеником, вторая вставка не удастся. Даже если вы измените индекс на '(StudentID, CASE WHEN EXAM = 'French' THEN StudentID ELSE NULL END)' он все равно будет терпеть неудачу во второй раз, если для данного ученика вставлен не "французский" язык, по крайней мере, под Oracle 11.1. [SQLFiddle здесь] (http://sqlfiddle.com/#!4/f8cdd9/1) –

+1

Как только оператор case в определении индекса должен быть в порядке. Если вы удалите столбец student_id из индекса в sqlfiddle, тогда все будет в порядке. –

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, вводит полное сканирование таблицы, и если таблица большая, может быть проблема с производительностью, но по крайней мере это решение.

Делитесь и наслаждайтесь.

0

Предлагаю вам создать три триггера и пакет для обработки этой проверки.

  • 1 пакет с таблицей PL/SQL и процедурами, которые будут вызываться вашими триггерами.
  • 1 перед запуском оператора, чтобы очистить таблицу PL/SQL.
  • 1 до (или после) каждого триггера строки, чтобы добавить в таблицу PL/SQL записи, которые вы вставляете/обновляете.
  • 1 после триггера оператора для выполнения проверки на основе заполненной таблицы PL/SQL.

Вы можете добавить в таблицу PL/SQL только записи с экзаменом = 'Французский' и проверить, есть ли у студента французский экзамен в базе данных.

0

Как насчет этого?

изменить таблицу MyTable добавить ограничение std_exam unique (ID студента, экзамен);

Смежные вопросы