Respecto a PKs

29/03/2008 - 13:10 por Juan Diego Bueno | Informe spam
Buenas gente:

El otro día escuché que las IDs en claves primarias deberían ser
enteras para su uso con índices y que no es bueno usar varchar para
ello. Todo eso está muy bien, pero a mi se me plantea una situación en
la que no lo acabo de ver con ids exclusivamente numéricos. Se trata
de una BD distribuida que converge en un nodo central. Cada inserción
de un registro en alguno de los nodos de esta BD no se actualiza en
tiempo real en la central, sino que se transfiere mediante una
exportación. En ese caso, a mi me cuesta pensar en claves numéricas o
autonuméricas, puesto que evidentemente a cada inserción de registro
en dos nodos diferentes, le van a corresponder los mismos IDs. El
trabajo de tener que reorganizar esos IDs en la BD central, y por ende
cambiarlos de forma que no coincidan con los de los nodos me parece
que entraña mucho riesgo, a la par que me gustaría que fueran
idénticos ambos registros.

Es por ello por lo que recurro a varchars que de alguna manera
incluyen información sobre cada uno de los nodos codificada.

¿Podríais darme alguna solución alternativa o decirme si aún así es la
correcta?

Un saludo

Preguntas similare

Leer las respuestas

#11 Alfredo Novoa
31/03/2008 - 22:10 | Informe spam
Hola Juan Diego,

On 31 mar, 20:31, "Juan Diego Bueno"
wrote:

> Para recuperar el 100 tienes que hacer un
> CAST(SUBSTRING(CAMPO,4,nosecuanto) as int) y esto si que es un coñazo
> y no lo de la clave externa con 2 campos.

Pero es que yo el 100 ya lo tengo en otro campo, y compongo el valor de la
columna con ese campo y el otro código que te dije. Además, generalmente
nunca uso ese id numérico para las consultas, por lo tanto nunca necesito
hacer ningún substring ni similar. Si el problema es la redundancia, ya que
tengo una PK que vale EB-100 y otro campo que vale 100 y eso vulnera... no
recuerdo que forma normal (creo que la segunda) lo entiendo, pero por nada
más.



Pues no es poco. Y además necesitas usar SUBSTRING para recuperar el
EB.

Además, no suelo necesitar el número de orden del registro, con lo cual
podría generar ese id numérico e integrarlo en la columna que sirve de PK
sin necesidad de tenerlo en otro campo.



Tampoco te digo que no te pueda servir para salir del paso, pero es
bastante chapuza y bastante más complicado que hacerlo de la forma
"normal".

Lo de la clave externa con dos
campos me complica mucho sobre todo a la hora de programar la aplicación
cliente y tener que utilizar dos claves foráneas.



Y eso es mucho más sencillo que asegurar la integridad referencial de
tu campo compuesto. Si yo meto el código JB-666 a ver como compruebas
que existe un nodo que se llama JB.

Por ejemplo, supongamos un
combo que me muestra datos de una tabla relacionada que tiene una clave
principal compuesta. Pensando en .NET, ese combo tiene un VALUEMEMBER  y un
DISPLAYMEMBER ambos procedientes de diferentes campos de una tabla (ID,
DESCRIPCION). Así es simple, con una columna como clave principal, pero si
pensamos en una PK compuesta por NODOID, ID, ya tengo que recurrir a, como
mínimo un struct para reflejar eso, sin contar luego los problemas en
términos de databinding. No lo acabo de ver...



Pero este ejemplo no tiene sentido. Como vas a meter eso en un combo.
Además juntar es más fácil que separar. Si necesitas hacer una ñapa
por las limitaciones de un control visual pues la haces en la consulta
con algo como: select a+b from ..., y dejas que la base de datos siga
bien diseñada.

Además si tienes un campo DESCRIPCION que es clave te sobra el ID.


Saludos
Alfredo
Respuesta Responder a este mensaje
#12 Juan Diego Bueno
01/04/2008 - 10:29 | Informe spam
Hola Alfredo:

A ver, yo te explico el por qué hago lo que hago porque igual he
explicado mal lo que hago y por qué lo hago.

Vamos a suponer que tengo una tabla de nodos con las siguientes
columnas:

ID_NODO: Tiene la forma COD_NODO-XX. Es la PK y no puede modificarse.
XX es un código numérico de control generado en la inserción
COD_NODO: Es el código del nodo, el cual si es modificable. Tiene
restricción UNIQUE. Es el que hasta ahora he llamado EB
NOMBRE_NODO: El nombre del nodo.

El COD_NODO puede ser cambiado por el usuario, con lo cual, si yo tengo
EB-00 como PK y decido cambiar el código, ese registro seguirá
constando como EB-00, pero con código MO (el que podría ser el nuevo
valor). Por lo tanto no hay ninguna dependencia entre columnas dentro
de un mismo registro.

Ahora supongamos que tengo una tabla departamentos tal que así:

ID_DPTO: Tiene la forma COD_DPTO-YY, donde YY es un código de control
COD_DPTO: Igualmente, un código de departamento definido por el usuario
que graba y crea los departamentos. Al igual que con la anterior
entidad, no depende la PK de este código, puesto que se puede modificar
a posteriori mientras que la PK permanecería inalterada. También UNIQUE
NOMBRE_DPTO: Descripción del departamento
ID_NODO: Id del nodo al que pertenece este departamento, clave foránea
relacionada con la principal de nodos.

Por último, una tabla de personal:

ID_PERSONAL: Se puede crear, ya sea utilizando el nif o componiendolo
con nombre y apellidos más un código de control similar a los
anteriores. Es la PK
NIF: Con restricción UNIQUE. También puede ser cambiado por el usuario,
con lo que si la ID_PERSONAL no depende directamente de él, ya que esa
nunca cambiará
NOMBRE_APELLIDOS: Nombre y apellidos del personal
ID_DPTO: Id del departamento al que pertenece. Clave foránea de la
tabla departamentos

En las tres entidades, la PK no es visible por el usuario que crea,
modifica y elimina los registros, únicamente lo es el código

Vamos con lo que tu planteas:

Pues no es poco. Y además necesitas usar SUBSTRING para recuperar el
EB.



El código del nodo lo puedo recuperar con una simple query con uno o
varios joins

Y eso es mucho más sencillo que asegurar la integridad referencial de
tu campo compuesto. Si yo meto el código JB-666 a ver como compruebas
que existe un nodo que se llama JB.



Más de lo mismo, con una query

Por ejemplo, supongamos un
combo que me muestra datos de una tabla relacionada que tiene una clave
principal compuesta. Pensando en .NET, ese combo tiene un VALUEMEMBER  y un
DISPLAYMEMBER ambos procedientes de diferentes campos de una tabla (ID,
DESCRIPCION). Así es simple, con una columna como clave principal, pero si
pensamos en una PK compuesta por NODOID, ID, ya tengo que recurrir a, como
mínimo un struct para reflejar eso, sin contar luego los problemas en
términos de databinding. No lo acabo de ver...



Pero este ejemplo no tiene sentido. Como vas a meter eso en un combo.
Además juntar es más fácil que separar. Si necesitas hacer una ñapa
por las limitaciones de un control visual pues la haces en la consulta
con algo como: select a+b from ..., y dejas que la base de datos siga
bien diseñada.



En el caso del personal, tendría la tabla asociada por databindings a
un form que tendría un combo con el departamento, el cual mostraría el
nombre de departamento tomado de su tabla correspondiente, y en el
valuemember el id de departamento asociado por databinding a la tabla
de personal. A eso me refiero, únicamente necesito un campo para ello y
es muy sencillo.

No veo además que vulnere ningún principio de información, puesto que
las tablas están perfectamente relacionadas unas con otras. Y respecto
a la dependencia entre columnas es ficticia, solo se hace en la
inserción y por obtener un id único para la PK que después va a
permanecer inalterable, manteniendo la unicidad de los registros con
cláusulas UNIQUE. No necesito substrings ni cosas raras para obtener
los códigos, ya que una query me los da.

Espero tus pegas o las de otros al diseño

Un saludo

http://www.moondance.tk
Respuesta Responder a este mensaje
#13 Alfredo Novoa
01/04/2008 - 13:10 | Informe spam
Hola Juan Diego,

On Tue, 01 Apr 2008 10:29:33 +0200, Juan Diego Bueno
wrote:

ID_NODO: Tiene la forma COD_NODO-XX. Es la PK y no puede modificarse.
XX es un código numérico de control generado en la inserción
COD_NODO: Es el código del nodo, el cual si es modificable. Tiene
restricción UNIQUE. Es el que hasta ahora he llamado EB
NOMBRE_NODO: El nombre del nodo.

El COD_NODO puede ser cambiado por el usuario, con lo cual, si yo tengo
EB-00 como PK y decido cambiar el código, ese registro seguirá
constando como EB-00, pero con código MO (el que podría ser el nuevo
valor). Por lo tanto no hay ninguna dependencia entre columnas dentro
de un mismo registro.



Pues no entiendo el diseño. No se para que quieres el ID_NODO si ya
tienes el COD_NODO.

No se para que puede servir almacenar un código de control y en el
caso en el que sirviese para algo debería de ir él solo en una columna
a parte.

Tampoco se muy bien para que quieres el COD_NODO si ya tienes
NOMBRE_NODO.

Ahora supongamos que tengo una tabla departamentos tal que así:



Aquí lo mismo.

Por último, una tabla de personal:

ID_PERSONAL: Se puede crear, ya sea utilizando el nif o componiendolo
con nombre y apellidos más un código de control similar a los
anteriores. Es la PK
NIF: Con restricción UNIQUE.



Si NIF es único entonces podrías usarlo como identificador aunque se
pueda cambiar.

Vamos con lo que tu planteas:

Pues no es poco. Y además necesitas usar SUBSTRING para recuperar el
EB.



El código del nodo lo puedo recuperar con una simple query con uno o
varios joins



Cosa que cuesta bastante más trabajo que acceder directamente a un
campo simple.

Y eso es mucho más sencillo que asegurar la integridad referencial de
tu campo compuesto. Si yo meto el código JB-666 a ver como compruebas
que existe un nodo que se llama JB.



Más de lo mismo, con una query



Una query disparado por un trigger que tiene que lanzar una excepción
en caso de que no se cumpla la regla de integridad referencial.

Mucho más complicado que usar una FOREIGN KEY sobre campos simples.

Pero este ejemplo no tiene sentido. Como vas a meter eso en un combo.
Además juntar es más fácil que separar. Si necesitas hacer una ñapa
por las limitaciones de un control visual pues la haces en la consulta
con algo como: select a+b from ..., y dejas que la base de datos siga
bien diseñada.



En el caso del personal, tendría la tabla asociada por databindings a
un form que tendría un combo con el departamento, el cual mostraría el
nombre de departamento tomado de su tabla correspondiente, y en el
valuemember el id de departamento asociado por databinding a la tabla
de personal. A eso me refiero, únicamente necesito un campo para ello y
es muy sencillo.



No se para que podrías querer un código compuesto en una tabla de
departamentos.

No veo además que vulnere ningún principio de información, puesto que
las tablas están perfectamente relacionadas unas con otras.



Lo vulnera por que representas la relación entre EB y 00 por medio de
una cadena de caracteres 'EB-00' en lugar de hacerlo utilizando una
tabla.

El principio de información no tiene nada que ver con que unas tablas
estén "bien relacionadas" con otras (cosa que no se muy bien lo que
significa), sino con que la información debe de ser representada
usando relaciones, y el "equivalente" SQL de una relación se llama:
"Tabla".

Las relaciones del Modelo Relacional no tienen nada que ver con las
claves externas.

Y respecto
a la dependencia entre columnas es ficticia, solo se hace en la
inserción y por obtener un id único para la PK que después va a
permanecer inalterable, manteniendo la unicidad de los registros con
cláusulas UNIQUE. No necesito substrings ni cosas raras para obtener
los códigos, ya que una query me los da.



Pero por que tienes un montón de redundancia.


Saludos
Respuesta Responder a este mensaje
#14 Juan Diego Bueno
01/04/2008 - 13:46 | Informe spam
Hola Alfredo:

Tengo la impresión de que no te voy a entender en la vida, así que
simplemente aclarar ciertos aspectos y dar por zanjado el tema, por lo
que a mi respecta.

Pues no entiendo el diseño. No se para que quieres el ID_NODO si ya
tienes el COD_NODO.



Para tener una clave primaria que permanezca inmutable. El código de
nodo es para que el usuario codifique los nodos.


No se para que puede servir almacenar un código de control y en el
caso en el que sirviese para algo debería de ir él solo en una columna
a parte.



Es un código irrelevante, no guarda información, es para otra cosa que
me va a costar explicar aquí. En otros casos, si he guardado ese
código aparte.


Tampoco se muy bien para que quieres el COD_NODO si ya tienes
NOMBRE_NODO.



Porque todo Dios codifica sus registros. Cada factura tiene su número,
cada artículo, su código, etc... y esto es a nivel de usuario. Lo
mismo para el resto de tablas. Repito que lo que quiero hacer con esto
es evitar a toda costa updates que modifiquen la PK


>El código del nodo lo puedo recuperar con una simple query con uno o
>varios joins

Cosa que cuesta bastante más trabajo que acceder directamente a un
campo simple.



Obviamente, en el caso que nos ocupa, siempre voy a necesitar hacer
joins para obtener a que nodo pertenece en un momento dado un personal


>> Y eso es mucho más sencillo que asegurar la integridad referencial de
>> tu campo compuesto. Si yo meto el código JB-666 a ver como compruebas
>> que existe un nodo que se llama JB.

>Más de lo mismo, con una query
Una query disparado por un trigger que tiene que lanzar una excepción
en caso de que no se cumpla la regla de integridad referencial.
Mucho más complicado que usar una FOREIGN KEY sobre campos simples.



Yo es que no veo por ninguna parte que se vulnere la integridad
referencial. Todas las tablas están relacionadas con claves foráneas
contra PKs. No uso triggers, la propia constraint me asegura eso. El
campo, aunque se haya creado inicialmente a partir de otros, es un
campo simple.

No se para que podrías querer un código compuesto en una tabla de
departamentos.


Lo vulnera por que representas la relación entre EB y 00 por medio de
una cadena de caracteres 'EB-00' en lugar de hacerlo utilizando una
tabla.



No existe tal relación. El 00 es un código de apoyo en la creación de
la clave, nada más.

El principio de información no tiene nada que ver con que unas tablas
estén "bien relacionadas" con otras (cosa que no se muy bien lo que
significa), sino con que la información debe de ser representada
usando relaciones, y el "equivalente" SQL de una relación se llama:
"Tabla".

Las relaciones del Modelo Relacional no tienen nada que ver con las
claves externas.


> Y respecto
>a la dependencia entre columnas es ficticia, solo se hace en la
>inserción y por obtener un id único para la PK que después va a
>permanecer inalterable, manteniendo la unicidad de los registros con
>cláusulas UNIQUE. No necesito substrings ni cosas raras para obtener
>los códigos, ya que una query me los da.

Pero por que tienes un montón de redundancia.



Bajo mi punto de vista, una poca nada más y simplemente como
metodología de creación de claves con otros fines. Lo acepto así
porque me sirve para conseguir otro objetivo cuyas otras alternativas
no me convencen. Es más, si de repente decidiera hacer un recodificado
completo de todas las tablas (a nivel de la columna código que ve el
usuario), la PK ya no tendría ningún tipo de relación redundante con
el resto del registro, y respecto al código, imagina que es un
apéndice que sirve para muy poco, aunque se que esto último te
parecerá una estupidez (ya son muchos posts tuyos leídos, jejeje).

Un saludo
Respuesta Responder a este mensaje
#15 Alfredo Novoa
01/04/2008 - 16:07 | Informe spam
Hola Juan Diego,

On Tue, 1 Apr 2008 04:46:52 -0700 (PDT), Juan Diego Bueno
wrote:

Pues no entiendo el diseño. No se para que quieres el ID_NODO si ya
tienes el COD_NODO.



Para tener una clave primaria que permanezca inmutable. El código de
nodo es para que el usuario codifique los nodos.



En principio no hay ninguna razón por la que las PK tengan que ser
inmutables, pero si tu quieres que lo sean de todas formas por motivos
funcionales, entonces no le veo sentido a tener otro código cambiable.

Es un código irrelevante, no guarda información,



Entonces obviamente lo deberías eliminar.

es para otra cosa que
me va a costar explicar aquí.



Ya, con información incompleta no se puede aconsejar.

Tampoco se muy bien para que quieres el COD_NODO si ya tienes
NOMBRE_NODO.



Porque todo Dios codifica sus registros. Cada factura tiene su número,
cada artículo, su código, etc... y esto es a nivel de usuario. Lo
mismo para el resto de tablas.



En el caso de una factura y un artículo tiene sentido tener códigos,
pero en montones de otros casos no lo tiene. Meter sistemáticamente
códigos a todas las entidades es una tontería. Solo hay que codificar
cuando hace falta. Y en la gran mayoría de los casos los códigos deben
de ser alfanuméricos y nemotécnicos (o memotécnicos:). Por ejemplo el
código 'ALCO' es bastante mejor que el código 666 para referirse al
almacén de Alcorcón.

Repito que lo que quiero hacer con esto
es evitar a toda costa updates que modifiquen la PK



Lo que no entiendo es por que quieres evitar que modifiquen la PK.

Obviamente, en el caso que nos ocupa, siempre voy a necesitar hacer
joins para obtener a que nodo pertenece en un momento dado un personal



Se podría hacer con una simple selección y proyección.

Lo vulnera por que representas la relación entre EB y 00 por medio de
una cadena de caracteres 'EB-00' en lugar de hacerlo utilizando una
tabla.



No existe tal relación. El 00 es un código de apoyo en la creación de
la clave, nada más.



Por supuesto que existe por que la podemos ver, y tu has explicado
como formas los identificadores asociando el código de nodo con otro
código. Obviamente los estás relacionando aunque luego permitas romper
la relación.

Pero por que tienes un montón de redundancia.



Bajo mi punto de vista, una poca nada más y simplemente como
metodología de creación de claves con otros fines.



La redundancia en el modelo lógico es una chapuza siempre evitable.

Lo que estamos discutiendo es si se puede hacer mejor, y la respuesta
es: rotundamente si.

Lo acepto así
porque me sirve para conseguir otro objetivo cuyas otras alternativas
no me convencen.



Pues yo sigo sin ver el objetivo.

Es más, si de repente decidiera hacer un recodificado
completo de todas las tablas (a nivel de la columna código que ve el
usuario), la PK ya no tendría ningún tipo de relación redundante con
el resto del registro, y respecto al código, imagina que es un
apéndice que sirve para muy poco, aunque se que esto último te
parecerá una estupidez (ya son muchos posts tuyos leídos, jejeje).



Yo creo que el problema es que tienes metido en la cabeza que las PK
no se pueden cambiar cuando es totalmente falso.


Saludos
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida