Cómo elegir la clave primaria de una tabla

Juan Mellado, 23 Febrero, 2007 - 22:20

SQLA veces tengo la impresión de que elegir las columnas que constituirán la clave primaria de una tabla es una decisión que suele tomarse muy a la ligera, cuando la realidad es que la correcta elección de las claves primarias es un factor decisivo para poder construir un modelo relacional de base de datos bien formado, coherente, mantenible y fácilmente ampliable. Lo más irónico del asunto es que en realidad resulta una tarea muy sencilla si se comprende que ningún valor tomado del dominio que estamos intentando modelar sirve para identificar unívocamente a los registros en base de datos. Dicho de otra forma, no puede utilizarse como clave primaria una columna que contenga información que tenga significado para los usuarios; hay que crear una columna expresamente para la clave primaria. O dicho de una tercera forma, si tiene que crear una tabla de personas no utilice DNI como clave primaria.

¿Pero por qué no es una buena idea elegir DNI como clave primaria?, ¿acaso ese número no nos identifica de forma unívoca?. Pues sí, pero rotundamente NO. Piense por ejemplo que los menores de edad o los ciudadanos de otros paises no tienen normalmente un carnet de identidad, y todo ello sin mencionar además el hecho de que los números del DNI no son únicos, históricamente la misma numeración se ha reutilizado en distintas personas.

Puede que en este momento esté pensando en alternativas muy inteligentes para tratar de resolver los problemas que se plantean en el párrafo anterior, posiblemente mediante la incorporación de nuevas columnas a la clave primaria, pero créame, déjelo, el esfuerzo será inútil, la realidad es que los problemas no desaparecerán, se incrementarán. Por ejemplo, podemos pensar que podremos almacenar menores de edad en nuestra tabla si añadimos una nueva columna a la clave primaria que nos indique si en realidad el DNI es suyo o de su representante legal. Pero ocurre que una persona puede tener varios hijos, con lo cual necesitariamos otra nueva columna para distinguirlos. También podemos pensar que podremos almacenar personas de distintos paises si añadimos una nueva columna que nos indique la nacionalidad de cada persona, permitiendo así además que un mismo número se repita para personas de distintos paises. Pero ocurre que una persona puede tener varias nacionalidades. Y así, vuelta a empezar. Lo normal es que siguiendo esta línea de razonamiento se acabe necesitando facilmente 7 u 8 columnas más.

En lineas generales no se deben utilizar claves primarias compuestas en las tablas maestras, es decir, claves formadas por varias columnas en las tablas que almacenan las entidades básicas que gestiona un sistema. Complica los modelos haciéndolos difíciles de mantener y ampliar. Piense en el ejemplo anterior, en si persitieramos en nuestra idea original de utilizar DNI como clave primaria, de forma que el día de mañana nos encontráramos un problema de los antes citados, y que además lo solucionáramos añadiendo un nuevo campo a la clave primaria. Pues ocurriría que tendriamos que añadir ese nuevo campo a todas las tablas y procesos que hicieran referencia a la tabla de personas. El cambio no sería único y localizado, si no que se expandería como una enfermedad contagiosa por todas las entidades y procesos del sistema que tuvieran algún tipo de relación con la tabla de personas.

Hay que tener cuidado con las claves compuestas, sobre todo porque a veces se presentan camufladas bajo la apariencia de lo que normalmente se denominan "códigos inteligentes". Un código inteligente es la unión de varias claves en una sola columna, o sea, una clave primaria compuesta con piel de cordero. Un ejemplo típico de este tipo de código son los localizadores, como el de una entrada de cine en la que figura "S07-F12-B08", lo que vendría a significar "Sala 7" (S07) "Fila 12" (F12) "Butaca 8" (B08). Este tipo de composición se utiliza a veces para identificar las entidades por su ubicación, suponiendo el hecho de que sólo puede haber una entidad en un mismo sitio a un mismo tiempo. El principal problema que plantea este tipo de clave primaria es que a veces, en el mundo real, las entidades se extravían y acaban en localizaciones distintas a las que indican sus códigos, siendo necesario cambiar las claves primarias en la tabla principal y en todas las tablas en las que aparezcan referenciadas, lo que puede ser bastante laborioso, por no decir engorroso y proclive a errores.

El párrafo anterior nos da las dos últimas pistas definitivas para entender el por qué no hay que utilizar DNI como clave primaria de la tabla de personas. La primera pista es que una clave primaria nunca puede depender de información introducida manualmente. Si se hace depender el valor de una clave primaria de lo que escriba un usuario se está creando una dependencia brutal de éste con el funcionamiento interno del sistema. El acoplamiento entre capas de una aplicación siempre debe ser débil, de forma que se pueda modificar cada componente de forma individual sin afectar al resto, y en consecuencia, las reglas que rigen el mundo real no tienen porque influir en las que se establecen en el interior de una aplicación. Si la clave primaria de la tabla persona fuera DNI, y el día de mañana se decidiera utilizar el NIF, entonces se tendría que cambiar todo el modelo y los procesos para gestionar la clave como un campo alfanumérico en vez de como sólo nunérico. Si DNI no fuera clave entonces bastaría con cambiar ese campo concreto de forma aislada.

La segunda pista es que una clave primaria nunca ha de poder modificarse. La clave primaria de un registro identifica de forma unívoca a un objeto dentro del dominio que se está modelando. Si se cambia la clave primaria de un registro se produce una "mutación" por la cual el registro pasa a representar a otro objeto. Este aspecto quizás sea un poco sutil de entender, sobre todo por que conlleva cierto nivel de abstracción. Una persona se podría decir que es la suma de sus características individuales, así como del lugar que ocupa en cualquiera de las dimensiones en las que se proyecta (y posiblemente de su ausencia en las dimensiones en las que no se proyecta). Es una entidad, un ser único y distinguible. Su clave primaria ha de identificarlo de forma unívoca, si se cambia representaría otra entidad, no al individuo original. Piense en términos de variables, como las que se utilizan normalmente en cualquier lenguaje de programación. Primero se definen, y luego se les puede cambiar su contenido, de igual forma que una persona puede cambiarse de ropa o de peinado. Las variables siempren hacen referencia a una misma información concreta, independientemente del valor que contengan en un momento dado. Con las personas ocurre lo mismo, da igual el peinado o la ropa que llevemos, e incluso donde nos encontremos, por encima de todo seguimos siendo nosotros mismos, no otros. Si a una persona se le cambia su DNI porque se introdujo un número equivocado en el alta, debe seguir siendo la misma entidad que se insertó originalmente en el sistema, no otra distinta que implique una actualización masiva de las relaciones.

En definitiva, la forma correcta de identificar las entidades en una tabla es utilizar un código o identificador único que carezca de significado en el mundo real. Un simple valor numérico generado de forma secuencial es suficiente. La idea es crear una tabla con una primera columna de tipo numérico que sirva como clave primaria. En el ejemplo inicial, la tabla de personas, podría ser algo como: ID_PERSON NUMBER(10) NOT NULL. De forma que cuando se inserte una primera persona en la tabla se le asigne el valor 1 como clave primaria (ó 1527, es indistinto). Cuando se inserte una nueva persona se le asigne el 2 (ó 1528). Y así sucesivamente. De esta forma no hay posibilidad de conflictos, o lo que es lo mismo, de encontrarse con errores por claves primarias duplicadas. Cada persona queda emparejada con un identificador que le distingue unívocamente del resto. Y lo dicho para persona sirve para cualquier tipo de entidad. Un motor no se identifica por su número de bastidor, sino por su clave primaria. Un televisor no se identifica por su número de serie, sino por su clave primaria. Una factura no se identifica por su número, sino por su clave primaria. Un usuario no indentifica por su nombre, sino por clave primaria. ¿Captan la idea?

Esta forma de definir las claves suele crear bastante confusión en los desarrolladores no acostumbrados a esta forma de modelar. Las primeras cuestiones que se suelen plantear son la tocantes al rendimiento, sobre todo porque las búsquedas por columnas como DNI son bastantes habituales. Al dejar de ser parte de la clave primaria hay que definir índices adicionales sobre las tablas para estas columnas. Algunos diseñadores reniegan espontáneamente cuando se sugiere añadir varios índices sobre una misma tabla alegando que corresponde a un mal diseño. Pero entonces, ¿para qué diablos queremos los índices?. Otra cuestión habitual que se suele plantear es cómo generar las claves primarias. La respuesta creo que depende en gran medida de las herramientas que se utilicen para desarrollar. Oracle por ejemplo proporciona los objetos de tipo SEQUENCE, que generan valores secuenciales de forma atómica. Algunos gestores permiten indicar que las columnas sean autoincrementales, de forma que cada vez que se inserta un registro se genera automáticamente un nuevo valor. Los "gurús" suelen divagar acerca de aspectos tales como si es necesario utilizar una única secuencia para todas las entidades del sistema o una secuencia distinta para cada tabla. Lo que está claro es que nunca se debe ejecutar COUNT o MAX sobre las tablas para obtener el siguiente secuencial, son atentados directos contra la integridad y el rendimiento de la aplicación. Otra cuestión que se suele plantear es el tema del tamaño requerido por la columna de la clave primaria. Un tamaño de 10 representa una cantidad de diez billones de valores posibles, suficiente para la mayoría de aplicaciones de propósito general. Lo que hay que hacer sobre todo es que todas las tablas tengan una columna de clave primaria con el mismo tamaño, no cada una con un tamaño distinto ajustado en función de su ocupación estimada. Referente a esta última cuestión, hay que matizar que añadir una columna de tamaño diez no implica añadir automáticamente 10 bytes por registro, el espacio adicional requerido dependerá enteramente del gestor de base de datos que se esté utilizando.

Trabajar con tablas definidas de esta forma por primera vez puede resultar un tanto inquietante al principio. Puede parecer que mantener la coherencia de tantos identificadores es algo complicado, pero no lo es, de hecho, hoy en día es la forma más natural de diseñar y trabajar. Simplifica el diseño de las capas de persistencia con las que se consiguen mapear los objetos en memoria, al tiempo que ayuda a separar la información que resulta significativa para los usuarios de la forma en que se gestiona internamente. Si sus herramientas no soportan esta forma de trabajar vaya pensando seriamente en sustituirlas por otras nuevas.

Y por último, no quería dejar de comentar el hecho de que seguramente todos estos razonamientos parezcan complicaciones innecesarias para sistemas pequeños en ambientes muy controlados. Sin embargo, pensar así es olvidar una máxima informática que hay que tener siempre muy presente: ¡los requerimientos siempren cambian!

¿No encontró lo que buscaba?

Utilice el buscador para encontrar más páginas en esta web o en toda Internet.
 
Web www.inmensia.com
Waldemar (no verificado), 23 Marzo, 2009 - 17:59

Excelente artículo, justo lo que estaba buscndo para fundamentar mis ideas.
En mi experiencia he llegado a esta mismas practicas y a las mismas conclusiones.

Miguel Alzate (no verificado), 20 Mayo, 2009 - 17:02

Estoy de acuerdo con que el artículo es bueno, pero creo que le hacen falta ciertos temas. Por ejemplo, ¿cómo debe ser la llave primaria de tablas que manejan vigencias (fechas)? ¿Por qué a veces pareciera necesario que todas las columnas de una tabla deberían ser parte de la llave primaria? Etc.

Anónimo (no verificado), 21 Junio, 2009 - 07:54

Realmente me has despejado de muchas dudas. Es algo que muchos diseñadores que recién empezamos nos planteamos. Así que creo que diste en el clavo para aclarar nuestras dudas. Felicitaciones y esperamos otras ideas que tengas por allí.

Saludos desde Perú

Jany (no verificado), 15 Septiembre, 2009 - 06:02

Muy interesante el contenido del articulo, pero que hay de la validaciòn de los datos, el hecho de que la clave primaria sea un nùmero secuencial nos obliga a realizar una operacion màs al momento de insertar, que es la de validar que el registro no se encuentre duplicado.
Y si hablamos de una tabla que se identifica mediante 2 o 3 campos entonces estamos hablando de varias mas operaciones que debemos realizar por nuestra cuenta al realizar una inserciòn.

Juan Mellado, 16 Septiembre, 2009 - 07:38

Jany, la generación de los números para las claves primarias no es hoy en día un problema. La mayoría de los gestores de base de datos proporcionan campos autoincrementales u objetos de tipo secuencia. Relée el artículo, se habla de ello.

Y en general, no es necesario realizar ninguna comprobación previa. Cada inserción de un registro es equivalente a la creación de una entidad nueva, cada una con su ID propio, único.

Juan (no verificado), 23 Septiembre, 2009 - 11:06

Estoy parcialmente de acuerdo con este artículo.
En la práctica es cierto que es muy cómodo y ágil, incluir una columna para que actúe como clave primaria. Habitualmente son numéricos de 4 u 8 bytes. Es más, para el que comienza le pone las cosas muy fáciles.

Pero es cierto que va encontra de unos de los principios del modelo relacional, y es el de la redundancia de información, o la inclusión de información adicional innecesaria...

Si aceptamos la inclusión de un campo tipo numérico como clave primaria para todos los casos, estaríamos simplificando y reduciendo a un grado burdo toda la teoría relacional y los procesos de normalización de las tablas (relaciones) de la base de datos. Debemos recordar que se recomienda llevar las tablas al menos a una normalización de grado 3, siendo 5 el ideal.

Si hacemos esto en la práctica le quitamos gran parte de la "sustancia" al modelo relacional.

Es más, debido a práctica en este sentido, existen frameworks y librerías que te obligan a modificar el modelo de la base de datos (cuando debería ser al revés), porque no aceptan claves compuestas, o claves que no sean numéricas.

Juan Mellado, 8 Octubre, 2009 - 16:12

Crear una columna para la clave primaria nunca será "añadir información innecesaria" al modelo, y mucho menos crear redundacia. Precisamente lo que evita es que unos mismos datos estén esparcidos por todo el modelo, con el problema que ello implica cuando se realiza un cambio en los mismos.

No creo que le quite "sustancia" al modelo relacional, si no que refuerza las buenas prácticas del uso del mismo.

Anónimo (no verificado), 27 Octubre, 2009 - 19:30

Este comentario está totalmente en contra de la teoria del modelo relacional. Lo que se propone es equivalente a usar lo que en Oracle, por ejemplo, devolvería el ROWNUM. Sin duda es mucho más fácil para quien no controla bien la teoría y permite avanzar más deprisa en el análisis, pero traslada muchos más problemas al desarrollo. Todo lo que debería controlar el gestor de base de datos mediante integridad referencial, se transfiere al código de cada módulo que acceda a la tabla para hacer cualquier operación de manipulación de datos, como se ha indica en otro comentario, con el consiguiente incremento de errores.
Sin duda, el que lleve tiempo trabajando se ha dado cuenta de ello, sobre todo si se trabaja en equipos de desarrollo medianos o grandes, donde el mismo que ha creado la tabla no es el que trabaja con ella.
En cuanto a rendimientos, rara vez se accedería a un registro por esa clave, pues, como dices, no tiene ninguna información lógica. Siempre se haría por alguno de los otros campos que deberían ser la clave primaria. Un claro ejemplo es el que se cita, por ejemplo, el CIF. Un usuario de una aplicación realizará búsquedas por él, por ejemplo, nunca por ese ID secuencial. Y puesto que tiene que estar, ¿por qué no ser la clave?. Y de paso eliminamos el otro, que sobra.
Y otro error básico de concepto es de que la clave nunca debe ser modificada. Y de hecho, para eso existen los borrados y modificaciones en cascada.
Espero que no te moleste el comentario. Es un error de concepto que ya me he encontrado en muchas ocasiones con programadores que hacen sus primeros trabajos de análisis y diseño. Si te sirve de consuelo, la mayoría de ellos han reconocido su error al cabo del tiempo. Y la prueba de ello es la cantidad de tiempo que lleva funcionando el modelo relacional.
Un saludo.

Juan Mellado, 29 Octubre, 2009 - 13:17

La integridad referencial la sigue manteniendo el gestor de base de datos. Las "foreign keys" entre tablas siguen existiendo. En ningún momento se dice lo contrario. La diferencia está en que se propone usar una columna sin ningún significado funcional, en vez de una columna como el CIF.

La diferencia del planteamiento está en que no hace falta esparcir el CIF (o cualquier otro dato similar) por todas las tablas del modelo entre las que exista relación. Precisamente es cuando se utiliza campos como CIF cuando se introduce redundancia. El mismo dato "real" en varias tablas.

Y por supuesto, en ningún momento se traslada ningún problema al desarrollador. ROWNUM es otra cosa. Si queremos hablar de Oracle, fíjate que se habla de SEQUENCE para generar los secuenciales. Cualquier desarrollo propio o framework de terceros encapsularía esto en su capa de persistencia correspondiente de forma transparente. Es decir, se inserta un registro y se obtiene el ID del registro insertado. Ese ID se utiliza en los registros hijos para hacer referencia al padre y asi sucesivamente.

En cualquier caso, si la intención del comentario era decir: "con el modelo propuesto se puede introducir dos veces un mismo CIF, y pasa a ser responsabilidad del desarrollador comprobar ese tipo de cosas", entonces contestar que no. Ese problema se resuelve con un índice único sobre esa columna, sin necesidad de convertirla en clave primaria.

Respecto al rendimiento, comentar que para eso están los índices, particiones, etc. Por ejemplo, si la aplicación que estamos desarrollando presenta una interface al usuario para que haga búsquedas por el CIF, pues es normal que se cree un índice sobre dicha columna para optimizar las consultas. Y posiblemente por algunas otras.

Y tu comentario no molesta. Simplemente creo que no se ha entendido el artículo. En ningún momento se dice que esto sea una sustitución del modelo relacional. Sólo una recomendación acerca de la creación de claves primarias utilizando dicho modelo. Y ni siquiera es una idea original, lleva años haciéndose así.

Es probable que con el tiempo seas tú el que cambie de opinión. Piensa que tienes que hacer una tabla "personas", ¿qué clave elegirías?

Anónimo (no verificado), 29 Octubre, 2009 - 14:53

En el caso en que no haya un campo (o conjunto de ellos) que pueda identificar unívocamente a cada registro, como podría ser la tabla de personas que comentas, sí puedes usar un código inventado. Y, de hecho, es lo que se hace.

Algo distinto es aquellas entidades que sí lo tienen, como por ejemplo, las provincias. Si cada una tiene su código que no se repite, ¿qué necesidad hay de crear otro campo?. Si lo haces, puedes cometer el error de grabar 2 registros con el código de provincia 28, y colaría. ¿Qué se arregla creando un índice único?. Por supuesto, pero precisamente para eso está la PK y no necesitas crear otro campo.

Y el problema te lo vas a encontrar en el momento que tengas entidades que dependan de esa. Como sabes, en la definición de entidades, modelo previo al paso a tablas, no necesitas definir los campos heredados en entidades hijas. Si declaras la relación con heredable, te pasará los atributos en esa primera herencia, pero lo perderías en las siguientes. Así funcionan todas las herramientas de soporte al análisis. Por seguir con Oracle, por ejemplo, la herramienta Designer. Te propongo el ejemplo de provincias, de la cuelga localidades, y otra más que dependa de ésta. En la última, ya no aparecía el código de la provincia, a no ser que lo declares a capón, con la consiguiente posibilidad de cometer errores y multiplicación de recursos para el mantenimiento. Y, claro, puedes seguir manteniendo la integridas con FK, pero para eso necesitas tener los campos. Y si ya los tienes, ¿para qué crear otros?. Multiplicas las fuentes de error.
Sin ánimo de ofender, te diré que este error es típico de la gente que crea diréctamente las tablas sin pasar por la fase de análisis, sin tener previamente las entidades. Igual que la gente que se pone diréctamente a programar sin un análisis previo. Eso o el hecho de no trabajar con modelos medianos o grandes.
Puede que algún día cambie, pero no creo que sea en este tipo de modificaciones sobre el modelo relacional. Otra cosa es si hablamos de otros modelados diferentes. Hace casi 20 años que acabé la Ingeniería en Informática. Por aquel entonces ya se estudiaba el modelo entidad-relación, y desde entonces se lleva utilizando. El hecho de peinar canas en el oficio y haber pasado por todos los niveles, empezando desde abajo, con modelos desde 10 ó 12 tablas hasta modelos de más de 700, me permite hablar desde la experiencia.

Juan Mellado, 30 Octubre, 2009 - 11:43

- Me alegro de que estemos de acuerdo en lo referente a las tablas de tipo "personas". Lo que confirma que de alguna forma ya estás utilizando secuenciales para algunas claves primarias sin que ello signifique "renunciar al modelo relacional" (algo que creo no haber dicho en ningún momento).

- Lo de la tablas de tipo "provincias" para mi es el mismo caso que el del tipo "personas". Esa es la diferencia principal. Para mi son todas iguales. El hecho de que el código de una provincia TIENE que ser "28" es porque se tiene que utilizar para algunos procesos concretos que exigen que valga "28", y eso es lo que lo excluye a mi juicio como candidato a ser parte de la clave primaria y esparcirlo por todo el modelo.

- El problema que planteas para el ejemplo de las provincias yo no lo veo por ningún lado. Permíteme un esquema burdo:
  PROVINCIAS (id_provincia, nombre)
  LOCALIDADES (id_localidad, id_provincia, nombre)
  MONUMENTOS (id_monumento, id_localidad, nombre)
¿Por qué tendría que estar el id_provincia en la tabla de monumentos? ¿Donde están las fuentes de error? Quizás no te he entendido el ejemplo que proponías.

De lo que hablamos, es que para tí el id_provincia deber contener "códigos oficiales" como "28", y que para mí el id_provincia debe ser un valor carente de significado funcional y dicho "código oficial" debe identificarse y añadirse como un atributo más en la tabla de provincias.

Decir que una provincia es la "28" es adherirse a la nomenclatura y clasificación que "otros" han hecho de la entidad provincia. Y compromete al sistema a un ámbito de utilización en que dicha clasificación concreta tenga sentido. El uso de IDs genéricos para la realización física del modelo lo que pretende es aislar al desarrollo de este tipo de "compromisos", sobre todo de cara a futuros cambios.

- Y los comentarios de este tipo no ofenden, se agradecen.

Anónimo (no verificado), 2 Noviembre, 2009 - 13:10

No me he debido explicar bien en lo de la tabla personas, porque para nada estoy de acuerdo con lo que propones. Si relees mi comentario anterior, empiezo diciendo claramente que sólo en el caso de que no haya un campo o conjunto de ellos que identifiquen unívocamente al registro. Si tenemos el NIF, por supuesto que se usará ese, sin ningún tipo de duda. Lo que propones, va en contra de lo que usa el 99% de los analistas, y, creemé, no lo digo con ánimo de llevarte la contraria.
Y con el modelo de localidades, ¿no guardarías el código de la provincia en ningún lado?. ¿Sólo tendrías el que tú eliges, que dices es mejor y que no tienes que usar el que usa todo el mundo?. Piénsalo. Si eliges el que ya elegido el INE, por ejemplo, no necesitas otro. Y si no, ¿cómo sabes la provincia del monumento?. Tienes que tener también un código elegido por tí para identificar la localidad, que no se repita (vuelves a despreciar el del INE), otro código para el monumento... En fin, para tí, absolutamente todas las tablas tendrán un único campo secuencial que será el índice de la tabla.
Veo que es difícil que lo veas. Si me lo permites, te recomendaría que empezaras desde el principio, estudiando bien el modelo relacional. He tenido alumnos con tus mismas ideas cuando daba clases, la mayoría esperimentados programadores que creían haber descubierto una nueva teoría, pero a ellos tenía un curso por delante para convencerles. Todos, absolutamente todos, terminaron entendiéndolo, y no lo decían sólo para aprobar. De aquellos con lo tuve contacto después de la Universidad, TODOS lo hacen como te digo. Si conoces como dices el modelo relacional, sabrás que heredar la clave es uno de sus puntos básicos.
Y me preocupa que puedas influir en los jóvenes que empiezan ahora, porque te aseguro que no todos los jefes de proyecto tienen mi paciencia o espíritu de docencia, desgraciadamente, creo yo. Sé de muchos que si se encontraran con un modelo definido como comentas, prescindirían inmediatamente de su creador, porque creemé, es un error bastante grande que acarrea muchísimos costes posteriormente.
Un saludo, y creo que, por mi parte, se da por zanjado el tema, aunque me gustó el debate que me sacó de la rutina y me recordó mis años de docencia.

Juan Mellado, 2 Noviembre, 2009 - 14:57

De acuerdo, lo damos por zanjado. Aunque me siento obligado a responder a la pregunta que haces en el último comentario.

El código INE de una provincia es un atributo de provincia y habría que añadirlo como un atributo más a la tabla de provincias. Relée mi comentario anterior por favor. Es como el atributo "nombre" que puse de ejemplo.

No sé, quizás la falta de entendimiento en todo este tema se deba a que yo siempre hablo de "realización física" (modelo físico), y no de "diagramas de alto nivel" (modelo conceptual) donde evidentemente no aparecerían los IDs de la discordia.

Luis Villaverde (no verificado), 30 Enero, 2010 - 17:49

Yo estoy totalmente de acuerdo con lo defendido por este artículo. Por ejemplo la persona que está discutiendo el tema del código postal.

Mira mañana hay un acuerdo internacional y los códigos cambian de ser numéricos a ser mezcla de caracteres, por ejemplo el 28 pasaría a ser EUESMA342.

Con este sistema lo resolverías sencillamente, incluso, si en vez de ser un "texto" pasa a ser un objeto, pobrecito de ti...
Porque llegará un momento que a lo mejor manejas 500 o 600 tablas y a lo mejor el euqipo de trabajo ha cambiado, y para algún cambio en algún lado se os puede colar algo y luego pasa lo que pasa, por muy documentado que esté el proyecto, somos humanos.

Yo vengo programando así desde tiempos del dbase, pero el problema es que el tema de dni y codigos postales lo ponen mucho de ejemplo y la gente se queda con la cantinela cuando es UN ERROR GARRAFAL. Lo entenderás cuando trabajes con cantidades ingentes de datos, la cuestión es fácil. Hacerte la vida fácil o difícil.
Incluso el mantenimiento de las aplicaciones es mucho menor, te olvidas de "curiosos" sistemas de actualización de datos, por tener que cambiar el dni o una referencia a un artículo 4 años después.

Luis Villaverde (no verificado), 30 Enero, 2010 - 19:48

Se me ocurre un caso bastante común. Un sistema de facturación, donde le vendes a una universidad con NIF Q000000
PERO tienes que hacer facturas diferentes por centros y por departamentos.
Con el sistema de clave por nif, sería "imposible" porque se repetiría el NIF a lo mejor en 200-300 casos. Y habría que montar un tinglado de la repera para permitir eso.
Con la idea que se muestra en este artículo como si tienes 800 NIF iguales, uno puede ser de UNIVERSIDAD U - Rectorado, otro gestión, otro facultade de mate, otro...

Anónimo (no verificado), 27 Octubre, 2010 - 17:59

Hola a todos, soy novato en el tema y me interesa el tema ya que no consigo resolver el problema de las claves primarias en las tablas que surgen de las relaciones muchos a muchos, no se como hacerlas, no se si usar a clave autonumerica, una clave numerica incrementada por codigo. Al leer el debate generado por el articulo veo que la razón la teneis los dos en ciertos aspectos, pero no me aclara totalmente como resolver el problema de una base de datos con entidades maestras(que podrían tener una clave primaria tipo DNI, número de bastidor, etc) y entidades que surgen de relaciones muchos a muchos, ¡aquí es donde no se que hacer! si usar autonuméricos, numéricos incrementales o otro tipo de clave.

Juan Mellado, 27 Octubre, 2010 - 18:43

Uhm... ¿podrías especificar un poco mejor tu problema?

Si tienes una tabla A con clave id_a, otra tabla B con clave id_b, puedes tener tablas con claves compuestas (id_a, id_b), e incluso un índice por id_b si vas a acceder por esa columna.

Un ejemplo muy simple: alumnos (id_alumno) y cursos (id_curso)

Alumnos matriculados a un curso: (id_curso, id_alumno)

A un mismo curso pueden asistir muchos alumnos, y un alumno puede matricularse en muchos cursos. Y esas claves en las tablas maestras pueden ser IDs numéricos autogenerados.

futuro (no verificado), 2 Marzo, 2011 - 16:59

Que pasa con los Orm's y las tablas con clave primaria compuesta. He probado el adodb Activerecord y me da problema usarlo en esa situacion

lenny (no verificado), 6 Diciembre, 2011 - 20:13

Hola
Voy hacer una pregunta y me excuso si peco de ignorante.
¿cómo consulto un registro en una tabla que tenga una clave primaria autoincremntal?
Voy a dar un ejemplo
Tengo una tabla de empleados y si uso como clave primaria el DNI entonces puedo hacer una consulta para saber sus nombres, apellidos y sueldo, o mediante un formulario de entreda puedo colocar el DNI mediente el teclado y darle a un boton "Aceptar" y entonces me mostrará algunos datos que yo decida ponerle a la consulta.
Me explico mejor. Estoy en Dpto de Recursos Humanos y llega un empleado a pedirme una constancia de trabajo. Yo le pido su DNI para introducirla en una aplicación que me genera varios reportes sobre le enmpleado. En cambio creo que con una autoincremental debo darle el numero a cada empleado cada vez que lo ingrese a la Base de Datos. Si es una empresa de 50 0 100 empleados pues no hay mucho problema pero si en vez de empleados uso una tabla para registrar
3000 estudiantes de una Universidad.
Otro ejemplo mas grande. El rergistro electoral de un país.
Antes de una eleccion presidencial en un país "X" la oficina electoral decide tirar una jornada de actualización de electores colocando un punto de actualización en las calles. A cada ciudadano el Estado le asigna un DNI cuando saca su documento de identidad y con ese DNI el ciudadano va y se actualiza dandole al operardor¿ Si la oficina electoral trabaja con autoincremental entonces debera darle a un elector su núnmero correspondiente cada vez que se registre?
Teóricamente con la clave primaria autoincremental nunca voy a tener problemas ya que siempre va ser un valor unico ¿pero para los casos como los que expuse antes como se trabaja esta clave?

Juan Mellado, 7 Diciembre, 2011 - 15:31

Hola,
si tienes un formulario donde la entrada se hace por DNI (o número de empleado, o lo que quieras) entonces consultarás la tabla correspondiente por DNI, independientemente de que tenga un autoincremental como clave primaria.

No se trata de que tengas que cambiar los formularios para que en vez del DNI se introduzca el valor del autoincremental, ni mucho menos que los usuarios tengan que saberse esos números.

¿Cual es la ventaja entonces? Pues para verlo no tienes que pensar en 1 sola tabla maestra, sino pensar que existen otras 500 tablas con información asociada a ella.

Y además de pensar sólo en búsquedas directas por DNI, tienes que pensar que normalmente también existirán otros procesos, como listados de consultas, mantenimientos, cálculos automatizados, ...

Si para todo utilizas "de forma interna" (no de cara al usuario) los autoincrementales, entonces estarás protegiendo al sistema de cara a futuros cambios.

lenny (no verificado), 7 Diciembre, 2011 - 20:31

Hola
bueno ademas de la clave primaria autoincremental puedo estonces agregar un dni para una tabla maestro de empleados¿eso implica que puedo agragar un mismo DNI dos veces?
Está claro como el agua que la PK autoincremental va a ser un valor único y por nada del mundo se va a repetir pero entonces podria como mínimo crear dos veces a un mismo empleado o estudiante o profesor¿ Tendria entonces que controlar ese piosible error mediante programación?
Con usar PK autoincremental la integridad referencial queda perfectamente definida para todas las tablas que pueda relacionar, pero en el caso en tablas "maestras" estaría produciendo redundancia por lo cuál estaría irrespetando la 2º y 3º forma normal.

Juan Mellado, 7 Diciembre, 2011 - 23:41

- Para evitar agregar dos veces un DNI puedes usar un índice único definido sobre la columna DNI.

- Siempre vas a tener que controlar de alguna forma que no metes registros duplicados, ya sea usando DNI como clave primaria, un índice único, o un proceso más elaborado.

- Pues si te "molesta" la redundancia, no uses autoincrementales. Como puedes leer en el resto de comentarios, hay algunos que opinan que no se deberían usar salvo cuando no haya más remedio.

Lo que si sería interesante que consideraras es que el DNI pertenece al dominio de la aplicación (o sea, tiene significado en el mundo real), y el autoincremental es un identificador del registro que guarda la información (o sea, un dato ficticio añadido por consideraciones técnicas). Son cosas distintas más que redundantes.

Lenny (no verificado), 8 Diciembre, 2011 - 03:27

Hola
Muy interesane la discución sobre las PK autoincrementales. Gracias por tenerme algo de paciencia mi amigo Juan Mellado. Teoricamente veo que los PK autoincrementales son una manera robusta de enfrentar cambios futuros pero en la practica me genera una duda.
1.-Si uso PK diferentes a las autoincrementales sería mas facil la actualización en cascada.
2.-Con PK diferentes a los autoincrementales podria manejar mejor las restricciones de integridad referencial como lo son Elimninación e Inserción.

No se como atacaría los dos puntos descritos anteriormente usando PK autoincremental.

De verdad mil gracias por tenerme paciencia si estoy pecando de ignorante.

Juan Mellado, 8 Diciembre, 2011 - 14:15

1.-Si uso PK diferentes a las autoincrementales sería mas facil la actualización en cascada.

A eso no le veo sentido, o no entiendo lo que quieres decir. Precisamente usar autoincrementales evita tener que actualizar varias tablas.

Si tienes una tabla con DNI como clave primaria, y tienes que cambiar el DNI (o no lo sabes en el momento del alta, otro caso en que los autoincrementales son útiles, para hacer registraciones incompletas previas a la definitiva) entonces tienes que actualizar el DNI de todas las tablas asociadas.

Si tienes una tabla con autoincremental como clave primaria entonces no tienes que hacer nada. Cambias la columna con el DNI y punto.

2.-Con PK diferentes a los autoincrementales podria manejar mejor las restricciones de integridad referencial como lo son Elimninación e Inserción.

A eso tampoco le veo sentido. La integridad referencial es sólo una columna de una tabla hija con un valor que existe como clave primaria en una tabla maestra. Al insertar o eliminar da igual que ese valor sea un DNI o un autoincremental.