Dónde vive cada dato: variable, archivo y tabla

David TorresInformática y FPLeave a Comment

Tres formas de nombrar un dato: el identificador de una variable, la ruta de un archivo y la clave primaria de una fila

Tres sitios donde puede estar un dato

Tienes el número 17. La edad de alguien, pongamos.

Ese 17 puede estar en tres sitios distintos, y en cada uno se comporta de otra manera:

  • En memoria, mientras tu programa se ejecuta. Se llama edad, y desaparece cuando el programa termina.
  • En un archivo, en el disco. Se llama datos.txt, y sigue ahí mañana.
  • En una tabla de una base de datos. Es una fila, y se llama 1 — su clave primaria.

Los tres guardan el mismo 17. Lo que cambia es cómo lo señalas. Y casi todos los atascos de las primeras semanas son señalar mal: creer que apuntas a algo cuando apuntas a otra cosa, o a nada.

Vamos uno por uno, y al final los juntamos en un solo ejercicio.

En memoria: la variable

Esta línea de Java tiene tres cosas, no una:

int edad = 17;

int es el tipo: qué clase de dato es y qué se puede hacer con él. edad es el nombre: cómo te refieres a ese hueco de memoria. 17 es el valor: lo que hay ahora mismo.

El nombre es lo importante para lo que nos ocupa. Una variable no contiene el valor: le pone nombre a un sitio donde hay un valor. Por eso la metáfora de la caja se queda corta en cuanto avanzas.

Declarar no es lo mismo que asignar

Son dos operaciones que esa línea junta:

int edad;        // declarar: reserva nombre y tipo
edad = 17;       // asignar: guarda un valor

Si intentas usarla entre una cosa y la otra, el compilador de Java te para:

error: variable edad might not have been initialized

No es un capricho. El hueco existe desde la primera línea, pero no hay nada válido dentro, y Java prefiere no dejarte leer basura.

El tipo no es una etiqueta: decide qué puedes hacer

Esto no compila:

edad = "diecisiete";
// error: incompatible types: String cannot be converted to int

Y esto compila, pero no da lo que esperas:

int mitad = 7 / 2;   // 3, no 3,5

Entre dos enteros la división también es entera: el resto se descarta. Es el origen de media docena de errores del primer trimestre, y lo vas a ver otra vez dentro de un momento, cuando el ejercicio calcule la mitad de 17.

En un archivo: la ruta

El 17 en memoria desaparece cuando el programa termina. Si quieres que siga ahí mañana, tiene que estar en un archivo. Y un archivo se señala con una ruta.

Aquí está el árbol con el que vamos a trabajar. Es el mismo de la pieza de rutas, con otro archivo dentro:

practicas
├── datos.txt
└── entrega
    └── Edad.java

A datos.txt se llega de dos formas, y la diferencia es toda la cuestión:

  • Ruta absoluta: /home/alumno/practicas/datos.txt. Empieza en la raíz. Significa lo mismo desde cualquier sitio.
  • Ruta relativa: datos.txt, o ../datos.txt. Empieza donde estás. Más corta, y depende de dónde estés.

«Donde estás» tiene un nombre y un comando. Se llama directorio de trabajo, y lo consultas con pwd:

$ pwd
/home/alumno/practicas

En Windows cambian el separador y la raíz —C:\Users\alumno\practicas\datos.txt—, pero la idea es idéntica: lo que empieza en la raíz es absoluto, lo demás se mide desde donde estás.

El programa no lee desde donde está: lee desde donde lo lanzas

Esta es la parte que cuesta, y la que no cabía en ningún short.

Escribe este programa en practicas/entrega/Edad.java. Necesitas Java 11 o superior: las tres cosas que usa —Path.of, Files.readString y lanzar un .java sin compilarlo antes— llegaron en esa versión. Compruébalo con java --version antes de seguir.

import java.nio.file.Files;
import java.nio.file.Path;

public class Edad {
    public static void main(String[] args) throws Exception {
        String texto = Files.readString(Path.of("datos.txt")).trim();
        int edad = Integer.parseInt(texto);
        System.out.println("edad = " + edad);
        System.out.println("dentro de 3 años = " + (edad + 3));
        System.out.println("la mitad = " + (edad / 2));
    }
}

Ahora lánzalo desde practicas, que es donde está datos.txt:

$ pwd
/home/alumno/practicas
$ java entrega/Edad.java
edad = 17
dentro de 3 años = 20
la mitad = 8

Funciona. Y fíjate en la última línea antes de seguir: la mitad de 17 sale 8, no 8,5. Es la división entera otra vez, ahora en un programa que has escrito tú.

Y ahora entra en entrega y lánzalo desde ahí, sin cambiar una letra del código:

$ cd entrega
$ java Edad.java
Exception in thread "main" java.nio.file.NoSuchFileException: datos.txt

El archivo no se ha movido. El programa no ha cambiado. Lo que ha cambiado es desde dónde lo has lanzado, y Path.of("datos.txt") es una ruta relativa: significa «datos.txt en el directorio de trabajo», no «datos.txt al lado del programa».

Es exactamente el mismo fallo que cuando cat datos.txt funciona en una carpeta y no en otra. Solo que ahora está dentro de tu código, y por eso parece otro problema.

En una tabla: la fila y su clave primaria

El tercer sitio. Una tabla no es una hoja de cálculo, y la diferencia cabe en una columna.

Imagina la tabla sin esa columna:

nombreedad
Marta Ruiz17
Marta Ruiz19

Ahora borra a Marta Ruiz. ¿Cuál de las dos? Esta consulta se lleva las dos por delante, y no es un fallo del motor: es que la tabla no tiene con qué distinguirlas.

DELETE FROM alumnos WHERE nombre = 'Marta Ruiz';

La columna que falta es la clave primaria: una columna cuyo valor no se repite jamás. Se declara al crear la tabla:

CREATE TABLE alumnos (
  id     INT PRIMARY KEY,
  nombre VARCHAR(60),
  edad   INT
);

Fíjate en edad INT: es el mismo tipo que declaraste en Java. Una columna tiene nombre y tipo, igual que una variable. No es una casualidad del lenguaje: es la misma idea en otra capa.

A partir de esa declaración, PRIMARY KEY no es un adorno. Es una promesa que el motor se compromete a hacer cumplir en cada inserción:

INSERT INTO alumnos VALUES (1, 'Otra persona', 20);
-- ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

Ese mensaje es el de MariaDB, que es lo que trae XAMPP. Si usas MySQL 8 verás lo mismo con la tabla delante, for key 'alumnos.PRIMARY'. Cambia el nombre de la clave; el número de error y el motivo son idénticos.

Única, obligatoria y estable

Son las tres condiciones para elegir una clave primaria, y la tentación del primer día las falla todas:

  • Única: no se repite nunca. El nombre se repite — hay dos Marta Ruiz.
  • Obligatoria: no puede quedar vacía. El email se puede no tener.
  • Estable: no cambia con el tiempo. El email cambia.

Por eso se usa un id que no significa nada. Su única virtud es no significar nada: así nunca hay motivo para cambiarlo.

El mismo error con tres caras

Aquí está el hilo. Los tres sitios tienen su forma de nombrar un dato, y los tres fallan igual: crees que estás señalando algo y estás señalando otra cosa, o nada.

Dónde viveCómo se llamaCuando lo señalas mal
En memoriaEl identificadorvariable edad might not have been initialized
En discoLa rutaNoSuchFileException: datos.txt
En la tablaLa clave primariaDuplicate entry '1' for key 'PRIMARY'

Los tres mensajes dicen lo mismo con palabras distintas: el nombre que me has dado no apunta a un dato válido. En el primero el hueco existe pero está vacío; en el segundo el nombre depende de dónde estás y te has movido; en el tercero el nombre ya estaba cogido.

Cuando te salga uno de los tres, la pregunta no es «¿qué he escrito mal?». Es «¿a qué apunta de verdad el nombre que he escrito?». Casi siempre la respuesta está ahí.

Ejercicio: el mismo dato en los tres sitios

Diez minutos, encadenado. Al final tendrás el número 17 viviendo en los tres sitios a la vez.

Lo que necesitas: una terminal, Java 11 o superior (java --version) y un MySQL o MariaDB a mano — el de XAMPP vale.

1. El archivo. Abre la terminal y prepara el árbol:

mkdir -p practicas/entrega
cd practicas
echo 17 > datos.txt
pwd

Esa última línea te dice dónde estás. Apúntala mentalmente: es el origen de todo lo que viene.

2. La variable. Crea entrega/Edad.java con el programa de más arriba y lánzalo desde practicas:

java entrega/Edad.java

Deberías ver edad = 17, dentro de 3 años = 20 y la mitad = 8. Si la mitad te sorprende, vuelve a la sección del tipo.

3. Rompe la ruta a propósito. Entra en entrega y lanza el programa otra vez:

cd entrega
java Edad.java

Ahí está tu NoSuchFileException. Ahora arréglalo sin mover el archivo, de dos formas: cambia "datos.txt" por "../datos.txt" en el código, y después pruébalo con la ruta absoluta entera. Las dos funcionan, y por motivos distintos.

4. La tabla. Crea la tabla y guarda ahí el mismo dato:

CREATE TABLE alumnos (
  id     INT PRIMARY KEY,
  nombre VARCHAR(60),
  edad   INT
);
INSERT INTO alumnos VALUES (1, 'Marta Ruiz', 17);
INSERT INTO alumnos VALUES (2, 'Iván Soto', 19);
SELECT * FROM alumnos;

5. Rompe la clave a propósito. Intenta insertar otra fila con id = 1 y lee el error. Ese error es la clave primaria trabajando.

Si has llegado hasta aquí, has visto el mismo 17 en memoria, en disco y en una tabla, y has provocado los tres errores de nombrado a propósito. Eso es más de lo que se ve en las dos primeras semanas de clase.

Por dónde seguir

Cada una de las tres ideas tiene su vídeo de un minuto, por si prefieres verlo antes de leerlo:

  • Variable, tipo y valor — los tres elementos de una línea de código, y por qué 7 / 2 da 3.
  • SQL: tabla, fila y clave primaria — qué convierte un montón de filas en datos que puedes señalar.
  • Terminal: rutas absolutas y relativas — por qué el mismo comando falla en otra carpeta.

Y si algo de esto se te está atragantando, en SASE Formación damos clases de informática y programación, presenciales y online. La primera clase de prueba es gratuita, y en informática las clases son individuales. Escríbenos y nos cuentas por dónde vas: saseformacion.es, o por WhatsApp al 656 251 438.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *