Problema con disparadores

EGA
17 de Noviembre del 2004
Hola!
Gracias a todos por la ayuda, pero sigo con mi mismo problema, ya que no me deja contar el número de usuarios que estan matriculados en una misma actividad, en un mismo grupo y en el mismo periodo. El problema es que no me los suma. Yo he hecho dentro del disparador una consulta que sería así:
SELECT COUNT(*)into MatriculadosActuales
FROM REALIZAN
WHERE NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND GRUPO_ACT = GrupoInsert;
Gracias de antemano y un saludo.

abouza
17 de Noviembre del 2004
Hola otra vez

No te da ningun error?

Pon todo el codigo del trigger

Un saludo

ega
17 de Noviembre del 2004
Al acceder a la tabla sobre la

ega
17 de Noviembre del 2004
Hola!
Al crear el disparador en la tabla y al intentar leer de ella, da error de tabla mutante por lo tanto, para solucionar eso cree tres disparadores distitnos. Uno para leer a nivel de columna que seria el siguiente:

-- que no le deje a mas de dos usuarios reservar el pabellon a la misma hora

CREATE OR REPLACE PACKAGE DatosMatricula AS
TYPE TipoNomActivRea IS TABLE OF REALIZAN.NOM_ACT%TYPE INDEX BY BINARY_INTEGER;
TYPE TipoPlazas_C_CR IS TABLE OF ACTIV.PLAZAS_C_CR%TYPE INDEX BY BINARY_INTEGER;
TYPE TipoPlazas_S_CR IS TABLE OF ACTIV.PLAZAS_S_CR%TYPE INDEX BY BINARY_INTEGER;
--TYPE TipoPide_CR IS TABLE OF REALIZAN.PIDE_CR%TYPE INDEX BY BINARY_INTEGER;
TYPE TipoGrupo IS TABLE OF REALIZAN.GRUPO_ACT%TYPE INDEX BY BINARY_INTEGER;
TYPE TipoCodigo IS TABLE OF REALIZAN.COD_ACT%TYPE INDEX BY BINARY_INTEGER;
TYPE TipoPeriodo IS TABLE OF REALIZAN.PERIODO_ACT%TYPE INDEX BY BINARY_INTEGER;

NomActivRealizan TipoNomActivRea;
DatosPlazas_C_CR TipoPlazas_C_CR;
DatosPlazas_S_CR TipoPlazas_S_CR;
--DatosPide_CR TipoPide_CR;
DatosGrupo TipoGrupo;
DatosPeriodo TipoPeriodo;
DatosCodigo TipoCodigo;
NumMatricula BINARY_INTEGER := 0;
END DatosMatricula;
/
El segundo disparador es para leer a nivel fila, que seria el siguiente:

-- Creamos el disparador a nivel de fila para almacenar los nuevos datos

CREATE OR REPLACE TRIGGER FilaLimiteMatriculados
BEFORE INSERT OR UPDATE OF DNI,NOM_ACT,COD_ACT,GRUPO_ACT,PERIODO_ACT,PIDE_CR ON REALIZAN
FOR EACH ROW
BEGIN

DatosMatricula.NumMatricula := DatosMatricula.NumMatricula + 1;
DatosMatricula.NomActivRealizan(DatosMatricula.NumMatricula):= :new.NOM_ACT;
DatosMatricula.DatosPeriodo(DatosMatricula.NumMatricula) := :new.PERIODO_ACT;
DatosMatricula.DatosGrupo(DatosMatricula.NumMatricula) := :new.GRUPO_ACT;
--DatosMatricula.DatosPide_CR(DatosMatricula.NumMatricula) := :new.PIDE_CR;
DatosMatricula.DatosCodigo(DatosMatricula.NumMatricula) := :new.COD_ACT;
END FilaLimiteMatriculados;
/

-- Este disparador es a nivel de orden para dar la funcionalidad que queremos

CREATE OR REPLACE TRIGGER OrdenLimiteMatriculas
AFTER INSERT OR UPDATE OF DNI,NOM_ACT,COD_ACT,GRUPO_ACT,PERIODO_ACT,PIDE_CR ON REALIZAN

DECLARE
MaxMatriculadosCON ACTIV.PLAZAS_C_CR%TYPE;
MaxMatriculadosSIN ACTIV.PLAZAS_S_CR%TYPE;
ActivInsert REALIZAN.NOM_ACT%TYPE;
GrupoInsert REALIZAN.GRUPO_ACT%TYPE;
PeriodoInsert REALIZAN.PERIODO_ACT%TYPE;
CodigoInsert REALIZAN.COD_ACT%TYPE;
MatriculadosActuales NUMBER(5);

BEGIN
FOR indice IN 1..DatosMatricula.NumMatricula LOOP
ActivInsert := DatosMatricula.NomActivRealizan(indice);
PeriodoInsert := DatosMatricula.DatosPeriodo(indice);
MaxMatriculadosSIN := DatosMatricula.DatosPlazas_S_CR(indice);
GrupoInsert := DatosMatricula.DatosGrupo(indice);
MaxMatriculadosCON := DatosMatricula.DatosPlazas_C_CR(indice);
CodigoInsert := DatosMatricula.DatosCodigo(indice);
RAISE_APPLICATION_ERROR(-20000,'holaaaaaaaaa');

SELECT PLAZAS_C_CR into MaxMatriculadosCON
FROM ACTIV,REALIZAN
WHERE ACTIV.COD = REALIZAN.COD_ACT AND ACTIV.NOM = REALIZAN.NOM_ACT AND ACTIV.GRUPO = REALIZAN.GRUPO_ACT AND ACTIV.PERIODO = REALIZAN.PERIODO_ACT AND COD_ACT = CodigoInsert AND NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND REALIZAN.GRUPO_ACT = GrupoInsert AND PIDE_CR = 'SI';

RAISE_APPLICATION_ERROR(-20000,'las varibales toman los siguientes valores: '|| ActivInsert || PeriodoInsert || GrupoInsert || PeriodoInsert || CodigoInsert);

SELECT PLAZAS_S_CR into MaxMatriculadosSIN
FROM ACTIV,REALIZAN
WHERE ACTIV.COD = REALIZAN.COD_ACT AND ACTIV.NOM = REALIZAN.NOM_ACT AND ACTIV.GRUPO = REALIZAN.GRUPO_ACT AND ACTIV.PERIODO = REALIZAN.PERIODO_ACT AND COD_ACT = CodigoInsert AND NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND REALIZAN.GRUPO_ACT = GrupoInsert AND PIDE_CR = 'NO';

RAISE_APPLICATION_ERROR(-20000,'holaaaaaaaaa');
SELECT COUNT(*)into MatriculadosActuales
FROM REALIZAN
WHERE NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND GRUPO_ACT = GrupoInsert;

MatriculadosActuales := 10;
MaxMatriculadosCON := 8;
RAISE_APPLICATION_ERROR(-20000,ActivInsert || PeriodoInsert || GrupoInsert || PeriodoInsert || CodigoInsert);
IF MatriculadosActuales > MaxMatriculadosCON THEN
RAISE_APPLICATION_ERROR(-20000,'El número de matriculados CON créditos se ha sobrepasado');
ELSIF MatriculadosActuales > MaxMatriculadosSIN THEN
RAISE_APPLICATION_ERROR(-20000,'El número de matriculados SIN créditos se ha sobrepasado');
END IF;
END LOOP;
DatosMatricula.NumMatricula := 0;

exception
When others then
DBMS_OUTPUT.PUT_LINE('ERROR');
null;
END OrdenLimiteMatriculas;
/
Gracias de antemano y un saludo

abouza
17 de Noviembre del 2004
Hola de nuevo, pedazo de chorizo que has hecho... ;)

No entiendo muy bien que has pretendido con lo que has hecho.

El error de tabla mutante sale cuando intentas actualizar la misma tabla sobre la que se esta realizando el trigger, si solo la consultas no da ese error.

He hecho una pequeña prueba.

He creado una tabla con un campo numerico, y he creado un trigger que controla el numero de registros que hay insertados y cuando llega a 10 genera una excepcion y no inserta.

create trigger basura_tg before insert on basura for each row
declare
cuenta number(4);
begin
select count(*) into cuenta from basura;
if cuenta >= 10 then
raise_APPLICATION_ERROR(-20000,'holaaaaaaaaa');
end if;
end;

Ten encuenta que la instrucción RAISE_APPLICATION_ERROR detiene la ejecución del TRIGGER

Un saludo

EGA
17 de Noviembre del 2004
hola:
Gracias por la ayuda, pero no me funciona. No se me detiene cuando se sobrepasa el valor,no se porque. Si se te ocurre porque agradeceria que me lo dijeses
Un saludo

EGA
17 de Noviembre del 2004
Hola!!
Ya lo siento ser tan pesada, pero me estoy desesperando.Abouza te he hecho caso, y he cambiado mi disparador pero al ejecutarlo me da problemas ya que me dice q no se encuentran datos. El código del disparador seria el siguiente:
CREATE OR REPLACE TRIGGER CONTROLA_MATRICULADOS
BEFORE INSERT ON REALIZAN
FOR EACH ROW

DECLARE
MatriculadosActuales number(4);
MaxMatriculadosCON number(4);
MaxMatriculadosSIN number(4);

ActivInsert REALIZAN.NOM_ACT%TYPE;
GrupoInsert REALIZAN.GRUPO_ACT%TYPE;
PeriodoInsert REALIZAN.PERIODO_ACT%TYPE;
CodigoInsert REALIZAN.COD_ACT%TYPE;

BEGIN
SELECT PLAZAS_C_CR INTO MaxMatriculadosCON
FROM ACTIV,REALIZAN
WHERE ACTIV.COD = REALIZAN.COD_ACT AND ACTIV.NOM = REALIZAN.NOM_ACT AND ACTIV.GRUPO = REALIZAN.GRUPO_ACT AND ACTIV.PERIODO = REALIZAN.PERIODO_ACT AND COD_ACT = CodigoInsert AND NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND REALIZAN.GRUPO_ACT = GrupoInsert AND PIDE_CR = \'SI\';


SELECT PLAZAS_S_CR INTO MaxMatriculadosSIN
FROM ACTIV,REALIZAN
WHERE ACTIV.COD = REALIZAN.COD_ACT AND ACTIV.NOM = REALIZAN.NOM_ACT AND ACTIV.GRUPO = REALIZAN.GRUPO_ACT AND ACTIV.PERIODO = REALIZAN.PERIODO_ACT AND COD_ACT = CodigoInsert AND NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND REALIZAN.GRUPO_ACT = GrupoInsert AND PIDE_CR = \'NO\';


SELECT COUNT(*)INTO MatriculadosActuales
FROM REALIZAN
WHERE NOM_ACT = ActivInsert AND PERIODO_ACT = PeriodoInsert AND GRUPO_ACT = GrupoInsert;

if MatriculadosActuales >= MaxMatriculadosCON then
raise_APPLICATION_ERROR(-20000,\'holaaaaaaaaa\');
elsif MatriculadosActuales >= MaxMatriculadosSIN then
raise_APPLICATION_ERROR(-20000,\'holaaaaaaaaa2\');
end if;
end;
/
Me dice que no encuentra datos porque es necesario introducir los datos ya que en el select compara con los datos que introducimos para así coger el numero de matriculados que puede haber en una actividad y como he puesto "before insert" pues los intenta comparar antes de que yo haya introducido los valores correspondientes pero si pongo "after insert" me da error de tablas mutantes. Por favor ayudame q me estoy desesperandoo!!!!
Gracias de antemano
Un saludo

Jos?ntonio
17 de Noviembre del 2004
Hola,

Yo creo que el problema esta en el select count(*) que no lo debes hacer bien ya que para el periodo le pones un = cuando debería ser un between. Revisalo y haz pruebas desde fuera.

Saludos

pepillo grillo
17 de Noviembre del 2004
me teneis hasta los huevos.... y tu inepta deja de dar porculo , ya te han dado 6 soluciones... no crees que es bastante pedazo de zorrón? anda a mamarla al foro "oracle para inutiles" no en este.

EGA
17 de Noviembre del 2004
hola:
Gracias por la ayuda, pero no me funciona. No se me detiene cuando se sobrepasa el valor,no se porque. Si se te ocurre porque agradeceria que me lo dijeses
Un saludo