Ir al contenido


Foto

CLAVES COMPUESTAS CON RESTRICCIÓN "UNIQUE"


  • Por favor identifícate para responder
11 respuestas en este tema

#1 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 05 abril 2014 - 08:38

Saludos.

Traigo una duda que espero me puedan sacar de ella.  :)

Tengo una tabla (Que ya contiene datos y relaciones con otras tablas) con clave primaria compuesta por dos campos y, debo crear una relación entre esta tabla y otra nueva. Pero la relación la necesito hacer a través de un solo campo. Por ejemplo mi clave primaria de la "tabla 1" esta compuesta por dos campos (campo1,campo2) y al relacionar con otra tabla "tabla 2" necesito crear la relación solo haciendo referencia al campo1.

Firebird me advierte que para poder hacer esto debo crear una restricción UNIQUE para algunos de los campos que conforman la clave primaria.

Debido a que la tabla que contiene clave primaria compuesta por dos campos ya tiene datos y relaciones con otras tablas, quisiera saber si al crear esta restricción me causaría algún inconveniente posteriormente en algunas de las relaciones que existen con esta tabla que contiene clave compuesta.

NOTA: Tengo entendido que la diferencia que resalta más entre las restricciones PRIMARY KEY y UNIQUE es que la PRIMARY no acepta valores nulos y la UNIQUE si. Pero su funcionamiento es muy parecido ya que no permiten valores duplicados. Desde mi punto de vista creo que no me causara ningún problema, pero eso de creo no me gusta  :) prefiero que alguien con experiencia me saque de esta duda y luego no tener problemas.

Adjunto dejo una imagen con la estructura de la tabla que contiene clave primaria compuesta.

Espero me den una mano!  (y)

Archivos adjuntos


  • 0

#2 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 06 abril 2014 - 10:45

Hola amigo, a mi antes de cualquier cosa me surge una enorme duda en cuanto a lo que quieres realizar...

Si tienes una llave compuesta en tu tabla de productos_servicios con los campos codigo_producto y tipo_producto, quiero suponer que pueden presentarse registros como los que siguen:

codigo_producto  tipo_producto
1111111                X
1111111                Z
1111111                Y
2222222                X
3333333                X

los cuales claramente cumplen con ser únicos pero dentro de la combinación...

Ahora conforme a lo que deseas plantear es que vas a hacer una segunda tabla que se relacione con la de productos_servicios pero donde sólo deseas como campo llave el código de producto dejando de lado el tipo.

Mi pregunta es, si esa segunda tabla hace referencia en un registro al codigo_producto 1111111, a cuál de los 3 está ligado en la tabla de productos_servicios ???

Porqué no generar la segunda tabla haciendo referencia a la llave completa, de tal modo que específicamente puedas hacer referencia a un sólo registro ???

Me surgen estas dudas porque no me suena muy lógico que una llave compuesta se quiera "descomponer" para hacer relación con otra tabla  ^o|

Ojalá puedas aclararme las dudas  (y)

Saludox ! :)


  • 0

#3 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 06 abril 2014 - 10:47

Me acaba de surgir otra duda...

Acaso deseas hacer un master de la tabla productos_servicios y que ésta funciona como detalle de la nueva ???  ^o|

(Para ser domingo ando muy preguntona  :D :D :D)

Saludox ! :)
  • 0

#4 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 06 abril 2014 - 12:29

Hola, gracias por responder.

Muy buenas tus preguntas. Debido a esto puedo explicar con más detalle todo, ya que si lo explicaba una vez iniciado el tema posiblemente muchas personas se complicaban e iba a salir muy extenso y lo más seguro es que pocos lo leyeran  :D. Ahora, te explico:

La tabla "PRODUCTOS_SERVICIOS" pertenece al Sistema Administrativo utilizado en la Empresa de mi Cliente. Este Sistema maneja inventarios, ventas, compras, cuentas por cobrar, cuentas por pagar, nómina, bancos, importaciones entre otras cosas. Yo no forme parte del desarrollo de este Sistema por lo cual no tengo el código fuente de la aplicación ni el diseño de la Base de Datos (Módelo Lógico) ni mucho menos el Diccionario de Datos para ver a detalle la estructura de las tablas. Mi cliente adquirió este Sistema comprándolo a un distribuidor.

Yo puedo acceder a la Base de Datos  mediante el uso de IBExpert ya que el servidor firebird hace uso del usuario y clave básico de Firebird "SYSDBA, masterkey". Gracias a esto puedo modificar cualquier objeto de la Base de Datos.

Ahora, mi cliente desea un Sistema que gestione las solicitudes de servicios realizadas por los clientes, tal y como explique al principio. Ya que este Sistema Administrativo no esta en capacidad de hacerlo. Y debo hacer uso de los clientes, servicios y técnicos que tienen registrados en la Base de Datos del Sistema Administrativo.

Me toco agregar unas cuantas tablas para que la aplicación que estoy construyendo cumpla con los requerimientos de mi cliente.

Ok, en esta base de datos me he conseguido con relaciones algo extrañas pero esto se debe a que la empresa que realizo el Sistema Administrativo diseño la Base de Datos a su manera para que no fuese blanco fácil de copia. O sea, cualquier persona que entre a la Base de Datos vea un diseño fácil de Base de Datos y luego se la copie y saque un Sistema idéntico.

Una vez explicado esto, te aclaro lo siguiente:

Si observas la imagen de la tabla "PRODUCTOS_SERVICIOS" te darás cuenta que los dos primeros campos a la misma vez que son PRIMARY KEY son támbien FOREING KEY. Esto se debe a que estos dos campos se encuentran relacionados con otra tabla llamada "PRODUCTOS_FACTURABLES" (Tabla Padre) la cual contiene el codigo y tipo de todos los productos que maneja el Sistema Administrativo.

Además de la tabla "PRODUCTOS_SERVICIOS" también existen otras tablas llamadas "PRODUCTOS_TERMINADOS", "PRODUCTOS_COMPUESTOS". Para que estas tres tablas puedan almacenar productos, dichos productos primero deben existir en la tabla "PRODUCTOS_FACTURABLES" que es la tabla padre donde se le asigna el código único y el tipo de producto. Y por ende los productos que se almacenan en las distintas tablas "Hijas" hacen uso del código y el tipo que ya se les ha sido asignado en la tabla padre "PRODUCTOS_FACTURABLES". Debido a esto estos códigos nunca se repiten en ninguna tabla. Adjunto esta una imagen donde veras un mini ejemplo de como se guardan los datos entre estas tablas.

Ahora, el detalle esta en que unas de las tablas que yo cree para mi aplicación hace uso de la tabla "PRODUCTOS_SERVICIOS" por lo cual debo tomar las claves primarias de esta tabla y relacionarlas como claves foráneas con la tabla que estoy creando. He creado en mi tabla un campo que corresponda al campo codigo_producto y otro al campo tipo_producto, cuando intento crear la restricción de clave foránea entre los dos campos que cree en mi tabla y los campos codigo_producto y tipo_producto en la tabla "PRODUCTOS_SERVICIOS" firebird me genera una excepción diciéndome que no es posible. He registrado la base de datos así como reiniciado el manejador de base de datos varias veces y me genera esta excepción. Pienso que debe ser por alguna configuración que hayan hecho las personas que diseñaron el sistema, pero como no tengo diccionario de datos y nada, pues ni idea.

Debido a esto relacione solo el campo codigo_producto de la tabla "PRODUCTOS_SERVICIOS" con el campo que le asigne en la tabla que cree. Al momento de crear esta restricción firebird me dice que debo declarar alguno de los dos campos que conforman la clave primaria en la tabla "PRODUCTOS_SERVICIOS" como único "UNIQUE", lo hice y listo, puede relacionar las tablas correctamente.

Y pues ya que hice esto la duda es, debido a que la tabla que contiene clave primaria compuesta por dos campos ya tiene datos y relaciones con otras tablas, quisiera saber si al crear esta restricción (UNIQUE en el campo codigo_producto) me causaría algún inconveniente posteriormente en algunas de las relaciones que existen con esta tabla.

En lo particular lo he pensado mucho y pienso que no, ya que si los productos deben existir primero en la tabla "PRODUCTOS_FACTURABLES" automáticamente se les asigna un código y un tipo, luego de eso es que se inserta en la tabla que corresponda ya sea "PRODUCTOS_SERVICIOS","PRODUCTOS_COMPUESTOS" o "PRODUCTOS_TERMINADOS". Por lo que, el código_producto en las tablas hijas no se va a repetir. Entonces podría crear una restricción de tipo UNIQUE para el campo codigo_producto en la tabla "PRODUCTOS_SERVICIOS". Según el ejemplo que colocaste quedaría algo así:

TABLA: PRODUCTOS_SERVICIOS

codigo_producto  tipo_producto
1111111                X
2222222                X
3333333                X

Y pues bueno, pregunto por salir de dudas y saber que me recomiendan en el foro ya que no poseo ningún tipo de documentación sobre la base de datos (Diccionario de Dato o Modelo Lógico). Y en estos casos la situación se torna delicada debido a que si daño una relación todos sabemos que el Sistema no funcionara bien y hasta perdida de datos se pueden provocar.

Espero me haya dado a entender jejeje, es algo largo pero sino explico todo van a quedar muchos cabos sueltos.

Saludos!



 

Archivos adjuntos


  • 0

#5 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 06 abril 2014 - 01:34

Ok me queda un poco más claro el panorama al que te enfrentas...

Podríamos deducir que realmente no era necesaria la llave compuesta en la tabla de PRODUCTOS_FACTURABLES (y por ende en las tablas "HIJAS") ya que supongo que por sistema restringen que el campo codigo_producto sea único, porque realmente en la base de datos es posible que el campo sea repetido, mientras el tipo_producto sea diferente (como en el ejemplo que indiqué antes)...

Ahora, si tu colocas el campo codigo_producto como UNIQUE, estarás haciendo la restricción directo en la base de datos para la duplicidad de códigos del producto (independientemente de si en la aplicación también lo restringía o no) lo que insisto, hace aún más ociosa la llave compuesta.

Ya respondiendo a tu duda yo veo que en teoría no debes tener problemas con la restricción de UNIQUE en el campo de producto, SIEMPRE Y CUANDO estés realmente seguro de que nunca de los nuncas podrás encontrar algo así en el sistema:

codigo_producto  tipo_producto
1111111                X
1111111                Z
1111111                Y


... si ésto no ocurrirá, entonces no le veo problema con el cambio que has realizado, e inclusive veo ocioso el uso de la clave compuesta, realmente deberías tener únicamente como PK el campo del codigo del producto, y su tipo, como un campo "normal" informativo.

Saludox ! :)


  • 0

#6 JRichard

JRichard

    Advanced Member

  • Miembros
  • PipPipPip
  • 67 mensajes

Escrito 07 abril 2014 - 02:08

Saludos.

Si como los código no se repetirán en la tabla "PRODUCTOS_FACTURAS" por ende no se repetirán en la tabla "PRODUCTOS_SERVICIOS". Y si, es algo vicioso lo que hicieron en esa Base de Datos pero lo hacen con el fin de que sea difícil de copiar. Pero bueee, la idea es cumplir con el cliente jejeje! Gracias por responder!
  • 0

#7 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 07 abril 2014 - 02:43

Hasta el día de hoy, no he visto un caso en donde esté realmente justificado el uso de una clave compuesta.
Y hasta tengo motivos de porqué no emplearla:
1) La enorme mayoría de los motores no tienen un manejo eficiente de estos tipos de claves, y Firebird no es la excepción.
2) Relacionado con el punto anterior, los índices no suelen trabajar con éstas.
3) A largo plazo, en la medida en que la base de datos va creciendo y cumpliendo con su ciclo de vida, llega el punto en el que el propio diseño hace que las claves compuestas "estallen" y deba ser necesario eliminarlas y optar por las claves simples.

Saludos,


  • 0

#8 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 08 abril 2014 - 08:50

Hola amigo Delphius,

Y cómo es la propuesta para un maestro-detalle, por ejemplo, en algo tan simple y común como las facturas y su detalle de productos ???

Yo inmediatamente lo pienso así:

TABLA_FACTURAS
num_factura    fec_factura  tot_factura  mon_factura
      X              08.04.2014        1850.00      PESOS


TABLA_DETALLE_FACTURAS
num_factura    cons_detalle    cod_producto    tot_producto
      X                      1                236985533            500.00
      X                      2                100036984            600.00
      X                      3                998566336            750.00


... donde lo marcado con negritas se consideran como campos llave y específicamente en el detalle es una llave compuesta...

Saludox ! :)
 

  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 08 abril 2014 - 12:52

Una relación del tipo maestro-esclavo entre dos tablas requiere forzosamente una estructura de este tipo:

Tabla Maestra:
-------------------
IDMaestra: PK
etc

Tabla Esclava:
------------------
IDEsclava: PK
MaestraID: FK >> Tabla Maestra.IDMaestra
etc

Creo que con esto ilustro la idea.
Como he dicho antes, tarde o temprano las claves compuestas tienden a romperse.

Saludos,
  • 0

#10 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 08 abril 2014 - 02:35

Aunque puedo estar de acuerdo con la idea de que las llaves compuestas no son forzosas, obligatorias ni mucho menos indispensables, honestamente me parece un mejor modo de leer una tabla maestro-detalle de la forma en que lo he expresado.

Su estructura me parece más legible y más simple de interpretar...

Mi pregunta ahora va por el lado del rendimiento... es igual para ambos casos ???

Saludox ! :)
  • 0

#11 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 08 abril 2014 - 02:49

Aunque puedo estar de acuerdo con la idea de que las llaves compuestas no son forzosas, obligatorias ni mucho menos indispensables, honestamente me parece un mejor modo de leer una tabla maestro-detalle de la forma en que lo he expresado.

Su estructura me parece más legible y más simple de interpretar...

Mi pregunta ahora va por el lado del rendimiento... es igual para ambos casos ???

Saludox ! :)

Pues para tablas de muchísimos registros si se va a observar diferencias en el rendimiento. Tenlo por seguro.
No recuerdo si fue en la documentación o en el HandBook escrito por Helen Borrie que leí sobre ciertas advertencias en el uso de claves compuestas.
En ese punto Firebird no está pulido (al menos no lo estaba en la version 1.5) y entre los consejos y la propia teoría que aportaba detallaba muy bien sobre lo que implica emplear claves compuestas.

1) El utilizar claves compuestas hace que el motor deba hacer doble trabajo, ni que decir si encima se le indica que sea UNIQUE ya que debe mantener a dichos campos como una unidad.
2) El motor puede que no sepa elegir adecuadamente que índices utilizar si justamente se cuenta con varios de ellos y en donde se vean involucrados los campos que hacen a la clave compuesta.
3) Relacionado con esto, si existe un único índice, y sólo aplica a la clave compuesta y se requiere de una búsqueda u operatoria que involucre SÓLO a uno de dichos campos el motor no podrá usarlo.
4) Las operatorias de modificación sobre estos campos son más complejas.

Esos son los principales puntos en contra que tiene el emplear una clave compuesta y que recuerdo que se han señalado en el documento.

Saludos,
  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 08 abril 2014 - 03:34

Ahora, respecto a lo que sucede con UNIQUE hay que entender lo que se entiende por NULL.
La lógica indica que un NULL es distinto a otro NULL. Desde Firebird 1.5 en adelante en una clave única o índice único se permite el valor NULL.
Cuando se define UNIQUE el campo se hace único, se le asocia un "identificador" que hace de éste la imposibilidad de que exista un valor repetido. ¿Que sucede con los NULOS?
Pues bien, UNIQUE entiende a cada NULL como diferente a otro. Es decir que si se ve esto:

CampoUNIQUE - Campo1 - etc
NULL - valor1
NULL - valor2
...

El primer NULL tiene un valor diferente al segundo NULL. De modo que si se compara en una evaluacion if si son iguales el resultado va a ser falso.

Lo mismo sucede si se trata de una clave compuesta unica, la diferencia está en que ahora cada dupla NULL es tratada como diferente a otra:

{NULL, NULL} <> {NULL, NULL}

¿Me explico?
Saludos,

  • 0




IP.Board spam blocked by CleanTalk.