Usuario
Error al borrar cliente contra sql Server express 2005

Pregunta
-
Hola me ocurre un error un error el cual ya no se como afrontar. Tengo una base de datos en sql express 2005, La tabla de clientes tiene varias tablas dependientes de ella (domicilios, telefonos, emails, etc) al borrar un cliente le tengo configurado que automaticamente borre en cascada de esas tablas dependientes los registros enlazados a dicho cliente. Hasta aquí todo correcto, si desde el "SQL management Studio" ejecuto una consulta tal que así:
"Delete from clientes where id =1"
Me elimina el cliente de dicho id y los ids relacionados de sus tablas dependientes sin mayor problema.
Bien hasta aquí todo perfecto, luego tengo en Visual Basic una aplicación que gestiona estas tablas, donde doy de alta y modifico mis clientes, todo funciona a la perfección, puedo crear, modificar, moverme adelante, atrás, buscar un cliente y situarme en el, pero si a la hora de borrar intento hacer algo de lo siguiente:
Recordset.delete
o por ej.:
Cnn.execute "Delete from clientes where id =1"
El sistema me devuelve el siguiente error:
Error '-2147217900 (80040e14)' en tiempo de ejecución: Error interno del procesador de consultas: el procesador de consultas no pudo producir un plan de conulta. Para obtener más información, póngase en contacto con los servicios de soporte al cliente.
He encontrado este artículo: http://support.microsoft.com/kb/953854/es pero entiendo que las tres posibles soluciones ofrece ese artículo, es cuando te falla la consulta de borrado desde el propio motor de base de datos, pero el caso es que desde el motor de base de datos, ejecuto el borrado perfectamente es solo si lo ejecuto desde Visual Basic cuando me devuelve el mensaje de error: Las soluciones que ofrece son:
Para evitar este problema, utilice uno de los métodos siguientes: -Crear una clave principal agrupada en lugar de una clave principal no agrupada en la tabla con respecto al cual se ejecuta la instrucción DELETE .
-Vuelva a escribir la instrucción DELETE para evitar las filas duplicadas. Por ejemplo, tiene la siguiente consulta problemática. DELETE Table1 FROM Table1 JOIN Table2 on Table1.col1 = Table2.col1 Puede reescribir la consulta como la siguiente. WITH cte AS ( SELECT c FROM Table1 WHERE Table1.col1 IN (SELECT col1 FROM Table2) ) DELETE cte; -Quite la acción en cascada de la clave externa.
Aun así para la primera solución, mi tabla de clientes solo tiene como clave principal el campo Id. ç
Para la segunda solución no tengo ni idea como puedo reescribir mi consulta "delete from clientes where id=1" de la forma que dice ahí
Y bueno la solución nº 3 de quitar la acción en cascada podría hacerlo pero me causaría bastante perjuicio pues lógicamente trabajo desde muchas más partes del programa con clientes y sus tablas dependientes y si no están enlazadas en cascada me podría causar errores o tener que estar controlandolo yo por código y verme obligado a reescribir muchas partes que ya tengo hechas, por lo que por lo pronto prefiero evitarlo e intentar buscar otra solución si es posible.
¿A alguien se le ocurre otra solucion?
Muchas gracias.
Todas las respuestas
-
-
NO tenes que ejecutar el metodo .delete sino hacer un execute "delete from tabla where codigo=1"
Hola Luis gracias por tu respuesta, como comento en mi mensaje, igual demasiado extenso :P tanto con el método .delete como con un execute "delete from tabla..." me produce el error :(
Saludos.
-
-
Hola Rock76, si el programa no puede desarrollar el plan de ejecucion de borrado fallara siempre, si desde el management Studio a la consulta
delete from clientes where id=1 le pides el plan de ejecucion, te lo muestra correctamente? por otro lado, comentanos si estas usando ADO.net o LINQ.
de momento te muestro un ejemplo de borrado en LINQ
private void btnEliminar_Click(object sender, EventArgs e) { try { LINQDataContext mibase= new LINQDataContext(); MV_CLIENTES clienteactual = mibase.MV_CLIENTES.Single(p => p.ID == int.Parse(iDComboBox.Text)); mibase.MV_CLIENTES.DeleteOnSubmit(clienteactual); mibase.SubmitChanges(); } catch (Exception ex) { MessageBox.Show("ERROR: " + ex.Message); } }
espero tu respuestas para poder solucionar tu problema!
Saludos!
Victoria Rodriguez
Raona - Software Engineer
Mi BLog -
Hola Victoria, muchas gracias por tu respuesta, ¿Ado.Net LinQ? Aun estoy con Visual Basic 6 y ado a secas :$ Respecto a tus otras preguntas sí, si ejecuto la consulta:
delete from clientes where id=1
Desde el Management Studio, no sólo borra correctamente el cliente si no que borra también todos sus registros dependientes en otras tablas. En cambio si ejecuto la misma consuta desde mi proyecto en Visual Basic 6.0 me aparece el error indicado en mi primer mensaje :(
¿Alguna sugerencia.
Gracias por tu tiempo.
-
Hola Rock76, cierto que estas en visual 6, pero no es un problema de lenguaje, es un problema de la forma que haces el borrado en cascada, ya que tu programa intenta borrar las filas y el SQL se "entretiene" borrando en cascada
por lo que veo estas haciendo un programa de gestion, y debes plantearte la mejor estructura para esto
tu consulta al sql es:
Delete from clientes where id =1
supongo que tus desencadenadores son
after delete (esto es despues de borrar!)
delete from domicilios where clientes =1
delete from telefonos where clientes =1
delete from email where clientes =1
aun no entiendo porque tienes esto, ya que podrias tener todo en la misma tabla, y en caso de que necesites una especial para los contactos, crea una sola tabla que sea "contactos, donde relaciones solo el codigo o id del cliente entre ambas, y antes de borrar el cliente, debes borrar la contacto con el cliente
lo que te recomiendo es que el borrado lo hagas de atras para adelante, o sea, desde las tablas email, domicilio, telefono, y si todo esta ok, recien ahi borres el cliente, porque sino estas diciendole al sql que borre "clientes =1" donde el cliente ya no existe
me podes mostrar los desencadenadores que tenes para borrar las otras tablas y como son las otras tablas? asi te podemos ayudar a hacer un procedimiento que borre en cascada, primero las relaciones y despues la tabla principal, ya que el error de PK y FK parece impedir que lo hagas directo
Victoria Rodriguez
Raona - Software Engineer
Mi BLog -
Hola Victoria muchas gracias por tu respuesta y tiempo, el motivo por el que tengo separado domiciliios, telefonos y email separados de clientes en otras tablas distintas al cliente es bien sencillo y es que es habitual que el cliente disponga de más de un domicilio, más de un teléfono y más de un email. Por tanto cuando le digo a la base de datos que borre el cliente de ID=1 al tener delete en cascada, si este cliente tiene dados de alta 5 teléfonos debe borrar esos 5 registros de la tabla teléfonos también y así con el resto de tablas relacionadas.
De hecho así funciona desde el magnament Studio, pero no encuentro sentido a que falle la misma consulta desde Visual Basic. Además ya tengo otro programa de gestión con una organización de tablas parecida y funciona perfectamente, no entiendo porqué este falla. Pensaba que era por el orden de las referencias o por algo así había descartado por completo cualquier tema relacionado con la base de datos ya que si no fallaría también en el magnagement studio ¿no? :-/
Saludos.
-
Asi es, no deberia falla.
colocale un bloque
{ try { } catch (Exception ex) { MessageBox.Show("ERROR: " + ex.Message); } }
como te explica en esta pagina y captura la excepción, seguramente te va a brindar mas información para poder atacar el problema.
esperamos mas informacion para resolver tu problema!
Saludos!
Victoria Rodriguez
Raona - Software Engineer
Mi BLog -
-
Bueno, es verdad, pero tambien tienes una forma de hacerlo:
Aquí es un programa de software gratuito:
http://wareseeker.com/Software-Development/Automatic-error-handling-Pro-1.1.0.ZIP/238557este programa le ayuda en la inserción de código para controlar los errores en procedimientos de Visual Basic. Lo hace automáticamente , al insertar en cada procedimiento seleccionado, el código necesario para controlar los errores (la famosa "On Error GoTo Label" declaración).
y aquí está el código fuente para que lo hagas vos:
http://www.nigelrivett.NET/VB/VBAddErrorHandling.htmlte muestro un ejemplo muy completo en esta web
http://forum.codecall.net/vb-tutorials/1360-vb6-0-tutorial-error-handling.html
espero que te haya ayudado un poco!
Cuando alguien conteste a tu pregunta, si la información te resulto Útil Votala o marcarla como respuesta
Victoria Rodriguez
Raona - Software Engineer
Mi BLog