инициировать исполнение против удовлетворения условия - PullRequest
0 голосов
/ 09 апреля 2010

Я создал этот триггер, который должен выдавать ошибку, всякий раз, когда значение нового rctmemenrolno таблицы-квитанций1 сопоставляется с memenrolno таблицы-меммаста, но оно выдает ошибку в обоих условиях (совпадает или не совпадает) , пожалуйста, помогите мне.

CREATE OR REPLACE TRIGGER HDD_CABLE.trg_rctenrolno
before insert ON HDD_CABLE.RECEIPTS1 for each row
declare
v_enrolno varchar2(9);
cursor c1 is select memenrolno from memmast;
begin
open c1;
fetch c1 into v_enrolno;
LOOP
    If :new.rctmemenrolno<>v_enrolno
then
raise_application_error(-20186,'PLEASE ENTER CORRECT ENROLLMENT NO');
close c1;
end if;
END LOOP;
end;

Ответы [ 2 ]

2 голосов
/ 09 апреля 2010

Вы проверяете, совпадает ли введенный RECEIPTS1.rctmemenrolno с memenrolno в MEMAST, верно? Ну, триггер это неправильный способ сделать это.

Цикл полностью не масштабируется (чем больше строк в MEMAST, тем больше времени потребуется для вставки записи в RECEIPTS1). Но даже прямой поиск для проверки наличия указанного ключа все равно будет отстой. Также этот подход не может безопасно работать в многопользовательской среде, потому что Oracle использует уровень изоляции READ COMMITTED. Другими словами, пока ваша транзакция выполняет проверку, другой сеанс удаляет только что найденную строку. Что приводит к повреждению базы данных.

Единственный правильный способ сделать это - с помощью ограничения внешнего ключа.

alter table receipt1
    add constraint receipts1_memast_fk foreign key (rctmemenrolno)
                  references memast (memenrolno);  

Конечно, это предполагает, что у вас есть первичный ключ - или уникальное ограничение - на memast для обеспечения уникальности memenrolno. Я искренне надеюсь, что вы не пытаетесь навязать его уникальность с помощью триггеров.

редактировать

«У меня уже есть 1 первичный ключ в качестве MEMID для таблицы memmast»

Если между MEMID и MEMENROLNO существует взаимно-однозначное отношение, которое является обычным явлением, когда у нас есть бизнес-ключ и суррогатный ключ, тогда правильным решением будет использование первичного ключа в RECEIPTS1. То есть отбросьте столбец RCTMEMENROL и замените его на RCTMEMID. Затем вставьте имена этих столбцов в оператор alter table. Внешний интерфейс будет отвечать за предоставление пользователям возможности поиска MEMID для данного MEMENROLNO, например виджета «Список значений».

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

Если между MEMID и MEMENROLNO нет взаимно-однозначных отношений, тогда я не знаю, какова цель проверки. Запрос на MEMAST может подтвердить существование данного MEMENROLNO сейчас , но без внешнего ключа он ничего не может сказать о состоянии базы данных через пять минут. Так зачем вообще проверять чек?

0 голосов
/ 09 апреля 2010

Похоже, что вы просматриваете все возможные значения memenrolno и проверяете, что новое значение соответствует каждому возможному значению, которое всегда будет ложным, если существует более одного возможного memenrolno.

Попробуйте вместо этого.

CREATE OR REPLACE TRIGGER HDD_CABLE.trg_rctenrolno
before insert ON HDD_CABLE.RECEIPTS1 for each row
begin
    If NOT EXISTS SELECT 1 FROM memast WHERE memenrolno = :new.rctmemenrolno
        then
            raise_application_error(-20186,'PLEASE ENTER CORRECT ENROLLMENT NO');
    end if;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...