Няколко коментара за DDL, който публикувахте.
- Няма
AUTOINCREMENT
ключова дума в Oracle. Ще трябва да създадете последователност (обикновено една последователност на таблица) и да използватеNEXTVAL
от последователността или вINSERT
самият оператор или в тригер за попълване на синтетичния първичен ключ. - Няма нищо, което да създава
VENUE_NO
колона вEVENT_DETAILS
. Предполагам, че вашият действителен DDL дефинира тази колона.
Не можете да наложите това чрез обикновена CHECK
ограничение. Можете да създадете тригер
CREATE OR REPLACE TRIGGER validate_capacity
BEFORE INSERT OR UPDATE ON event_details
FOR EACH ROW
DECLARE
l_venue_capacity venue.capacity%type;
BEGIN
SELECT capacity
INTO l_venue_capacity
FROM venue
WHERE venue_no = :new.venue_no;
IF( l_venue_capacity < :new.no_players )
THEN
RAISE_APPLICATION_ERROR( -20001, 'Sorry, the venue has insufficient capacity' );
END IF;
END;
Имайте предвид обаче, че
- Ще трябва също така да имате тригер на
VENUE
таблица, която проверява дали промените в капацитета на мястото причиняват определени събития да станат невалидни. Като цяло, това би изисквало да има някаква дата в таблицата с подробности за събитието, тъй като, вероятно, капацитетът на дадено място може да се промени с течение на времето и вие наистина искате валидирането само да проверява за бъдещи събития в това място. - Решенията, базирани на тригери, не винаги работят в среди с много потребители. Представете си, че място 1 има капацитет от 30. Сега сесия A актуализира този капацитет до 15. Но преди сесия A да се ангажира, сесия B вмъква събитие с
NO_PLAYERS
от 20. Тригерът на нито една сесия няма да види проблем, така че и двете промени ще бъдат разрешени. Но след като и двете сесии се обвържат, ще има резервирано събитие с 20 играчи в място, което поддържа само 15 играчи. Задействането наEVENT_DETAILS
потенциално може да заключи реда вVENUE
таблица, за да избегнете това състояние на състезание, но вие сериализирате вмъквания и актуализации наEVENT_DETAILS
таблица, което може да бъде проблем с производителността, особено ако вашето приложение някога чака човешки вход, преди да извърши транзакция.
Като алтернатива на тригерите можете да създадете ON COMMIT
материализиран изглед, който свързва двете таблици и поставя CHECK
ограничение върху този материализиран изглед, който налага изискването броят на играчите да не може да надвишава капацитета на мястото. Това ще работи в многопотребителска среда, но изисква материализирани изгледи на регистрационни файлове на двете базови таблици и премества проверката до точката, където сесиите се ангажират, което може да бъде малко трудно. Повечето приложения не отчитат възможността COMMIT
може да се провали, така че обработката на тези изключения може да бъде трудна. И от гледна точка на потребителския интерфейс, може да бъде малко трудно да се обясни на потребителя какъв е проблемът, тъй като изключението може да се отнася до промени, направени много по-рано в транзакцията.