entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Forma eficiente de gestionar claves compuestas en SQL

Estoy buscando la mejor forma de poder gestionar el siguiente caso.
Tengo una clase Cliente para la que necesito generar una referencia con una longitud prefijada de 9 dígitos, esta referencia debería contener como primeros dígitos el código del Local donde se dio de alta, seguido de ceros y luego un auto incremento relativo al numero de clientes dados de alta en ese local concreto.

Pongo un ejemplo para que se entienda mejor:
Tengo dos locales:
Madrid(cod=1)
Barcelona(cod=2).
Un cliente se da de alta en Madrid y se le asigna el código 100000001
otro se da de alta en Barcelona y se le asigna el código de cliente 2000000001.

Este código debe ser mostrado por pantalla en el formulario de creación de cliente por lo que debe estar disponible antes de insertar el registro en la base de datos, ademas son identificadores que serán públicos y se mostraran y utilizarán por distintas partes del programa y según tengo entendido NO es una buena práctica mostrar claves primarias(Id) de la base de datos a través de la interfaz y que estas sean manejadas por los usuarios, no se hasta que punto esto es verdad o si en este caso si sería aceptable, si alguien pudiera aclarármelo se lo agradecería.

Dado que el auto incremento es relativo al local y que lo necesito antes de haber insertado el registro creo que voy a tener que gestionar de forma manual, buscando cual es el último mediante una consulta SQL e incrementándolo en uno. Y no se si hacer esta consulta directamente a la tabla clientes o mantener en una tabla aparte el último código de cada local que es como lo he estado haciendo hasta ahora siempre que he necesitado algo parecido pero la verdad lo he estado haciendo sin saber si era la mejor manera o si SQL provee una forma mas fácil de manejar este tipo de situaciones y me gustaría saber vuestra opinión y poder aclararme del todo en este asunto.

Un saludo

1 Respuesta

2votos

Leonardo-Tadei Puntos227020

Hola @Javi2EE,

interesante cuestión... vamos por partes:

Primero: no hay ningún problema con que muestres los códigos 100000001 o 200000001 con la forma, pero si guardás un dato así, estás violando la Primera Forma Normal, porque tenés 2 datos en un mismo campo. Pero como no hay inconveniente en mostrar una cosa y guardar otra completamente diferente, tu tabla puede tener una estructura como esta:

Clientes
--------
id
num_suc
num_cli
...
...

para manejar los datos del cliente por su ID pero muego mostrar la concatenación rellenada con ceros que te hace falta.

b) Efectivamente, darle libertad al usuario de poner claves, primarias o no, no es una buena práctica, porque en caso de que te la cambien pueden hacer un buen lio... por ejemplo en este caso, a un cliente de Barcelana ponerlo como de Madrid. Es algo que se podría resolver con mucha valiadción y cuidado, pero desaconsejado.
Si además el software es web, esta práctica es inviable, porque en caso de darse se alta dos clientes de Madríd a la vez, no tenés como garantizar que el número preasignado sea el que efectivamente corresponda, por la concurrencia inherente a las cosas en Internet.
Esto tiene una solución fea, que trae otros muchos problemas: al ingresar al formulario dar de alta un registro con estos datos y lo demás en blanco, y al terminar el alta actualizarlo y ponerle los datos cargados. Los problemas que esto trae es generar registros blancos (sin poder validar en la DB campos no nulos ni relacionados) y el tener que borrar los registros craedos que no son usados porque el cliente no termina el alta.

c) respecto a tener que generar manualmente el próximo número de cliente, yo creo que es mejor hacerlo sobre la tabla real, ya que hacerlo sobre una tabla auxiliar te crea el problema de tener que mantener sincronizados los datos, lo que no es tan sencillo como parece en entornos multiusuario concurrentes.

Saludos cordiales!

0voto

Javi2EE comentado

Gracias por la respuesta, me has ayudado bastante al recordarme que es multiusuario concurrente, a veces en un entorno de desarrollo estas cosas se pasan por alto y luego vienen los problemas. Vistas las opciones creo que en este caso concreto voy a optar por una solución intermedia para poder mantener la validación en la BBDD, en lugar de crear un nuevo cliente en blanco, voy a guardar la secuencia en una tabla auxiliar en el momento de abrir el formulario y solo insertar el cliente cuando este esta creado, con este sistema puede que queden algunos códigos sin asignar pero en este proyecto concreto prefiero eso a tener que controlar la creación y destrucción de usuarios incompletos y a tener que validar a mano. Gracias por tu tiempo!

0voto

Javi2EE comentado

Actualización al comentario anterior: lo de dejar códigos en blanco sin asignar no es solución, ahora mismo lo que hago es consultar en la tabla real el siguiente código y se muestra en el formulario, al momento de guardarlo si ese código ha sido ocupado se asigna automáticamente el siguiente y se guarda, y muestro una advertencia por pantalla con el código asignado.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta