2010-11-17 3 views
1

Я написал триггер в mysql, который проверяет, может ли человек проверить другой элемент библиотеки. Лимит проверки, который я установил, равен 3. Мне нужно преобразовать это в триггер Oracle, но у меня много проблем.mysql trigger to oracle trigger

Вот мой MySQL код:

DELIMITER // 
DROP TRIGGER IF EXISTS library.CheckBorrowsTable// 
CREATE TRIGGER CheckBorrowsTable 
BEFORE INSERT ON library.Borrows 
FOR EACH ROW 
BEGIN 
IF ((SELECT COUNT(*) FROM library.Borrows WHERE libraryID = new.libraryID) >= 3)THEN 
SET new = NULL; 
END IF; 
END// 
DELIMITER ; 

Вот мой Oracle код:

IF((SELECT COUNT(libraryID) FROM Borrows WHERE libraryID = :NEW.libraryID) >= 3) THEN 
:NEW = NULL; 
END IF; 

Есть другие части в мой код Oracle, но Oracle Express Edition добавляет эти части (начало, конец и т.д. ...)

ответ

3

Триггер уровня на таблице A (т.е. library.borrows) не может запрашивать таблицу A. Если вы это сделаете, вы получите исключение для мутирующих таблиц (если вы не можете гарантировать, что вы будете onl y всегда делают однострочные вставки с предложением VALUES). Таким образом, это не будет считаться хорошей практикой развития в Oracle.

Самый логичный способ реализации такого рода требований - не через триггер. Вместо этого, если ваше приложение вызывает API хранимой процедуры, у вас будет хранимая процедура (например, CHECK_OUT), которая сначала запрашивает таблицу, чтобы определить, сколько книг, которые человек проверил, и вставляет строку в таблицу BORROWS только в том случае, если патрон ниже его лимит.

Второй подход заключается в том, чтобы сохранить количество элементов, извлеченных в отдельной таблице. Если у вас есть таблица Меценатов с колонкой NUM_CHECKED_OUT и ваш стол заимствует был PATRON_ID, чтобы указать, кто позаимствовал книгу, триггер может сделать что-то вроде

CREATE OR REPLACE TRIGGER CheckBorrowsTable 
    BEFORE INSERT ON library.borrows 
    FOR EACH ROW 
BEGIN 
    UPDATE patrons p 
    SET p.num_checked_out = p.num_checked_out + 1 
    WHERE p.patron_id = :new.patron_id 
END; 

вместе с проверочным ограничением на столе Меценатов для того, чтобы NUM_CHECKED_OUT никогда не превышает 3.

Запрет на то, что это возможно, хотя и довольно громоздко, чтобы обойти ошибку мутирующего стола с помощью «трех триггерного решения».

  1. A Перед уровне оператора INSERT триггер очищает коллекцию, вы создали в пакете.
  2. ПЕРЕД НАЧАЛОМ ВСТАВКИ уровня строки записывает первичный ключ (или ROWID) , который изменяется в коллекции .
  3. после заявления INSERT триггер уровня считывает данные из коллекции, запрашивает таблицу, и определяет, будет ли какой-либо из вставок нарушили бизнес-правила. Если они сделали, выбросьте исключение.

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

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

+2

Следует отметить, что в многопользовательском сценарии это не сработает - два сеанса могут вставлять строки для одного и того же патрона, и оба будут обновлять таблицу патронов до того же значения, потому что они не будут видеть обновление другого сеанса , Вам потребуется сериализовать доступ к таблице патронов (например,'CHECK_OUT' сначала блокирует строку, обновляет ее, вставляет книгу, а затем фиксирует (которая освобождает блокировку)). –