Un par de comentarios sobre el DDL que publicaste.
- No hay
AUTOINCREMENT
palabra clave en Oracle. Debería crear una secuencia (generalmente una secuencia por tabla) y usarNEXTVAL
de la secuencia ya sea en elINSERT
instrucción en sí misma o en un activador para completar la clave primaria sintética. - No hay nada que esté creando un
VENUE_NO
columna enEVENT_DETAILS
. Supongo que su DDL real está definiendo esa columna.
No puede hacer cumplir esto a través de un simple CHECK
restricción. Puedes crear un disparador
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;
Tenga en cuenta, sin embargo, que
- También necesitaría tener un disparador en el
VENUE
tabla que verifica si los cambios en la capacidad del lugar causan que ciertos eventos dejen de ser válidos. En general, eso requeriría que haya algún tipo de fecha en la tabla de detalles del evento ya que, presumiblemente, la capacidad de un lugar puede cambiar con el tiempo y realmente solo desea la validación para verificar futuros eventos en ese lugar. - Las soluciones basadas en activadores no siempre funcionarán en entornos multiusuario. Imagine que el lugar 1 tiene una capacidad de 30. Ahora, la sesión A actualiza esa capacidad a 15. Pero antes de que la sesión A se comprometa, la sesión B inserta un evento con
NO_PLAYERS
de 20. Ninguno de los activadores de sesión detectará un problema, por lo que se permitirán ambos cambios. Pero una vez que ambas sesiones se comprometan, habrá un evento reservado con 20 jugadores en un lugar que solo admite 15 jugadores. El disparador enEVENT_DETAILS
potencialmente podría bloquear la fila en elVENUE
para evitar esta condición de carrera, pero está serializando inserciones y actualizaciones enEVENT_DETAILS
tabla que podría ser un problema de rendimiento, especialmente si su aplicación alguna vez espera la entrada humana antes de realizar una transacción.
Como alternativa a los disparadores, puede crear un ON COMMIT
vista materializada que une las dos tablas y coloca un CHECK
restricción en esa vista materializada que impone el requisito de que el número de jugadores no puede exceder la capacidad del lugar. Eso funcionará en un entorno multiusuario, pero requiere registros de vista materializados en ambas tablas base y mueve la verificación al punto donde se confirman las sesiones, lo que puede ser un poco complicado. La mayoría de las aplicaciones no consideran la posibilidad de que un COMMIT
La declaración podría fallar, por lo que manejar esas excepciones puede ser complicado. Y desde el punto de vista de la interfaz de usuario, puede ser algo complicado explicarle al usuario cuál es el problema, ya que la excepción puede estar relacionada con cambios realizados mucho antes en la transacción.