Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Trigger para eliminar en cascada master/detail (https://www.clubdelphi.com/foros/showthread.php?t=70786)

tgsistemas 10-11-2010 18:04:05

Trigger para eliminar en cascada master/detail
 
Hola a tod@s :

trabajo con D7, tengo una bbdd en SQL 2005 Express con unas tablas Master / Detail y he creado el siguiente trigger en la tabla Master (AREC01E) para que al eliminar un registro, elimine en cascada los registros de la tabla Detail (AREC02E) que le corresponden.

El trigger es :

Código SQL [-]
ALTER TRIGGER [dbo].[del_areae] ON [dbo].[AREC01E] for delete as
declare @CDGOTEMP integer
begin
  SELECT @CDGOTEMP = CDGO FROM DELETED
  DELETE FROM AREC02E WHERE CDGOCAB = @CDGOTEMP
end

el trigger funciona correctamente si la tabla detail (AREC02E) tiene un único registro pero el problema viene cuando la tabla detail tiene más de un registro y produce el
Código:

"error información de columna clave insuficiente o incorrecta, demasiadas filas afectadas por la actualización"
qué es lo que estoy haciendo mal ???

muchas gracias a tod@s por la ayuda

Al González 10-11-2010 19:29:28

Hola Toni.

No necesitas un disparador para la eliminación en cascada.

Basta con que la restricción de llave foránea de la tabla detalle esté creada con la opción "On Delete Cascade".

http://www.mssqlcity.com/Articles/Ge...onstraints.htm

Saludos.

BlueSteel 10-11-2010 21:30:30

Cita:

Empezado por Al González (Mensaje 381968)
Hola Toni.

No necesitas un disparador para la eliminación en cascada.

Basta con que la restricción de llave foránea de la tabla detalle esté creada con la opción "On Delete Cascade".

http://www.mssqlcity.com/Articles/Ge...onstraints.htm

Saludos.


No sabia de esto... muy buen aporte... y yo que me daba el trabajo de borrar todo...

duilioisola 10-11-2010 23:06:20

Es verdad lo de la llave foranea, pero no resuelve todos los casos.
El error que tiene tu trigger parece ser que es que debes utilizar un bucle para seleccionar cada línea y borrarla.

No conozco SQL Server, pero supongo que debe ser algo así:

Código SQL [-]
ALTER TRIGGER [dbo].[del_areae] ON [dbo].[AREC01E] for delete as
declare @CDGOTEMP integer
begin
  FOR SELECT @CDGOTEMP = CDGO FROM DELETED
  BEGIN
     DELETE FROM AREC02E WHERE CDGOCAB = @CDGOTEMP
  END
end

Resolver este problema te servirá por ejemplo cuando quieras guardar registros borrados en un log o hacer algunos recálculos sobre terceras tablas por cada registro borrado.

BlueSteel 11-11-2010 00:11:07

Cita:

Empezado por duilioisola (Mensaje 382004)
Es verdad lo de la llave foranea, pero no resuelve todos los casos.
El error que tiene tu trigger parece ser que es que debes utilizar un bucle para seleccionar cada línea y borrarla.

Hace un tiempo yo lo hacia con cursores.... deja buscar un ejemplo y lo dejo...

Salu2:p:D

BlueSteel 11-11-2010 00:16:16

Aqui te dejo el ejemplo
Código SQL [-]
Create TRIGGER [Producto_Update]
   ON  [dbo].[Producto]
   FOR Update
AS 
BEGIN
    SET NOCOUNT ON;

    -- Sentencia que cuenta cuantos registros se eliminaran..
    -- Si son más de uno.. da error
/*    if ((Select Count(*) From Deleted) > 1) 
    Begin
         RaisError(' Quiere Eliminar mas de uno',16,1)
         Rollback Transaction 
    End
    
    -- Sentencia que verifica que el dato no este en otra tabla
    -- de lo contrario no elimina...
    if Exists(Select 1 From DVenta
              Where DVenta.Pro_Codigo in
                    (Select Deleted.Pro_Codigo From Deleted))
    Begin
         RaisError(' No se puede eliminar',16,1)
         Rollback Transaction 
    End


    if Exists(Select 1 From Venta, DVenta, updated
              Where Venta.Vta_Numero = DVenta.Vta_Numero
                And DVenta.Pro_Codigo = Updated.Pro_Codigo)
    Begin
         RaisError(' Existe',16,1)
         Rollback Transaction 
    End
*/
   -- Declaración de Cursores
    
    Declare @Codigo Int,
            @Descripcion Varchar(10)

    Declare  Cur_Prueba Cursor
    For Select Pro_Codigo, Pro_Detalle For Update

    Open Cur_Prueba

    Fetch Next From Cur_Prueba Into @Codigo, @Descripcion

    While @@Fetch_Status = 0
    Begin
         /*
         */
         Fetch Next From Cur_Prueba Into @Codigo, @Descripcion
    End

    Close Cur_Prueba
    DealLocate Cur_Prueba    
    
END

bueno, esto es un ejemplo que vi en un curso de SQL.... aunque aqui utiliza el Update... tendrias que cambiar por Delete....

Salu2

ASAPLTDA 11-11-2010 15:07:52

Comentario
 
DELETE FROM AREC02E WHERE CDGOCAB = @CDGOTEMP
Esta instruccion borrara todos los registros de la trabla sin usar cursor. No sera que tienes un trigger asociados a la tabla AREC02E?

tgsistemas 15-11-2010 16:36:51

uffff me había centrado en otro proceso del programa que fallaba y no he estado atento a vuestras respuestas... os pido disculpas a todos!!!!.

Esta aplicación la desarrollé hace tiempo en D7 y SQL2000 conectando con BDE, ahora estaba haciendo una nueva versión del programa utilizando ADO contra SQL2005 Express por cuestiones de costes para los clientes ;)

Ese trigger funcionaba correctamente en SQL2000 tal y como está, aunque para evitar sorpresas creo que me instalaré un SQL2000 para hacer pruebas y estar seguro.

Al Gonzalez.... he mirado muy por encima la info que me indicas y voy a estudiarla a fondo ahora que tengo más tiempo. Muchas Gracias

Duiliosola.... no soy un experto con SQL pero ese trigger funcionaba correctamente en SQL2000. De todas formas lo voy a comprobar ;)

BlueSteel... gracias por el ejemplo, lo voy a tener en cuenta ;)

ASAPLTDA..... la tabla AREC02E (detail) no tiene ningún trigger.

Gracias a todos por las respuestas, os pido disculpas de nuevo por no contestar antes y si alguien ve dónde puede estar el error o qué estoy haciendo mal... que no dude en decirlo!!!!

tgsistemas 17-01-2011 09:49:00

solucionado
 
bueno tras más de dos meses en producción puedo asegurar que la opción que propuso Al Gonzalez funciona a las mil maravillas.... muchas gracias!!!! :D:D:D


La franja horaria es GMT +2. Ahora son las 08:56:20.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi