sql >> Base de Datos >  >> RDS >> Oracle

Oracle:problema al crear un disparador que actualiza otra tabla

Algunos números sin ningún orden en particular.

Primero, en el cuerpo de un activador de nivel de fila, debe usar :new y :old para hacer referencia a los registros nuevos y antiguos. Los dos puntos principales son necesarios. Así que tu WHERE la cláusula tendría que ser

WHERE PROJECTID = :new.PROJECTID

En segundo lugar, si está ejecutando su CREATE TRIGGER en SQL*Plus, puede obtener una lista de errores y advertencias usando SHOW ERRORS comando, es decir,

SQL> show errors

También puede consultar el DBA_ERRORS tabla (o ALL_ERRORS o USER_ERRORS dependiendo de su nivel de privilegio), pero eso no es algo a lo que normalmente deba recurrir.

En tercer lugar, suponiendo que se corrijan los errores de sintaxis, obtendrá un mutante error de tabla si usas esta lógica. Un activador de nivel de fila en la tabla A (TPM_TRAININGPLAN en este caso) no puede consultar la tabla A porque la tabla puede estar en un estado inconsistente. Puede solucionar eso, como muestra Tim en su artículo, creando un paquete con una colección, inicializando esa colección en un disparador de declaración anterior, completando los datos en la colección en un disparador de nivel de fila y luego procesando las filas modificadas en un disparador de declaración posterior. Sin embargo, esa es una cantidad decente de complejidad para agregar al sistema, ya que tendrá que administrar múltiples objetos diferentes.

En general, sería mejor implementar esta lógica como parte de cualquier API que use para manipular el TPM_TRAININGPLAN mesa. Si ese es un procedimiento almacenado, tiene mucho más sentido poner la lógica para actualizar TPM_PROJECT en ese procedimiento almacenado en lugar de ponerlo en un disparador. Es notoriamente doloroso tratar de depurar una aplicación que tiene mucha lógica incrustada en los disparadores porque eso hace que sea muy difícil para los desarrolladores seguir exactamente qué operaciones se están realizando. Como alternativa, puede eliminar el TRAININGDELIVERYSTART columna de TPM_PROJECT tabla y simplemente calcule la fecha de inicio mínima en tiempo de ejecución.

En cuarto lugar, si su activador se activa en inserciones, actualizaciones y eliminaciones, no puede simplemente hacer referencia a :new valores. :new es válido para inserciones y actualizaciones, pero será NULL si está realizando una eliminación. :old es válido para eliminaciones y actualizaciones, pero será NULL si está haciendo una inserción. Eso significa que probablemente necesite tener una lógica similar a (haciendo referencia a la solución del paquete de Tim)

BEGIN
  IF inserting 
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
  ELSIF updating
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
  ELSIF deleting
  THEN
    trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
  END IF;
END;