Bases de datos
Los símbolos: #, * y o
Qué significan exactamente el numeral, el asterisco y la o minúscula delante de cada atributo en la notación Barker, qué es un UID y cómo elegirlo bien.
Tres símbolos, tres preguntas
En la notación Barker —la que Data Modeler usa por defecto en el modelo lógico— cada atributo lleva delante un símbolo. No son decoración: cada uno responde una pregunta distinta sobre ese dato.
┌──────────────────────────┐
│ ALUMNO │
├──────────────────────────┤
│ # id_alumno │ ← identifica a la instancia
│ * nombre │ ← obligatorio
│ * email │ ← obligatorio
│ o telefono │ ← opcional
│ o fecha_nacimiento │ ← opcional
└──────────────────────────┘| Símbolo | Se lee | Significa | Al pasar a tabla |
|---|---|---|---|
# | numeral, hash | Forma parte del identificador único (UID) | PRIMARY KEY |
* | asterisco | Obligatorio: toda instancia tiene que tener un valor | NOT NULL |
o | o minúscula | Opcional: puede no tener valor | Acepta NULL |
Esa última columna es la razón por la que vale la pena aprenderlos bien: no son anotaciones informales, son decisiones que la base de datos va a hacer cumplir. Un * mal puesto es un NOT NULL que después rechaza filas legítimas; un * que faltó es una columna que se llena de vacíos.
La o viene de optional. Que el símbolo del atributo opcional sea una letra y no un signo de puntuación es raro al principio, pero tiene una ventaja práctica: en una lista de veinte atributos, los * y los # saltan a la vista y las o se hunden en el fondo — que es exactamente el orden de importancia que tienen.
El asterisco: obligatorio
* significa que toda instancia de esta entidad debe tener un valor para ese atributo. No “casi siempre lo tiene”: siempre, sin excepción, o la instancia no se puede guardar.
La prueba para decidirlo es concreta: piensa en un caso real que no tenga ese dato. Si se te ocurre uno, el atributo es opcional.
| Atributo de ALUMNO | ¿Existe un alumno sin esto? | Símbolo |
|---|---|---|
nombre | No, un alumno sin nombre no es un alumno | * |
email | Depende del negocio: si la inscripción es online, no | * |
telefono | Sí, muchos no lo dan | o |
fecha_egreso | Sí, todos los que todavía cursan | o |
Ese fecha_egreso ilustra el caso más frecuente de atributo opcional: un dato que se conoce recién más adelante. Marcarlo * haría imposible cargar un alumno el día que se inscribe.
Ante la duda, marca o. Pasar un atributo de opcional a obligatorio más adelante es fácil (se completan los que faltan y se agrega la restricción); al revés también es fácil, pero mientras tanto el sistema estuvo rechazando datos válidos o, peor, la gente los estuvo rellenando con basura —"sin datos", "-", "n/a"— para poder guardar. Esa basura después ensucia todas las consultas.
El numeral: el identificador único (UID)
# marca los atributos que forman el identificador único — el UID (unique identifier): el dato que permite señalar una instancia y solo una, sin ambigüedad.
Es la pieza más importante del modelo. Sin UID, dos alumnos llamados “Ana Ruiz” son indistinguibles, y ninguna otra entidad puede referirse a uno de los dos.
┌──────────────────────────┐
│ CURSO │
├──────────────────────────┤
│ # codigo │ "JAV-01" identifica a este curso y a ninguno más
│ * nombre │
│ * horas │
└──────────────────────────┘Un UID debe cumplir tres condiciones:
| Condición | Qué significa | Contraejemplo |
|---|---|---|
| Único | No hay dos instancias con el mismo valor | nombre — hay dos “Ana Ruiz” |
| Obligatorio | Nunca puede faltar | email si algunos alumnos no dan uno |
| Estable | No cambia con el tiempo | email — la gente lo cambia |
Un atributo # es obligatorio por definición: no tiene sentido identificar algo con un dato que puede faltar. Por eso en la notación Barker el # reemplaza al *, no se escriben los dos. En Data Modeler el atributo aparece marcado a la vez como parte del UID y como obligatorio, y esa doble marca es correcta — es lo mismo que dice el #.
UID compuesto: varios atributos juntos
A veces ningún atributo alcanza solo, pero la combinación de dos sí:
┌──────────────────────────┐
│ AULA │
├──────────────────────────┤
│ # edificio │ "A" solo no alcanza: hay un 12 en cada edificio
│ # numero │ "12" solo tampoco
│ * capacidad │ pero ("A", 12) identifica un aula y solo una
└──────────────────────────┘Los dos llevan # porque los dos forman parte del identificador. Al pasar a tabla, eso se convierte en una clave primaria compuesta por dos columnas.
UID natural o artificial
Aquí hay una decisión de diseño real, con argumentos de los dos lados:
| UID natural | UID artificial (surrogate) | |
|---|---|---|
| Qué es | Un dato que ya existe en el negocio | Un número inventado sin significado |
| Ejemplo | dni, isbn, codigo de curso | id_alumno autoincremental |
| A favor | Significa algo; no hay datos de más | Nunca cambia; siempre está; siempre es único |
| En contra | Puede cambiar, faltar o repetirse | No significa nada para nadie |
Los casos que hacen fallar a un UID natural aparecen siempre, y son más comunes de lo que parece: un DNI que estaba mal cargado y hay que corregir, un extranjero que no tiene, dos productos a los que el proveedor asignó el mismo código por error. Cuando eso pasa, cambiar el UID es carísimo, porque su valor está copiado en todas las tablas que lo referencian.
La práctica más extendida hoy es usar un UID artificial (id_alumno) y, si además existe un dato naturalmente único como el DNI, marcarlo como unique pero sin que sea el identificador. Así ganas la estabilidad del artificial sin renunciar a que la base impida DNIs repetidos. Este es el criterio que sigue el resto de la sección.
La o minúscula: opcional
o es simplemente lo contrario de *: el atributo puede no tener valor. Al pasar a tabla, la columna acepta NULL.
Y NULL merece una advertencia propia, porque es la fuente de sorpresas más común al consultar una base de datos:
NULL no es cero, ni cadena vacía, ni false: significa “no se sabe”. Y eso cambia cómo se comporta en las consultas. WHERE telefono != '555-1234' no devuelve las filas donde telefono es NULL, porque comparar con algo desconocido no da ni verdadero ni falso. Para esas filas hay que preguntar explícitamente con IS NULL. Cada o que pones en el modelo es un lugar donde después habrá que acordarse de esto.
El modelo del instituto, ahora con símbolos
Aplicando todo lo anterior al enunciado:
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ ALUMNO │ │ CURSO │ │ PROFESOR │
├──────────────────────┤ ├──────────────────────┤ ├──────────────────────┤
│ # id_alumno │ │ # codigo │ │ # id_profesor │
│ * nombre │ │ * nombre │ │ * nombre │
│ * email │ │ * horas │ │ * email │
│ o telefono │ │ o descripcion │ │ o telefono │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘Justificando cada decisión, que es lo que se te va a pedir defender:
id_alumnoeid_profesorson artificiales. No hay ningún dato natural del enunciado que sea único, obligatorio y estable a la vez.codigode CURSO sí es natural. El instituto ya usa “JAV-01” para identificar sus cursos: es un identificador que existe en el negocio y no hace falta inventar otro.telefonoesoen las dos entidades porque el enunciado dice literalmente “opcionalmente su teléfono” para el profesor, y para el alumno vale el mismo criterio.descripcionesoporque un curso se puede dar de alta antes de haber redactado su descripción.
Pon a prueba
Una tienda online guarda de cada cliente: nombre, apellido, email, teléfono y fecha de registro. ¿Cuál es el mejor identificador único?
Un hospital registra pacientes. La historia clínica es el número que el hospital ya usa para identificarlos. El nombre y la fecha de nacimiento se piden siempre; la obra social y el teléfono, no. Escribe el símbolo (#, * u o) delante de cada atributo.
PACIENTE
nro_historia_clinica
nombre
fecha_nacimiento
obra_social
telefonoEste modelo tiene cuatro errores en el uso de los símbolos. ¿Cuáles son?
┌────────────────────────────────┐
│ PEDIDO │
├────────────────────────────────┤
│ o nro_pedido │
│ * fecha_entrega │
│ # email_cliente │
│ o fecha_pedido │
└────────────────────────────────┘1. o nro_pedido. Es lo que identifica a un pedido, así que debería ser #. Un identificador nunca puede ser opcional: no se puede señalar una instancia con un dato que puede faltar.
2. * fecha_entrega. Marcarla obligatoria hace imposible cargar un pedido que todavía no se entregó — o sea, todos los pedidos nuevos. Es el ejemplo clásico de dato que se conoce más adelante: debe ser o.
3. # email_cliente. Dos errores en uno. Como UID falla en las tres condiciones (cambia, puede faltar, un cliente hace varios pedidos con el mismo email, así que ni siquiera es único por pedido). Y además el cliente no debería estar como atributo suelto de PEDIDO: es una entidad aparte, vinculada por una relación.
4. o fecha_pedido. Todo pedido se hace en un momento determinado y ese dato se conoce en el instante mismo en que se crea. Debe ser *.
Corregido:
┌────────────────────────────────┐
│ PEDIDO │
├────────────────────────────────┤
│ # nro_pedido │
│ * fecha_pedido │
│ o fecha_entrega │
└────────────────────────────────┘
│
└── relación hacia CLIENTE (próxima página)Siguiente paso
Las entidades ya están completas por dentro. Falta lo que las une: las líneas entre cajas, con su pata de gallo, su tramo continuo y su tramo punteado — cada uno de esos detalles significa algo preciso — ver Relaciones y cardinalidad.