Saltar al contenido
vistas.sql · devschool

Vistas en SQL

Lección 18 de 22 · 11 min de lectura · Actualizado el

En esta lección
  1. El problema: consultas que repites una y otra vez
  2. Crear una vista: CREATE VIEW
  3. Una vista no guarda datos
  4. Para qué sirven las vistas
  5. Cambiar y borrar vistas
  6. Vistas actualizables
  7. Vistas materializadas
  8. Errores frecuentes
  9. Resumen

Una vista es una consulta a la que le pones nombre y guardas en la base de datos. A partir de ese momento puedes usarla como si fuera una tabla más: hacerle SELECT, filtrarla con WHERE o unirla con otras tablas. En esta lección aprenderás a crear vistas, a cambiarlas y borrarlas, y sobre todo a saber cuándo te conviene usarlas.

El problema: consultas que repites una y otra vez

Imagina que en la tienda del curso necesitas a menudo ver los pedidos con el nombre del cliente. Cada vez tienes que escribir el mismo JOIN:

SELECT p.id AS pedido_id, c.nombre AS cliente, c.ciudad, p.fecha, p.importe
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id;

Si esa consulta aparece en diez sitios de tu aplicación y un día cambia algo (por ejemplo, quieres añadir la edad), tendrás que tocar los diez. Además, un compañero que no conozca bien las tablas puede equivocarse al escribir el JOIN.

Una vista resuelve las dos cosas: escribes la consulta una vez, le das un nombre y todo el mundo usa ese nombre.

Crear una vista: CREATE VIEW

La sintaxis es CREATE VIEW nombre AS seguida de cualquier SELECT:

CREATE VIEW pedidos_con_cliente AS
SELECT p.id AS pedido_id,
       c.nombre AS cliente,
       c.ciudad,
       p.fecha,
       p.importe
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id;

Al ejecutarlo no se muestra ningún resultado: la base de datos solo guarda la definición. Ahora puedes consultarla igual que una tabla:

SELECT * FROM pedidos_con_cliente;
pedido_idclienteciudadfechaimporte
1Ana GarcíaSantander2026-09-0145.00
2Marta RuizSantander2026-09-03120.50
3Ana GarcíaSantander2026-09-1012.99
4Luis PérezBilbao2026-09-1260.00
5Eva MartínMadrid2026-09-1533.25

Los nombres de las columnas de la vista son los alias que pusiste en el SELECT (pedido_id, cliente). Por eso conviene poner alias claros: son la “cara” de la vista.

Usarla como una tabla

Todo lo que ya sabes de SELECT funciona sobre una vista:

SELECT cliente, importe
FROM pedidos_con_cliente
WHERE importe > 40
ORDER BY importe DESC;
clienteimporte
Marta Ruiz120.50
Luis Pérez60.00
Ana García45.00

Fíjate en que la consulta ya no tiene ningún JOIN. Quien la escribe no necesita saber que los datos vienen de dos tablas.

Una vista no guarda datos

Esto es lo más importante que debes entender: una vista no es una copia de los datos. Es solo una consulta con nombre. Cada vez que la usas, la base de datos ejecuta el SELECT que hay dentro sobre las tablas reales.

Lo vas a ver con un ejemplo. Crea una vista con el número de pedidos y el total facturado por ciudad (usa GROUP BY):

CREATE VIEW total_por_ciudad AS
SELECT c.ciudad,
       COUNT(p.id) AS num_pedidos,
       SUM(p.importe) AS total
FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id
GROUP BY c.ciudad;

SELECT * FROM total_por_ciudad ORDER BY total DESC;
ciudadnum_pedidostotal
Santander3178.49
Bilbao160.00
Madrid133.25

Ahora Pablo, de Madrid, hace su primer pedido:

INSERT INTO pedidos (id, cliente_id, fecha, importe)
VALUES (6, 4, '2026-09-20', 18.00);

SELECT * FROM total_por_ciudad ORDER BY total DESC;
ciudadnum_pedidostotal
Santander3178.49
Bilbao160.00
Madrid251.25

No has tenido que “actualizar” la vista: siempre muestra los datos al día, porque los calcula en el momento. La parte negativa es que una vista con una consulta pesada tarda lo mismo que esa consulta; no la hace más rápida.

Consejo: puedes unir una vista con tablas u otras vistas, filtrarla o agruparla. Para la base de datos es una tabla más a la hora de escribir consultas.

Para qué sirven las vistas

1. Simplificar consultas

Es el uso que has visto: esconder JOIN, cálculos y agrupaciones detrás de un nombre sencillo. El código de tu aplicación queda más corto y, si la lógica cambia, la cambias en un solo sitio.

2. Seguridad: enseñar solo una parte

Supón que el equipo de marketing necesita la lista de clientes, pero no debe ver su edad. Puedes crear una vista sin esa columna:

CREATE VIEW clientes_publicos AS
SELECT id, nombre, ciudad
FROM clientes;
idnombreciudad
1Ana GarcíaSantander
2Luis PérezBilbao
3Marta RuizSantander
4Pablo DíazMadrid
5Eva MartínMadrid

Después das permiso a esos usuarios sobre la vista, pero no sobre la tabla clientes. Lo verás en la lección de usuarios y permisos.

3. Informes

Las vistas con totales, medias y recuentos (como total_por_ciudad) son la base de muchos paneles e informes. Las herramientas de informes se conectan a la vista y no necesitan conocer la estructura interna.

4. Aislar la aplicación de cambios en las tablas

Si reorganizas las tablas (por ejemplo, divides una en dos), puedes crear una vista con el nombre y las columnas antiguas. El código viejo sigue funcionando mientras lo vas adaptando.

Cambiar y borrar vistas

Para modificar una vista existente, MySQL y PostgreSQL tienen CREATE OR REPLACE VIEW. Si la vista no existe, la crea; si existe, la sustituye:

CREATE OR REPLACE VIEW clientes_publicos AS
SELECT id, nombre, ciudad, edad >= 18 AS mayor_de_edad
FROM clientes;

Para borrarla se usa DROP VIEW. Con IF EXISTS no da error si no existe:

DROP VIEW IF EXISTS total_por_ciudad;

Borrar una vista no borra ningún dato: solo desaparece la consulta guardada. Las tablas clientes y pedidos siguen intactas.

Nota: SQLite no tiene CREATE OR REPLACE VIEW. Tienes que hacer DROP VIEW IF EXISTS y luego CREATE VIEW otra vez. En PostgreSQL, CREATE OR REPLACE solo permite añadir columnas al final; si quieres quitar o renombrar columnas, también tienes que borrarla y crearla de nuevo. MySQL tiene además ALTER VIEW nombre AS SELECT ..., que hace lo mismo que CREATE OR REPLACE.

Para ver qué vistas tienes y cómo están definidas, en MySQL:

SHOW FULL TABLES WHERE Table_type = 'VIEW';
SHOW CREATE VIEW pedidos_con_cliente;

Vistas actualizables

¿Se puede hacer INSERT, UPDATE o DELETE sobre una vista? En MySQL y PostgreSQL, sí, si la vista es sencilla. Por ejemplo:

CREATE VIEW clientes_santander AS
SELECT id, nombre, ciudad, edad
FROM clientes
WHERE ciudad = 'Santander';

UPDATE clientes_santander SET edad = 35 WHERE id = 1;

El cambio se aplica a la tabla clientes, porque la vista no tiene datos propios. Cada fila de la vista corresponde exactamente a una fila de la tabla, así que la base de datos sabe qué fila tocar.

Una vista no es actualizable cuando esa correspondencia se pierde. Las causas más habituales son:

La vista contiene…Por qué no se puede actualizar
GROUP BY o funciones como SUM, COUNTUna fila de la vista resume muchas filas de la tabla
DISTINCTUna fila puede venir de varias filas iguales
UNIONLos datos vienen de varias consultas
Columnas calculadas (importe * 1.21)No puedes guardar un valor en un cálculo
Subconsultas en el SELECTLa base de datos no sabe qué tabla modificar

Por ejemplo, total_por_ciudad nunca será actualizable: ¿qué significaría cambiar el total de Madrid a 100?

Con vistas que tienen JOIN, MySQL permite a veces hacer UPDATE si solo tocas columnas de una de las tablas, pero no DELETE. Las reglas son complicadas y cambian entre sistemas. En la práctica, usa las vistas para leer y modifica los datos sobre las tablas.

Nota: en SQLite las vistas son siempre de solo lectura. Si intentas el UPDATE anterior obtienes el error cannot modify clientes_santander because it is a view.

WITH CHECK OPTION

Con la vista clientes_santander, nada te impide hacer esto en MySQL:

INSERT INTO clientes_santander (id, nombre, ciudad, edad)
VALUES (6, 'Sara López', 'Madrid', 31);

La fila se guarda en clientes, pero no aparece en la vista, porque no es de Santander. Es raro y confuso. Para impedirlo, añade WITH CHECK OPTION al final de la definición:

CREATE OR REPLACE VIEW clientes_santander AS
SELECT id, nombre, ciudad, edad
FROM clientes
WHERE ciudad = 'Santander'
WITH CHECK OPTION;

Ahora cualquier INSERT o UPDATE a través de la vista que deje una fila fuera del WHERE da error. Solo puedes añadir o cambiar clientes de Santander.

Vistas materializadas

A veces sí interesa guardar el resultado, por ejemplo en un informe que tarda un minuto en calcularse y que se consulta muchas veces al día. Para eso existen las vistas materializadas: guardan una copia de los datos en disco.

Nota: PostgreSQL las tiene con CREATE MATERIALIZED VIEW informe AS SELECT .... Como son una copia, no se actualizan solas: tienes que ejecutar REFRESH MATERIALIZED VIEW informe; cuando quieras recalcularlas (por ejemplo, cada noche). MySQL y SQLite no tienen vistas materializadas; se suelen imitar con una tabla normal que se rellena periódicamente.

Errores frecuentes

  • Pensar que la vista es una copia de los datos. Una vista normal siempre lee las tablas en el momento. Si la consulta es lenta, la vista también lo será.
  • Columnas sin alias. Si pones SUM(p.importe) sin AS total, la columna de la vista se llamará algo como SUM(p.importe), incómodo de usar. Ponle siempre un alias.
  • Poner ORDER BY dentro de la vista. Algunos sistemas lo ignoran y otros lo permiten, pero no garantiza el orden cuando la usas en otra consulta. Ordena en el SELECT que usa la vista.
  • Borrar o renombrar una tabla que usa una vista. La vista se queda “rota” y da error al consultarla. Antes de hacer ALTER TABLE o DROP, revisa qué vistas dependen de esa tabla.
  • Vistas encima de vistas encima de vistas. Funciona, pero cuando algo va lento o falla es muy difícil encontrar el porqué. Mantén pocas capas.
  • Nombres que se confunden con tablas. Muchos equipos usan un prefijo como v_ (v_pedidos_con_cliente) para saber a simple vista que es una vista.

Resumen

InstrucciónPara qué sirve
CREATE VIEW v AS SELECT ...Guarda una consulta con nombre
SELECT * FROM vUsa la vista como una tabla
CREATE OR REPLACE VIEW v AS ...Crea o sustituye la vista (MySQL y PostgreSQL)
ALTER VIEW v AS ...Cambia la vista (MySQL)
DROP VIEW IF EXISTS vBorra la vista, no los datos
WITH CHECK OPTIONImpide insertar o cambiar filas que la vista no mostraría
CREATE MATERIALIZED VIEWGuarda una copia del resultado (PostgreSQL)
  • Una vista es una consulta guardada, no una copia de los datos.
  • Sirve para simplificar, proteger columnas o filas y preparar informes.
  • Las vistas sencillas de una sola tabla se pueden actualizar en MySQL y PostgreSQL; las que tienen GROUP BY, DISTINCT o cálculos, no.
  • En la siguiente lección verás cómo hacer que las consultas vayan más rápido con índices.

Pon a prueba lo que has aprendido

[SQL] Con los datos del curso (3 pedidos de más de 40 €), ¿qué devuelve la última consulta?
CREATE VIEW caros AS
SELECT id, importe FROM pedidos WHERE importe > 40;

INSERT INTO pedidos VALUES (6, 2, '2026-09-20', 90.00);

SELECT COUNT(*) FROM caros;

[SQL] ¿Cuál de estas vistas NO se puede actualizar con UPDATE en MySQL?

[SQL] ¿Qué ocurre al ejecutar DROP VIEW pedidos_con_cliente?

[SQL] Tienes una vista con WHERE ciudad = 'Santander' creada con WITH CHECK OPTION. ¿Qué pasa si insertas a través de ella un cliente de Madrid?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.