none
Borrar registros de 2 tablas relacionadas RRS feed

  • Pregunta

  • Buen día a todos,

    Tengo tres tablas:

    1. Usuarios
    2. Telefonos
    3. UsuarioTelefono

    La tabla UsuarioTelefono tiene los campos idUsuario y idTelefono los cuales son llaves foraneas a las otras tablas.

    Quiero borrar todos los telefonos del usuario con id x

    ¿Como puedo lograr esto?

    De antemano gracias

    lunes, 20 de julio de 2015 15:45

Respuestas

  • -- Declaro una tabla que almacene los teléfonos borrados
    
    declare @UsuariosTelefonos_del table(idtelefono int)
    
    -- abro una transacción si se produce un error no quier oque se borre de una tabla si y otra no 
    
    
    begin tran
    
    -- borro marcando output del campo idtelefono a la tabla que he declarado (es una variable)
    delete from UsuariosTelefonos
    output deleted.idtelefono into @UsuariosTelefonos_del;
    
    
    -- ahora borro de la tabla teléfonos usando la variable tabla para hacer un inner yoin 
    delete t from  telefonos t inner join @UsuariosTelefonos_del d on t.idtelefono=d.idtelefono
    
    
    -- valido la transacción 
    commit
    
    

    el código completo es

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    martes, 21 de julio de 2015 19:07
    Moderador

Todas las respuestas

  • Hola jeduardonl,

    Lo que mencionas es bastante simple a menos que no estés otorgándonos todos los alcances. Si lo que requieres es eliminar los teléfonos de un determinado usuario entonces no queda más que hacer lo siguiente:

    delete UsuarioTelefono where (idUsuario = @idUsuario);


    Ahora, lo que no me queda claro es el objetivo de la tabla Teléfonos, ¿qué contiene esa tabla? ¿números de teléfono o operadores telefónicos?. De contener números de teléfono me parece incorrecto como lo has modelado a menos que un número de teléfono pertenezca a mas de un usuario. Pienso que sólo deberías tener 2 tablas: Usuarios y TelefonosUsuarios, incluso, podrías definir una regla de integridad referencial para que borre en cascada los registros de los teléfonos cuando borres un usuario.

    Si tienes alguna duda de lo mencionado no dudes en consultarlo.

    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.

    Willams Morales
    Arequipa - PERÚ

    lunes, 20 de julio de 2015 15:50
  • Hola

    William si mal no entiendo el quiere borrar los telefonos sin borrar el usuario, pero estan ligadas, primero pense en si tenian relación por cascada pero no creo que el aproach sea el correcto, tomaria 2 queries en mi opinion no se me ocurre sin hacer una variable que obtenga el idtelefono.  

    lunes, 20 de julio de 2015 15:54
  • declare @UsuariosTelefonos_del table(idtelefono int) begin tran delete from UsuariosTelefonos output deleted.idtelefono into @UsuariosTelefonos_del; delete t from telefonos t inner join @UsuariosTelefonos_del d on t.idtelefono=d.idtelefonodeclare @idusuario intset @idusuario=12345begin trandelete from usuariosTelefonos

    commit


    Creo que te refieres a algo así.


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA


    lunes, 20 de julio de 2015 15:58
    Moderador
  • Que tal,

    Para evitar errores por integridad referencial, elimina primero las tablas donde están las referencias, en este caso este sería el orden:

    delete from UsuarioTelefono where idUsuario = @idUsuario; 
    delete from Telefono where idUsuario = @idUsuario;

    Saludos!


    Ayacucho - Perú
    Recuerda si mi solución atiende tu consulta por favor márcala como útil y como respuesta.

    http://litigiouslobo.blogspot.com/
    El Blog de Herbert Mendoza

    • Editado Nathán XS lunes, 20 de julio de 2015 16:03
    lunes, 20 de julio de 2015 15:58
  • Gracias, quiza efectivamente no me exprese bien, lo que realmente quiero es borrar todos los telefonos de el usuario cuyo id es x, pero quiero borrarlos de la tabla Telefonos, dado que la tabla telefonos esta relacionada con la tabla UsuarioTelefono, se tienen que borrar tambien esas relaciones.
    lunes, 20 de julio de 2015 15:58
  • Entonces creo que es lo que te acabo de contestar, dale una vuelta.

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    lunes, 20 de julio de 2015 15:59
    Moderador
  • Hola

    William si mal no entiendo el quiere borrar los telefonos sin borrar el usuario, pero estan ligadas, primero pense en si tenian relación por cascada pero no creo que el aproach sea el correcto, tomaria 2 queries en mi opinion no se me ocurre sin hacer una variable que obtenga el idtelefono.  

    Hola Enrique AA,

    Quiero considerar que el OP confundió en la redacción y trato de otorgarle sentido lógico a este issue. La tabla UsuarioTelefono es una tabla de referencia (la que rompe la relación entre Usuarios y Teléfonos), entonces, es ilógico la persistencia de un campo sin el otro, no existe pertenencia, el objetivo de la tabla de referencia se pierde. Es más, de ser una tabla de referencia la restricción de primary key debería estar compuesta por ambas FK, motivo aún mayor para asumir que un campo no puede "vivir" sin el otro.

    En todo caso habrá que esperar el feed-back del OP porque a veces nos llevamos varias sorpresas, además comento en el aporte anterior que no estoy de acuerdo a como está modelado el caso, veamos que nos depara este caso.

    lunes, 20 de julio de 2015 16:01
  • Si era como Miguel

    Como ando algo oxidado en mi T-SQL crei que habia una mejor manera pero lo de Miguel es la respuesta correcta.  

    lunes, 20 de julio de 2015 16:02
  • El problema Steve es que la tabla teléfono si está bien normalizada no tendrá el idusuario... por eso proponía usar la clausula ouput para obtener los ids de teléfono que hay que borrar.

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    lunes, 20 de julio de 2015 16:05
    Moderador
  • Gracias, quiza efectivamente no me exprese bien, lo que realmente quiero es borrar todos los telefonos de el usuario cuyo id es x, pero quiero borrarlos de la tabla Telefonos, dado que la tabla telefonos esta relacionada con la tabla UsuarioTelefono, se tienen que borrar tambien esas relaciones.

    Hola jeduardonl,

    ¿Has considerado lo que te comente respecto a que estás redundando datos? Aquí creo estamos aplicando mal la normalización de datos. ¿No basta con la tabla UsuariosTelefonos para almacenar el usuario y sus teléfonos?


    lunes, 20 de julio de 2015 16:06
  • No. está expresando una relación muchos a muchos entre usuarios  y teléfonos, un teléfono puede ser de varios usuarios  (centralitas de empresa se me ocurre) y un usuario puede tener varios teléfonos, particular, empresa... etc.

    No creo que haya ningún error de diseño .


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    lunes, 20 de julio de 2015 16:08
    Moderador
  • De acuerdo,

    En todo caso (y si es posible que puedas modificar las reglas de IR) ¿no sería mejor definir una regla de IR para que se borre en cascada los registros relacionados al padre? 

    lunes, 20 de julio de 2015 16:14
  • No. está expresando una relación muchos a muchos entre usuarios  y teléfonos, un teléfono puede ser de varios usuarios  (centralitas de empresa se me ocurre) y un usuario puede tener varios teléfonos, particular, empresa... etc.

    No creo que haya ningún error de diseño .


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    Si Miguel,

    Depende del diseño físico que tenga y la alta abstracción que cada uno le de.

    Saludos.


    Ayacucho - Perú
    Recuerda si mi solución atiende tu consulta por favor márcala como útil y como respuesta.

    http://litigiouslobo.blogspot.com/
    El Blog de Herbert Mendoza

    lunes, 20 de julio de 2015 16:16
  • Si, sería una alternativa. En cualquier caso yo no pretendía cambiarle el diseño a nuestro interlocutor :)


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    lunes, 20 de julio de 2015 16:17
    Moderador
  • Saludos William

    Es que no es tan simple en estos casos, el cascada seria en general si borras al usuario pero por decir una empresa muy grande digamos Nissan tiene miles de telefonosc por sucursal, entonces no puedes hacer este tipo de borrado.

    lunes, 20 de julio de 2015 16:20
  • La tabla Telefonos contiene números de telefono.

    Efectivamente, un número de telefono pertenece a mas de un usuario

    lunes, 20 de julio de 2015 17:26
  • No, no basta con la tabla UsuariosTelefonos para almacenar el usuario y sus teléfonos.

    Adicionalmente, tengo otras tablas:

    • Proveedores
    • Clientes
    • etc.

    Todos ellos tienen telefonos y no puedo tener una tabla de telefonos para cada uno.

    lunes, 20 de julio de 2015 17:30
  • Estas en lo cierto.
     Es una relación muchos a muchos
    • Editado jeduardonl lunes, 20 de julio de 2015 17:36
    lunes, 20 de julio de 2015 17:30
  • Correcto, la tabla Telefonos no tiene el idUsuario.

    ¿Me harias el favor de explicarme como fuciona la clausula output?

    De antemano gracias

    lunes, 20 de julio de 2015 17:33
  • output permite devolver la psuedotabla deleted o inserted  que se genera automáticamente cuando se usan los comandos update o delete. lo que hace es devolver la tabla que contiene los registros borrados, en el caso tuyo solo devuelvo el campo idtelefono... lo meto en una tabla temporal (una variable de tipo tabla) y por ultimo uso esa tabla para borrar de teléfonos.

    ¿se entiende?


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    lunes, 20 de julio de 2015 17:38
    Moderador
  • Gracias, entendi el concepto, solo no entiendo la última parte que pusiste en el ejemplo:

    declare @idusuario int
    set @idusuario=12345
    begin tran
    delete from usuariosTelefonos 

    lunes, 20 de julio de 2015 22:39
  • -- Declaro una tabla que almacene los teléfonos borrados
    
    declare @UsuariosTelefonos_del table(idtelefono int)
    
    -- abro una transacción si se produce un error no quier oque se borre de una tabla si y otra no 
    
    
    begin tran
    
    -- borro marcando output del campo idtelefono a la tabla que he declarado (es una variable)
    delete from UsuariosTelefonos
    output deleted.idtelefono into @UsuariosTelefonos_del;
    
    
    -- ahora borro de la tabla teléfonos usando la variable tabla para hacer un inner yoin 
    delete t from  telefonos t inner join @UsuariosTelefonos_del d on t.idtelefono=d.idtelefono
    
    
    -- valido la transacción 
    commit
    
    

    el código completo es

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    martes, 21 de julio de 2015 19:07
    Moderador