Estoy con el proyec fin de carrera. Te voy a contar un poco el problem que tengo. Resulta que tengo una base de datos en access, y se me da el caso de que necesito insertar datos en una tabla, pero me dice que necesita un registro relacionado en la tabla primaria. Me ocurre lo mismo si yo quiero borrar un registro, me dice que existen registros relacionados en la tabla y no me deja borrarlos. Y sé que esto me ocurre porque tengo exigida integridad referencial. Mi pregunta es si queda muy cutre quitar la integridad referencial en la base de datos, o si hay alguna manera, a través de delphi, de modificar las relaciones, en la BD para poder poner o quitar integridad referencial cuando se necesite.
Respuesta de burraburiash
1
1
burraburiash, Bueno, sobre todo me gusta la computación
Lo que podes hacer que no es tan feo como sacarle la integridad referencial (yo NO LO HARÍA) es hacer que el campo que te pide que tenga una referencia pueda ser nulo. De esta forma la restricción desaparece. Otra forma sería agregar a la tabla de referencia (la primaria) un registro de propósito general que se use para los casos en que no sepas qué referencia (de la tabla primaria) ponerle a ese registro que estás insertando, de este modo no tira error. Cualquiera de las dos te va a ahorrar tiempo, porque si le sacás la integridad referencial, ¿quién garantiza que las cosas que controlaba el motor de BDD las controla tu aplicación?. Hacelo así y por supuesto, mucho más si es para la facu, DOCUMENTALO JUSTIFICANDO el porqué elegiste eso. Bueno, chau y suerte, cualquier cosa dejá la pregunta abierta y preguntame de nuevo...
Una preguntilla, me puedes explicar a que te refieres con un registro de propósito general. Te agradecería que me pusieses un ejemplo sencillo, para que lo pueda entender mejor. Gracias de antemano.
Te doy un ejemplo sencillo: Supongamos que somos un comercio y que queremos registrar a quien le vendemos qué cosa y para ello tenemos la lista de clientes. Pero se puede dar el caso que alguien que no sea cliente registrado compre algo. En ese caso, para no tener una tabla de relación extra, en la tabla de clientes agregamos una entrada "Desconocido" y asociamos las compras de estas personas no registradas con la entrada "Desconocido" de la tabla de clientes. Bueno, espero que te halla servido, sino, volvé a preguntar o decime si no lo podes aplicar. Bye!
Si, esta última aclaración la entendí, pero lo que pasa es que yo no puedo dejar ningún campo clave con valor desconocido, es más, el código de el cliente en mi caso, lo crearía el propio porograma, ya que es un campo autonumérico. Gracias por tu paciencia.
¿Cómo va todo? Retomando el tema que nos atañe, lo que yo decía no era dejar el campo clave vacío, pero vamos cerrando la idea progresivamente. Sigo con el ejemplo anterior pero más descriptivamente: Tabla Clientes: -->Código (Autoincrement) -->Nombre (String) Tabla Ventas: -->Código (Autoincrement) -->cliente (numérico) not null -->Artículo(String) -->Precio (numérico) Bueno, no le pongo más datos porque es un mero ejemplo, ahora te doy ejemplos de lo que habría en las tablas. Se agrega el cliente Juan Se agrega el cliente Rómulo Se agrega el cliente Remo Juan compra papas $2 Remo compra soda $1 Rómulo compra hielo $1,5 Juan compra un auto $15000 Tabla Clientes: Cod. Nombre 00001 Juan 00002 Rómulo 00003 Remo Tabla Ventas: Cod. Cliente artículo precio 00001 00001 papas 2 00002 00003 soda 1 00003 00002 hielo 1,5 00004 00001 auto 15000 Hasta acá todo bien. Supongamos que ahora dos personas que no son clientes compran un artículo cada una: Persona A compra una hollá $14 Persona B compra un secarropa $200 Si intentamos hacer un INSERT y no tenemos el cliente, como el campo cliente es obligatorio, el motor de base de datos no nos permite efectuar la acción. Tampoco el vendedor puede obligar a todos los clientes dar los datos personales para registrarlos en el sistema. Pero sin un cliente, no puede dar el alta a la transacción! Para solucionar esto sin perder las ventajas de la integridad referencial, ni incomodar a los clientes con preguntas, el programador ingresa un nuevo cliente a la base: Se agrega el cliente DESCONOCIDO por única vez en la vida del sistema: Tabla Clientes: Cod. Nombre 00001 Juan 00002 Rómulo 00003 Remo 00004 desconocido Luego se agregan las transacciones: Persona A compra una hollá $14 Persona B compra un secarropa $200 Tabla Ventas: Cod. Cliente artículo precio 00001 00001 papas 2 00002 00003 soda 1 00003 00002 hielo 1,5 00004 00001 auto 15000 00005 00004 hollá 14 00006 00004 secarropa 200 Obsérvece que tanto para las compras del cliente A, como las del B se empleó el mismo cliente genérico ("DESCONOCIDO") y el alta se realiza sin mayores problemas. Ahora, supongamos que el cliente Rómulo no está conforme con el comercio y aplicando su derecho de habeas data (que le permite tener control sobre sus datos personales) decide cancelar su suscripción como cliente. Si intentamos borrar el cliente Rómulo, el motor dará un nuevo error diciendo que en la tabla secundaria (Ventas) hay filas que dependen de esta entrada. La solución más sencilla es eliminar todos los registros de venta de ese cliente y luego borrar el cliente. Sin embargo, el propietario también tiene derecho de conservar registros de sus ventas, de hecho los necesita para el funcionamiento de su empresa. La solución a este problema que no entorpece los derechos de anonimato del cliente, ni las estadísticas del comerciantes es cambiar todos los registros de la tabla ventas que se refieren a Rómulo y apuntarlas al cliente "DESCONOCIDO". Luego se puede eliminar el cliente sin problemas. Entonces: 1) Cambio las transacciones de Rómulo y las apunto al cliente desconocido Tabla Ventas: Cod. Cliente artículo precio 00001 00001 papas 2 00002 00003 soda 1 00003 00004 hielo 1,5 <--Cambiada 00004 00001 auto 15000 00005 00004 hollá 14 00006 00004 secarropa 200 2) Luego doy de baja al cliente Rómulo Tabla Clientes: Cod. Nombre 00001 Juan 00003 Remo 00004 desconocido Bueno, como verás no sólo importa en una aplicación poder manipular la información, sino también que hay mecanismos que preservan la figura "legal y comercial" de los clientes y propietarios. Espero que esto sea lo que necesitabas, sino podemos convenir algo, pero confío en que es esto. Mucha suerte y cualquier cosa avisame, chau!
Ante todo te diré que lo de mantener la integridad referencial a nivel de base de datos tiene un sentido sobre todo a la hora de garantizar la coherencia de los datos. Si por la integridad no te deja eliminar algún registro es porque no se puede (pone en peligro la coherencia) o porque la integridad esta mal diseñada. En cualquiera de los casos hay solución, pero tendrás que currártelo un poco... Primero: Puedes pasar olímpicamente de la integridad referencial a nivel de base de datos y garantizarla tu a nivel de programa. Esto no es cutre, simplemente es rehacer trabajo ya hecho, y si bien puedes flexibilizarla tu tanto como quieras, también corres el riesgo de dejar huecos que te comprometan la coherencia de los datos (i.e. Borrar un cliente al cual están enlazados varios documentos, dejaría los documentos sin datos de cliente) Segundo: En los casos en que deseas borrar alguno de esos registros que te causa problemas de integridad, puedes forzar las reglas ha borrado en cascada en vez de integridad referencial. Esto te implicaría en el caso del ejemplo que te pongo que se borraría el cliente con todos sus documentos, dejando las cosas sin errores de coherencia. Tercero: La rutina para borrar los registros que te interesa borrar puede abrir las relaciones, es decir, los campos que están enlazados a otras tablas que pueden comprometer la integridad los llenas con valores nulos de manera que no se violen las reglas. Después de abrir estos enlaces ya puedes borrar el registro. En el ejemplo que te ponía, seria ir a los documentos, poner en el enlace con el cliente valor nulo y después borrar el cliente. Te quedarían los documentos huérfanos, pero sabrías por programa al tener nulo que son de histórico, o que no importan para los listados de clientes y esas cosas. Cuarto: Puedes modificar al vuelo las relaciones. Esto no esta bien visto y si que es cutre. Como no trabajo con Delphi no tengo idea de como puede hacerse, pero si usas algo parecido al DAO, existen objetos que se llaman TableDefs, que tienen colecciones de Relaciones. Puedes explorar estas colecciones y eliminar o re-crear las relaciones cuando lo necesites. En realidad esto no esta bien, sobre todo si el programa es multiusuario, ya que puede alguien tratar de borrar algo incorrecto mientras tu te has cargado temporalmente una relación, y como no esta activa, borrar y dejarte la base de datos hecha un desastre... por otro lado, si vas a quitar y poner relaciones, ¿para qué ponerlas a nivel de base de datos? Para eso usas la variante 1, que es la que uso yo en mis programas, por cierto...
La integridad referencia o la pones o la quitas, no debes modificarla para cada ocasión, ademas no se puede modificar por programación. Cutre queda el que no funcione bien el programa, ten en cuenta que ha de ser EEE (Efectivo, hacer lo que se supone que debe hacer, Eficiente, hacerlo lo más rapido posible, Eficaz, hacerlo utilizando el mínimo de recursos posibles).
P rimero evalúa si realmente es necesario que uses integridad referen cial, y la otra si, se puede manejar la integridad desde cualquier programa, pero es muy complicado, ya que cada amovimiento que ha gas vas a atener que hac er lo mismo, y la co dificacion tamabien es aabastante en gorrosa, vas a atener que declarar módulos de clases, para que te ahaga el laaburo
Hasta donde puedo contestarte es que no debes activar la integridad referencial hacia ambos lados de la relación, debes analizar y definir para que lado sera la relación, entonces, por ejemplo, si tienes una tabla con flores y otra con colores y exiges integridad hacia la tabla de flores no te permitirá eliminar un color que este siendo utilizado por algún registro en la tabla flores. De la misma manera no podrás insertar una flor que no tenga un color, si es un color que no tienes debes primero insertar el color y luego la flor. Cualquier cosa avisame...