SQL en Vivo: PostgreSQL Real en tu Navegador
Esto no es un simulador: es PostgreSQL de verdad, compilado a WebAssembly, corriendo enteramente en tu navegador. Cada bloque de esta guía es editable y ejecutable — vas a crear el esquema de la guía de DDL con tus propias manos y ver los errores reales que devuelve el motor cuando algo sale mal.
Bienvenido
Este taller es la práctica de laboratorio de DDL y Restricciones en PostgreSQL. No vuelve a explicar la teoría desde cero — asume que ya la viste — y en cambio te da un PostgreSQL real para ejecutar cada sentencia y comprobar con tus propios ojos qué pasa.
Si todavía no viste la teoría, repasa primero DDL y Restricciones en PostgreSQL antes de continuar. Este taller reconstruye exactamente el mismo esquema (CLIENTE, PRODUCTO, PEDIDO, DETALLE_PEDIDO) que esa guía.
Usa PGlite, una compilación del propio motor de PostgreSQL a WebAssembly (WASM). No es un motor distinto que imita la sintaxis de Postgres —como pasa con otras herramientas educativas basadas en SQLite— es el mismo PostgreSQL, corriendo dentro de tu navegador, sin instalar nada ni depender de ningún servidor.
La base de datos que vas a construir existe solo mientras esta página siga abierta. Si recargas la página, cierras la pestaña, o navegas a otra guía, se pierde todo y hay que volver a ejecutar los bloques desde el principio. Si te equivocás y querés empezar de cero sin recargar, usa el botón "Reiniciar base de datos" de abajo.
✍️ Lo escribís vos
Cada bloque parte vacío. El enunciado te dice qué tenés que lograr — el código SQL lo escribís de cero.
🩻 Errores reales
Los mensajes de error que vas a ver son exactamente los que da PostgreSQL en producción.
🧩 Progresivo
Todos los ejercicios comparten la misma base de datos: lo que crees en el ejercicio 1 lo vas a usar en el 4.
Zona de pruebas libres
Este bloque queda disponible durante toda la guía. Usalo en cualquier momento para probar una idea propia, revisar el estado de una tabla con SELECT * FROM tabla;, o experimentar con algo que se te ocurra a mitad de un ejercicio — sin desordenar los bloques guiados.
1. Tablas base: CLIENTE y PRODUCTO
Igual que en la guía teórica, empezamos por las dos tablas que no dependen de ninguna otra. Escribí vos mismo las sentencias CREATE TABLE y presioná ▶ Ejecutar para crearlas de verdad.
- cliente(
cliente_idclave primaria autoincremental,cliente_nombre VARCHAR(120)obligatorio) - producto(
producto_idclave primaria autoincremental,producto_nombre VARCHAR(120)obligatorio,precio NUMERIC(10,2)obligatorio con unCHECKque exija que sea mayor a 0,activo BOOLEANobligatorio conDEFAULT true)
Presiona ▶ Ejecutar una segunda vez, sin cambiar nada. PostgreSQL te va a devolver un error real de tipo relation "cliente" already exists. Corrígelo agregando IF NOT EXISTS después de CREATE TABLE en ambas tablas, y ejecuta de nuevo para confirmar que ya no falla.
2. Relaciones y claves foráneas: PEDIDO y DETALLE_PEDIDO
Ahora las tablas que sí dependen de otras. Escribí las sentencias CREATE TABLE siguiendo el enunciado.
- pedido(
pedido_idclave primaria autoincremental,fecha DATEobligatoria conDEFAULT CURRENT_DATE,cliente_idobligatorio como clave foránea haciacliente) - detalle_pedido(
pedido_idclave foránea haciapedidoconON DELETE CASCADE,producto_idclave foránea haciaproductoconON DELETE RESTRICT,cantidadobligatoria con unCHECKmayor a 0, y clave primaria compuesta porpedido_idyproducto_id)
Bajá a la zona de pruebas libres y escribí a mano CREATE TABLE otra_tabla (id INTEGER REFERENCES tabla_inexistente(id));. Vas a ver el error real: relation "tabla_inexistente" does not exist — exactamente lo que predice la guía teórica sobre el orden de creación.
3. Restricciones en acción
Primero cargamos datos válidos. Después, cada bloque siguiente te pide una sola sentencia que va a fallar a propósito — así podés ver, aislado, el mensaje de error exacto que corresponde a cada tipo de restricción.
La guía teórica de DDL no cubre estas tres instrucciones — son DML (Data Manipulation Language), tema de la próxima guía. Para este taller te alcanza con la forma general:
INSERT INTO tabla (columna1, columna2) VALUES (valor1, valor2);
UPDATE tabla SET columna = valor WHERE condición;
DELETE FROM tabla WHERE condición;
De acá en adelante, cuando el enunciado diga "inserta", "actualiza" o "borra", adaptá esta forma general con los datos que te pide cada ejercicio.
Inserta en cliente dos filas: 'Ana Gutiérrez' y 'Marco Flores'. Inserta en producto dos filas: 'Teclado mecánico' a 250.00 y 'Mouse inalámbrico' a 90.00.
3.1 — Viola un CHECK: intenta insertar en producto un 'Cable USB' con precio -5.00.
3.2 — Viola un NOT NULL: intenta insertar un cliente con cliente_nombre en NULL.
3.3 — Viola una clave foránea: intenta insertar un pedido con un cliente_id que no existe (por ejemplo, 999).
Cada tipo de restricción tiene un mensaje de error distinto y reconocible: violates check constraint, violates not-null constraint y violates foreign key constraint. Aprender a reconocer estos tres patrones te va a ahorrar mucho tiempo depurando scripts reales.
4. CASCADE vs. RESTRICT en acción
Primero armamos un pedido completo con su detalle. Después probamos qué pasa al intentar borrar cada extremo de la relación.
Inserta en pedido una fila para cliente_id = 1. Inserta en detalle_pedido dos filas para ese pedido: producto_id = 1 con cantidad = 3, y producto_id = 2 con cantidad = 1. Confirma con un SELECT * FROM detalle_pedido; al final.
4.1 — Intenta borrar un producto referenciado (declarado con ON DELETE RESTRICT): borra el producto con producto_id = 1.
4.2 — Borra el pedido (declarado con ON DELETE CASCADE) con pedido_id = 1, y comprueba con un SELECT qué pasó con su detalle:
RESTRICT bloqueó el borrado de producto mientras siguiera referenciado. CASCADE dejó borrar pedido y arrastró automáticamente sus filas de detalle_pedido — el SELECT final debería devolver 0 filas.
5. ALTER TABLE en vivo
Una tabla ya creada no es definitiva. Agregamos una columna nueva a cliente y comprobamos qué valor toman las filas que ya existían.
Agrega a cliente una columna email VARCHAR(150). Confirma con un SELECT * FROM cliente; al final.
Agrega una restricción UNIQUE llamada cliente_email_unico sobre la columna email. Luego actualiza el cliente cliente_id = 1 para que su email sea '[email protected]'.
5.3 — Intenta repetir el mismo correo en otro cliente: actualiza cliente_id = 2 con el mismo email '[email protected]'.
6. DROP TABLE y sus dos CASCADE
Hay dos cosas distintas en esta guía que se llaman "CASCADE", y es fácil confundirlas. Vamos a verlas una junto a la otra.
6.1 — Intenta borrar producto sin CASCADE: ejecuta un DROP TABLE simple sobre producto.
6.2 — Ahora con CASCADE: vuelve a borrar producto, esta vez con CASCADE, y comprueba con un SELECT qué le pasó a detalle_pedido.
ON DELETE CASCADE (sección 4) es una regla que vive dentro de una fila: borra automáticamente las filas hijas cuando se borra la fila padre. DROP TABLE ... CASCADE (esta sección) es una operación de estructura: borra la restricción de clave foránea que dependía de la tabla eliminada, pero no borra la tabla ni las filas de detalle_pedido — el SELECT final debería seguir mostrando datos, solo que detalle_pedido ya no tiene ninguna clave foránea apuntando a producto.
El esquema quedó parcialmente desarmado a propósito. Usa el botón 🔄 Reiniciar base de datos al principio de la guía para empezar el reto siguiente con una base de datos completamente vacía.
Reto final: diseña tu propio esquema
Con la base de datos reiniciada, diseña y crea desde cero el esquema de una biblioteca, aplicando todo lo practicado en este taller.
- autor(autor_id, autor_nombre)
- libro(libro_id, titulo, autor_id → referencia a autor, anio_publicacion con un
CHECKrazonable) - socio(socio_id, socio_nombre, email con
UNIQUE) - prestamo(libro_id, socio_id — clave primaria compuesta, fecha_prestamo con
DEFAULT CURRENT_DATE, fecha_devolucion que pueda quedar sin definir) - Decide vos la acción referencial (
CASCADE,RESTRICToSET NULL) de cada clave foránea de prestamo, y justifica tu elección con un comentario--en el propio bloque.
Una vez creadas las tablas, insertá un par de filas de cada una y confirmalas con SELECT * FROM tabla; — todavía no hace falta que domines SELECT a fondo, eso es tema de la próxima guía.
Repaso
Cuatro preguntas cortas sobre lo que acabas de observar en vivo. Tu progreso se guarda automáticamente en este navegador.
Al insertar un producto con precio -5.00, PostgreSQL respondió con un error que menciona "violates check constraint". ¿Qué restricción provocó ese error?
En el ejercicio 4, borrar el producto referenciado por detalle_pedido funcionó sin problema porque PostgreSQL siempre permite borrar cualquier fila.
Después de DROP TABLE producto CASCADE, ¿qué pasó con la tabla detalle_pedido?
¿Es una regla de fila (ON DELETE ...) o una operación de estructura (DROP TABLE ...)?
Cheat Sheet del taller
| Situación | Mensaje real de PostgreSQL |
|---|---|
| Crear una tabla que ya existe | relation "..." already exists |
| Referenciar una tabla que aún no existe | relation "..." does not exist |
| Violar un CHECK | new row for relation "..." violates check constraint "..." |
| Violar NOT NULL | null value in column "..." violates not-null constraint |
| Violar UNIQUE o PRIMARY KEY duplicada | duplicate key value violates unique constraint "..." |
| Insertar una FK que no existe en la tabla padre | violates foreign key constraint "...", detalle "Key (...) is not present in table "..."." |
| Borrar una fila padre protegida por RESTRICT | update or delete on table "..." violates foreign key constraint "..." on table "..." |
| DROP TABLE sin CASCADE, con dependientes | cannot drop table "..." because other objects depend on it |
¿Sabías que...?
🐘 PGlite es Postgres de verdad
A diferencia de motores educativos basados en SQLite (como sql.js), PGlite compila el código fuente real de PostgreSQL a WebAssembly: los mismos mensajes de error y el mismo comportamiento que en un servidor de producción.
📦 Menos de 4 MB
El motor completo de PostgreSQL comprimido para WebAssembly pesa alrededor de 3-4 MB — comparable a una foto de celular, y corre enteramente sin conexión una vez cargado.
🌳 PostgreSQL es más viejo que la Web
El proyecto POSTGRES nació en Berkeley en 1986, ocho años antes de que existiera el primer navegador gráfico — y hoy ese mismo motor corre dentro de uno.