Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Oracle »

Como evitar el insert del before insert.

Estas en el tema de Como evitar el insert del before insert. en el foro de Oracle en Foros del Web. Buenas tardes a todos y gracias por su ayuda. Tengo que realizar la siguiente acción, cuando el usuario inserte un nuevo registro, debo de checar ...
  #1 (permalink)  
Antiguo 17/12/2012, 17:39
 
Fecha de Ingreso: abril-2005
Mensajes: 124
Antigüedad: 19 años
Puntos: 0
Como evitar el insert del before insert.

Buenas tardes a todos y gracias por su ayuda.

Tengo que realizar la siguiente acción, cuando el usuario inserte un nuevo registro, debo de checar si este existe, en caso de existir solo debo actualizar ciertos campos, de lo contrario inserto el registro.

Entonces para lo anterior ocupe un trigger con la función before insert, el problema es cuando actualiza porque resulta que realiza la actualización pero al mismo tiempo me genera el registro. quise evitar la acción del insert con un raise application error que efectivamente me evita el insert, pero no realiza el update.

este es mi codigo:

Código SQL:
Ver original
  1. CREATE OR REPLACE TRIGGER tr_polizasprueba
  2. BEFORE INSERT ON polizasprueba
  3. REFERENCING NEW AS NEW FOR each ROW
  4.   DECLARE
  5.   existe INTEGER;
  6. BEGIN
  7.    SELECT COUNT(*) INTO existe FROM polizasprueba
  8.      WHERE TIPOPOLIZA = :NEW.TIPOPOLIZA AND FOLIO = :NEW.FOLIO AND to_char((FECHA),'yyyy') = to_char((:NEW.FECHA),'yyyy');
  9.      IF existe >0 THEN
  10.         UPDATE admin.polizasprueba
  11.         SET CLASE = :NEW.CLASE,IDDIARIO = :NEW.IDDIARIO,CONCEPTO = :NEW.CONCEPTO,
  12.             SISTEMAORIGEN = :NEW.SISTEMAORIGEN,IMPRESA = :NEW.IMPRESA,IDUSUARIO = :NEW.IDUSUARIO,
  13.             FECHAALTA = :NEW.FECHAALTA,BALANCEADA = :NEW.BALANCEADA
  14.         WHERE TIPOPOLIZA = :NEW.TIPOPOLIZA AND FOLIO = :NEW.FOLIO AND to_char((FECHA),'yyyy') = to_char((:NEW.FECHA),'yyyy');
  15.         RAISE_APPLICATION_ERROR(-20000, 'no quiero realizar el insert');
  16.      END IF;
  17. END;

De hecho intente conel rollback y me genera el mismo resultado. tienen alguna consejo? gracias.

Última edición por gnzsoloyo; 18/12/2012 a las 09:24 Razón: Código SQL sin etiquetar. Usar Highlight "SQL".
  #2 (permalink)  
Antiguo 17/12/2012, 19:31
 
Fecha de Ingreso: enero-2009
Mensajes: 32
Antigüedad: 15 años, 3 meses
Puntos: 2
Respuesta: Como evitar el insert del before insert.

Forma parte todo de la misma transacción. Si haces un RAISE finalmente no se realiza el COMMIT.

Si en cualquier caso quieres que el update se realice de modo independiente al insert deberías realizarlo encapsulado dentro de un PROCEDURE con el PRAGMA AUTONOMOUS_TRANSACTION. De ese modo al ser una transacción diferente si que podrás hacerlo.

Investiga sobre eso y si tienes dudas plantéalas, te responderé encantado.

Un saludo.
__________________
Anotaciones de un programador
  #3 (permalink)  
Antiguo 17/12/2012, 21:37
 
Fecha de Ingreso: abril-2005
Mensajes: 124
Antigüedad: 19 años
Puntos: 0
Respuesta: Como evitar el insert del before insert.

Gracias morway por tu ayuda, mira quedo asi:
Código SQL:
Ver original
  1. CREATE OR REPLACE TRIGGER tr_polizasprueba
  2. BEFORE INSERT ON polizasprueba
  3. REFERENCING NEW AS NEW
  4. FOR EACH ROW
  5. DECLARE
  6.   existe INTEGER;
  7. BEGIN
  8.    SELECT COUNT(*) INTO existe FROM polizasprueba
  9.      WHERE TIPOPOLIZA = :NEW.TIPOPOLIZA AND FOLIO = :NEW.FOLIO AND to_char((FECHA),'yyyy') = to_char((:NEW.FECHA),'yyyy');
  10.      IF existe >0 THEN
  11.         UPDATE polizasprueba
  12.         SET CLASE = :NEW.CLASE,IDDIARIO = :NEW.IDDIARIO,CONCEPTO = :NEW.CONCEPTO,
  13.             SISTEMAORIGEN = :NEW.SISTEMAORIGEN,IMPRESA = :NEW.IMPRESA,IDUSUARIO = :NEW.IDUSUARIO,
  14.             FECHAALTA = :NEW.FECHAALTA,BALANCEADA = :NEW.BALANCEADA
  15.         WHERE TIPOPOLIZA = :NEW.TIPOPOLIZA AND FOLIO = :NEW.FOLIO AND to_char((FECHA),'yyyy') = to_char((:NEW.FECHA),'yyyy');
  16.        RAISE_APPLICATION_ERROR('No registrar el insert');
  17.         procerror;
  18.      END IF;
  19. END;

solo agregueas lineas en rojo y en la sección de procedimientos, quedo asi:
Código SQL:
Ver original
  1. CREATE OR REPLACE PROCEDURE procerror IS
  2. PRAGMA AUTONOMOUS_TRANSACTION;
  3. BEGIN
  4. ROLLBACK;
  5. DBMS_OUTPUT.PUT_LINE('rollback ejecutado');
  6. END procerror;

solo que a la hora de compilarlo me marca estos errores:

Error(17,9): PL/SQL: Statement ignored
Error(17,9): PLS-00306: número o tipos de argumentos erróneos al llamar a 'RAISE_APPLICATION_ERROR'


voy a intentar encontrarlos errores y ejecutarlo, pero mas o menos es así como me recomendaste?

gracias.

Última edición por gnzsoloyo; 18/12/2012 a las 09:26 Razón: Código SQL sin etiquetar. Usar Highlight SQL
  #4 (permalink)  
Antiguo 18/12/2012, 04:47
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 16 años, 10 meses
Puntos: 43
Respuesta: Como evitar el insert del before insert.

Antes que nada, un consejillo.

Cuando te salta un error, si no sabes de que vá, lo tecleas en el google y te das un rulo por los resultados que te saque, te aseguro que en muchas ocasiones es mas rápido que postearlo en un foro y si no ves nada que te lo aclare, entonces es el momento de postear en los foros.

Y ahora..... el error que te está dando es por que le tienes que meter un código a la descripción, ls sintaxis correcta sería ésta :

Código SQL:
Ver original
  1. RAISE_APPLICATION_ERROR(-20001, 'No registrar el insert');

Entonces al hacer el raise, te mostraría algo similar a esto :

Código SQL:
Ver original
  1. ORA-20001 No registrar el INSERT
  #5 (permalink)  
Antiguo 18/12/2012, 14:44
 
Fecha de Ingreso: enero-2009
Mensajes: 32
Antigüedad: 15 años, 3 meses
Puntos: 2
Respuesta: Como evitar el insert del before insert.

Hola, de nuevo compañero.

Pensaba que el update que hacías era para otra tabla. Lo que pretendes, a mi modo de ver parece demasiado rebuscado. desde el trigger BEFORE INSERT no tiene sentido forzar un UPDATE y cancelar el INSERT. Seguramente tendrás problemas por MUTATING del registro que estás insertando/actualizando.

Deberías plantearte encapsular esa funcionalidad que necesitas en un procedimiento que haga el INSERT o UPDATE según corresponda.

Ejemplo:

Código SQL:
Ver original
  1. CREATE OR REPLACE PROCEDURE P_GUARDAR_POLIZA( P_POLIZA IN POLIZASPRUEBA%ROWTYPE ) IS
  2.   --
  3.   v_NUMERO_POLIZAS NUMBER ;
  4.   --
  5. BEGIN
  6.   --
  7.   SELECT COUNT(*)
  8.    INTO v_NUMERO_POLIZAS
  9.      ...
  10.      ...
  11.  
  12.   IF V_NUMERO_POLIZAS > 0 THEN
  13.     --
  14.     UPDATE ...........
  15.     --
  16.   ELSE
  17.     --
  18.     INSERT .......
  19.     --
  20.   END IF;
  21.   --
  22. END;

Ago así, espero que te sirva.

Un saludo.
__________________
Anotaciones de un programador
  #6 (permalink)  
Antiguo 18/12/2012, 16:18
 
Fecha de Ingreso: abril-2005
Mensajes: 124
Antigüedad: 19 años
Puntos: 0
Respuesta: Como evitar el insert del before insert.

Gracias morway por tu consejo, de hecho hice esto con anterioridad y me funciono perfectamente:

Código SQL:
Ver original
  1. MERGE INTO POLIZASPRUEBA pp
  2. USING (
  3. SELECT 1 IDPOLIZA
  4. ,DATE '04-01-12' FECHA
  5. ,1 TIPOPOLIZA
  6. ,100 CLASE
  7. ,00 IDDIARIO
  8. ,'abcdefg' CONCEPTO
  9. ,1 SISTEMAORIGEN
  10. ,2 IMPRESA
  11. ,7 IDUSUARIO
  12. ,'11/12/2012' FECHAALTA
  13. ,1 BALANCEADA
  14. ,00000032 FOLIO
  15. FROM dual
  16. ) p
  17. ON (pp.TIPOPOLIZA = p.TIPOPOLIZA AND pp.FOLIO =p.FOLIO AND to_char((pp.FECHA),'yyyy') = to_char((p.FECHA),'yyyy'))
  18. WHEN NOT MATCHED THEN
  19. INSERT VALUES (p.IDPOLIZA,p.FECHA,p.TIPOPOLIZA,p.CLASE,p.IDDIARIO,p.CONCEPTO,p.SISTEMAORIGEN,
  20. p.IMPRESA,p.IDUSUARIO,p.FECHAALTA,p.BALANCEADA,p.FOLIO)
  21. WHEN MATCHED THEN
  22. UPDATE SET pp.CLASE = p.CLASE,pp.IDDIARIO = p.IDDIARIO,pp.CONCEPTO = p.CONCEPTO,
  23. pp.SISTEMAORIGEN = p.SISTEMAORIGEN,pp.IMPRESA = p.IMPRESA,pp.IDUSUARIO = p.IDUSUARIO,
  24. pp.FECHAALTA = p.FECHAALTA,pp.BALANCEADA = p.BALANCEADA;

lo malo esque el merge into no funciona en los triggers, y mis superiores quieren que esto se haga cuando se ejecuta el insert, sabes como puedo meterlo a parte del before insert, mucho te lo agradecería, digo la funcion se hacerla igual que el procedimiento, pero a que horas los llamo?

gracias

Última edición por gnzsoloyo; 20/12/2012 a las 09:48 Razón: Código SQL sin etiquetar. Por favor usar Highlight "SQL"
  #7 (permalink)  
Antiguo 18/12/2012, 18:13
 
Fecha de Ingreso: enero-2009
Mensajes: 32
Antigüedad: 15 años, 3 meses
Puntos: 2
Respuesta: Como evitar el insert del before insert.

Deberías llamar al procedimiento desde el punto de la aplicación en el cual insertas en polizaprueba y en lugar de hacer un MERGE, un INSERT o UPDATE, llamar al proceso que lo gestiona.

Código SQL:
Ver original
  1. DECLARE
  2.   v_POLIZA  POLIZAPRUEBA%ROWTYPE ;
  3. BEGIN
  4.   v_POLIZA.IDPOLIZA     := 1 ;
  5.   v_POLIZA.TIPOPOLIZA := 1;
  6.   v_POLIZA.CLASE         := 100 ;
  7.   ...
  8.   ...
  9.   ...
  10.   P_GUARDAR_POLIZA( P_POLIZA => v_POLIZA);
  11. END;

Un saludo
__________________
Anotaciones de un programador

Etiquetas: insert, select, trigger, update
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:39.