---
title: "Vistas en MySQL: qué son, cómo se crean y para qué sirven"
excerpt: "Una vista en MySQL es una consulta SELECT guardada que usas como si fuera una tabla. Aquí ves cómo crearla con CREATE VIEW, cuándo acepta INSERT y UPDATE, cómo sirve para mostrarle a cada usuario solo ciertos datos y qué efecto tiene en el rendimiento."
date: "2026-10-09T15:00:00.000Z"
category: "Bases de Datos"
tech_article: true
author:
  name: "angel cruz"
  picture: "/images/me/angel-cruz.png"
ogImage:
  url: "/images/open-graph/og-image.png"
seo_title: "Vistas en MySQL (CREATE VIEW): qué son, cómo crearlas y beneficios"
seo_description: "Qué es una vista en MySQL, cómo crear una view con CREATE VIEW, ALTER VIEW y DROP VIEW, vistas actualizables, WITH CHECK OPTION, seguridad y rendimiento. Con ejemplos."
---

**Una vista en MySQL (una *view*) es una consulta `SELECT` guardada con nombre dentro de la base de datos, que después consultas como si fuera una tabla.** La vista no guarda filas: cada vez que haces `SELECT * FROM mi_vista`, MySQL ejecuta la consulta guardada contra las tablas y te devuelve los datos que hay en ese momento.

Sirve para tres cosas concretas: esconder un `JOIN` largo detrás de un nombre corto, dejar que un usuario lea algunas columnas de una tabla sin darle acceso a la tabla entera, y cambiar el esquema sin romper las consultas que ya usa la aplicación. Todo lo que sigue corresponde a MySQL 8.4.

## Qué es una vista en MySQL

Una vista se comporta como una tabla virtual. Tiene nombre y columnas, aparece en la lista de tablas de la base de datos y la consultas con `SELECT` igual que a una tabla, pero sus filas salen de una consulta.

El ejemplo más corto es el del propio manual:

```sql
CREATE TABLE t (qty INT, price INT);
INSERT INTO t VALUES (3, 50);

CREATE VIEW v AS SELECT qty, price, qty * price AS value FROM t;

SELECT * FROM v;
```

```text
+------+-------+-------+
| qty  | price | value |
+------+-------+-------+
|    3 |    50 |   150 |
+------+-------+-------+
```

La tabla `t` no tiene una columna `value`: ese valor se calcula cada vez que alguien consulta la vista. Si mañana cambias `price` en `t`, la próxima consulta a `v` ya devuelve el resultado nuevo.

Dos cosas que conviene saber desde el principio:

- Tablas y vistas comparten el mismo espacio de nombres dentro de una base de datos. No puedes tener una tabla `clientes` y una vista `clientes` en el mismo esquema.
- No se puede crear un índice sobre una vista. Según cómo la procese MySQL, la consulta puede usar los índices de las tablas base o no (lo vemos en la sección de rendimiento).

## Cómo crear una vista en MySQL con CREATE VIEW

La sintaxis completa de `CREATE VIEW` es esta:

```sql
CREATE
    [OR REPLACE]
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = user]
    [SQL SECURITY { DEFINER | INVOKER }]
    VIEW view_name [(column_list)]
    AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]
```

Casi siempre basta con `CREATE VIEW nombre AS SELECT ...`. Para los ejemplos uso una tienda con dos tablas, clientes y pedidos:

```sql
CREATE TABLE clientes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL,
    pais CHAR(2) NOT NULL,
    activo TINYINT(1) NOT NULL DEFAULT 1
);

CREATE TABLE pedidos (
    id INT PRIMARY KEY AUTO_INCREMENT,
    cliente_id INT NOT NULL,
    total DECIMAL(10, 2) NOT NULL,
    estado VARCHAR(20) NOT NULL,
    creado_en DATETIME NOT NULL,
    FOREIGN KEY (cliente_id) REFERENCES clientes (id)
);
```

Supón que la aplicación pide en varios lugares "los pedidos pagados, con el nombre y el país del cliente". En vez de repetir el `JOIN` en cada consulta, lo guardas una vez como vista:

```sql
CREATE VIEW pedidos_pagados AS
SELECT
    p.id,
    p.total,
    p.creado_en,
    c.nombre AS cliente,
    c.pais
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
WHERE p.estado = 'pagado';
```

Desde ese momento la consultas como a cualquier tabla, y puedes agregarle tu propio `WHERE`, `ORDER BY` o `JOIN`:

```sql
SELECT cliente, total
FROM pedidos_pagados
WHERE pais = 'MX'
ORDER BY creado_en DESC;
```

### Nombrar las columnas de la vista

Por defecto, las columnas de la vista se llaman igual que las del `SELECT`. Para usar otros nombres, ponlos entre paréntesis después del nombre de la vista. Tiene que haber exactamente un nombre por cada columna que devuelve el `SELECT`, y ninguno puede repetirse:

```sql
CREATE VIEW ventas_por_pais (pais, pedidos, facturado) AS
SELECT c.pais, COUNT(*), SUM(p.total)
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
WHERE p.estado = 'pagado'
GROUP BY c.pais;
```

Los nombres de columna de una vista no pueden pasar de 64 caracteres, que es el máximo para un nombre de columna. En un `SELECT` normal un alias puede llegar a 256, pero dentro de una vista se aplica el límite de 64.

### Qué no puede llevar el SELECT de una vista

El manual enumera estas restricciones:

- No puede usar variables de sistema ni variables de usuario (`@algo`).
- Dentro de un procedimiento almacenado, no puede usar sus parámetros ni sus variables locales.
- No puede usar parámetros de una sentencia preparada.
- No puede leer de una tabla `TEMPORARY`, y tampoco se pueden crear vistas temporales.
- No se le pueden asociar triggers.
- Todas las tablas y vistas que menciona tienen que existir cuando la creas.
- Puede mencionar como máximo 61 tablas.

Fuera de eso, el `SELECT` puede llevar `JOIN`, `UNION`, subconsultas, funciones de agregación y `GROUP BY`.

## La definición de una vista queda fija al crearla

Al crear una vista, MySQL guarda la lista de columnas tal como es en ese momento, y los cambios posteriores en las tablas no la actualizan. La documentación dice que la definición queda "congelada". Donde más se nota es con `SELECT *`: MySQL expande el asterisco al crear la vista y guarda las columnas que había entonces.

Eso tiene tres consecuencias:

- Si después agregas una columna a la tabla, la vista no la incluye.
- Si borras de la tabla una columna que la vista usaba, consultar la vista da error.
- Si borras o modificas con `DROP TABLE` o `ALTER TABLE` una tabla que la vista usa, MySQL no te avisa. El error aparece después, la primera vez que alguien consulta la vista.

Para encontrar vistas que quedaron rotas después de un cambio de esquema, usa `CHECK TABLE`:

```sql
CHECK TABLE pedidos_pagados;
```

Si agregaste columnas a la tabla y quieres que la vista las muestre, tienes que volver a crearla con `CREATE OR REPLACE VIEW`.

## ORDER BY dentro de una vista

La definición de una vista puede llevar `ORDER BY`, pero MySQL lo ignora si la consulta que lee la vista tiene su propio `ORDER BY`. Con `LIMIT` y otras cláusulas el manual no promete nada: se combinan con las de la consulta exterior y el resultado queda indefinido. Lo más seguro es poner el orden y la paginación en la consulta que lee la vista, no en la vista.

## Modificar, listar y borrar vistas en MySQL

### Cambiar una vista: CREATE OR REPLACE VIEW y ALTER VIEW

Las dos sentencias reemplazan la definición de una vista. La diferencia es que `CREATE OR REPLACE VIEW` crea la vista si no existe, y `ALTER VIEW` falla:

```sql
-- Crea la vista si no existe, la reemplaza si existe
CREATE OR REPLACE VIEW pedidos_pagados AS
SELECT p.id, p.total, p.creado_en, c.nombre AS cliente, c.pais, c.email
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
WHERE p.estado = 'pagado';

-- Cambia una vista que ya existe (falla si no existe)
ALTER VIEW pedidos_pagados AS
SELECT p.id, p.total, p.creado_en, c.nombre AS cliente, c.pais
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
WHERE p.estado = 'pagado';
```

`CREATE OR REPLACE VIEW` requiere los privilegios `CREATE VIEW` y `DROP` sobre la vista. `ALTER VIEW` requiere esos mismos dos y, además, solo puede ejecutarlo la cuenta que creó la vista o una cuenta con `SET_ANY_DEFINER` o `ALLOW_NONEXISTENT_DEFINER`.

### Ver la definición de una vista

```sql
SHOW CREATE VIEW pedidos_pagados;
```

Para esto necesitas el privilegio `SHOW VIEW`, y MySQL no lo da automáticamente a quien tiene `CREATE VIEW`. Puede pasarte que crees una vista y no puedas ver su definición hasta que un administrador te conceda `SHOW VIEW`.

La definición también está en `INFORMATION_SCHEMA.VIEWS`, que tiene columnas como `VIEW_DEFINITION`, `CHECK_OPTION`, `IS_UPDATABLE`, `DEFINER` y `SECURITY_TYPE`:

```sql
SELECT TABLE_NAME, IS_UPDATABLE, SECURITY_TYPE, VIEW_DEFINITION
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'tienda';
```

`VIEW_DEFINITION` no muestra el texto tal como lo escribiste. MySQL guarda la definición normalizada y, por ejemplo, elimina los comentarios que había antes del `SELECT`.

### Listar las vistas de una base de datos

Con el modificador `FULL`, `SHOW TABLES` agrega una columna que indica `BASE TABLE` para cada tabla y `VIEW` para cada vista. Filtrando por esa columna te quedas solo con las vistas:

```sql
SHOW FULL TABLES FROM tienda WHERE Table_type = 'VIEW';
```

### Borrar una vista con DROP VIEW

```sql
DROP VIEW IF EXISTS pedidos_pagados, ventas_por_pais;
```

`DROP VIEW` borra solo la definición; los datos siguen en las tablas. Si vienes de una versión anterior, ojo con un cambio de comportamiento: en MySQL 8.4, si alguna de las vistas de la lista no existe, `DROP VIEW` da error y no borra ninguna. Hasta MySQL 8.3 también daba error, pero borraba las que sí existían. Con `IF EXISTS` el comando funciona igual en las dos versiones: borra las que existen y, por cada una que falta, deja una nota que puedes ver con `SHOW WARNINGS`. `RESTRICT` y `CASCADE` aparecen en la sintaxis, pero MySQL las ignora.

## Vistas actualizables: INSERT, UPDATE y DELETE sobre una vista

También puedes escribir a través de una vista. Si cada fila de la vista corresponde a una fila concreta de una tabla, MySQL acepta `UPDATE`, `DELETE` y, con algunas condiciones más, `INSERT`, y aplica el cambio en la tabla base.

```sql
CREATE VIEW clientes_activos AS
SELECT id, nombre, email, pais
FROM clientes
WHERE activo = 1;

UPDATE clientes_activos SET email = 'ana@ejemplo.com' WHERE id = 7;
```

Ese `UPDATE` modifica la fila 7 de `clientes`. Una vista deja de ser actualizable si tiene cualquiera de estos elementos:

- Funciones de agregación o de ventana (`SUM()`, `COUNT()`, `MAX()`...).
- `DISTINCT`, `GROUP BY` o `HAVING`.
- `UNION` o `UNION ALL`.
- Una subconsulta en la lista del `SELECT`. Si la subconsulta no es correlacionada, solo impide el `INSERT`.
- Una subconsulta en el `WHERE` que lee una tabla que también está en el `FROM`.
- Ciertos tipos de `JOIN`.
- Una vista no actualizable en el `FROM`.
- Solo valores literales, sin ninguna tabla.
- `ALGORITHM = TEMPTABLE`.

Por eso `ventas_por_pais` es de solo lectura: tiene `GROUP BY` y `SUM()`. Si alguien cambiara el total de un país, MySQL no tendría forma de saber qué filas de `pedidos` modificar.

Para aceptar además `INSERT`, la vista tiene que cumplir tres condiciones: no repetir nombres de columna, incluir todas las columnas de la tabla que no tienen valor por defecto y que todas sus columnas sean columnas de la tabla, no expresiones como `col1 + 3` o `UPPER(col2)`. Una columna calculada solo bloquea el `UPDATE` de esa columna; las demás se pueden modificar:

```sql
CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;

UPDATE v SET col1 = 0;  -- funciona
UPDATE v SET col2 = 0;  -- falla: col2 es una expresión
```

Para saber si MySQL considera actualizable una vista, mira la columna `IS_UPDATABLE` de `INFORMATION_SCHEMA.VIEWS`.

## WITH CHECK OPTION: que la vista no acepte filas que no puede ver

Una vista actualizable permite escribir filas que después no muestra. Si `clientes_activos` incluyera la columna `activo`, un `UPDATE clientes_activos SET activo = 0` haría que ese cliente desapareciera de la vista. También podrías insertar a través de ella un cliente con `activo = 0`, que la vista nunca mostraría. `WITH CHECK OPTION` impide las dos cosas: rechaza los `INSERT` de filas que no cumplen el `WHERE` de la vista y los `UPDATE` que dejarían una fila fuera de ella.

```sql
CREATE TABLE t1 (a INT);

CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2
WITH CHECK OPTION;

CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0
WITH LOCAL CHECK OPTION;

CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0
WITH CASCADED CHECK OPTION;
```

```text
mysql> INSERT INTO v2 VALUES (2);
ERROR 1369 (HY000): CHECK OPTION failed 'test.v2'
mysql> INSERT INTO v3 VALUES (2);
ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'
```

Los dos `INSERT` fallan porque 2 no cumple la condición de `v1` (`a < 2`), aunque el mensaje de error nombra la vista en la que intentaste insertar. `LOCAL` y `CASCADED` se diferencian cuando una vista está construida sobre otra:

- Con `LOCAL`, MySQL revisa el `WHERE` de la vista y después pasa a las vistas sobre las que está construida, aplicando en cada una su propia opción. Si una de esas vistas no tiene `CHECK OPTION`, su `WHERE` no se revisa.
- Con `CASCADED`, MySQL revisa el `WHERE` de la vista y el de todas las vistas sobre las que está construida, tengan o no su propio `CHECK OPTION`.

Si escribes `WITH CHECK OPTION` sin `LOCAL` ni `CASCADED`, MySQL usa `CASCADED`.

## Vistas y seguridad: dar acceso a parte de una tabla

Para mí este es el mejor motivo para usar vistas. Imagina una tabla `empleados` con el sueldo de cada persona, y un usuario de reportes que necesita ver nombres y departamentos pero no sueldos:

```sql
CREATE DEFINER = 'admin'@'localhost'
SQL SECURITY DEFINER
VIEW empleados_publico AS
SELECT id, nombre, departamento
FROM empleados
WHERE activo = 1;

GRANT SELECT ON rrhh.empleados_publico TO 'reportes'@'%';
```

El usuario `reportes` puede consultar `empleados_publico` sin tener ningún permiso sobre `empleados`. Como la vista no incluye la columna de sueldo ni las filas de empleados inactivos, nunca los ve: el `SELECT` decide qué columnas se muestran y el `WHERE`, qué filas.

Esto funciona por la cláusula `SQL SECURITY`:

- Con `DEFINER` (el valor por defecto), la vista se ejecuta con los privilegios de la cuenta indicada en `DEFINER`. Quien la consulta solo necesita `SELECT` sobre la vista; sus propios privilegios sobre las tablas no cuentan.
- Con `INVOKER`, la vista se ejecuta con los privilegios de quien la consulta. Si ese usuario no puede leer `empleados`, la consulta falla.

Si no escribes `DEFINER`, MySQL usa como definidor la cuenta que ejecuta el `CREATE VIEW`. El manual recomienda `SQL SECURITY INVOKER` siempre que sea posible, para que una vista no le dé a nadie acceso a datos que no podría leer directamente. `DEFINER` se justifica en casos como el del ejemplo, donde quieres justamente eso: mostrar una parte de la tabla a quien no tiene permiso sobre la tabla completa.

Un riesgo con `DEFINER`: si se borra la cuenta que figura como definidora, la vista queda huérfana y cualquier consulta a ella da error. Para evitarlo, en MySQL 8.4 `DROP USER` y `RENAME USER` fallan si van a dejar objetos huérfanos, salvo que la cuenta que los ejecuta tenga el privilegio `ALLOW_NONEXISTENT_DEFINER`. Para ver qué cuentas figuran como definidoras de tus vistas:

```sql
SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.VIEWS;
```

## Rendimiento de las vistas en MySQL: MERGE y TEMPTABLE

El costo de consultar una vista depende de cómo la procesa MySQL, y para eso tiene dos algoritmos.

Con `MERGE`, MySQL combina tu consulta con la definición de la vista y ejecuta una sola consulta contra las tablas. Con esta vista:

```sql
CREATE ALGORITHM = MERGE VIEW v_merge (vc1, vc2) AS
SELECT c1, c2 FROM t WHERE c3 > 100;
```

La consulta `SELECT * FROM v_merge WHERE vc1 < 100;` se convierte en:

```sql
SELECT c1, c2 FROM t WHERE (c3 > 100) AND (c1 < 100);
```

El resultado es la misma consulta que habrías escrito sin la vista, así que MySQL puede usar los índices de `t` como siempre.

Con `TEMPTABLE`, MySQL ejecuta primero la consulta de la vista, guarda el resultado en una tabla temporal y después ejecuta tu consulta sobre esa tabla temporal. El manual advierte dos efectos: tu consulta ya no puede usar los índices de las tablas base (la consulta que llena la tabla temporal sí puede), y la vista deja de ser actualizable.

`UNDEFINED` deja la elección a MySQL, que usa `MERGE` siempre que puede. Si no escribes `ALGORITHM`, el comportamiento depende del flag `derived_merge` de `optimizer_switch`, que viene activado por defecto.

MySQL no puede usar `MERGE` si la vista contiene alguno de estos elementos:

- Funciones de agregación o de ventana.
- `DISTINCT`, `GROUP BY`, `HAVING` o `LIMIT`.
- `UNION` o `UNION ALL`.
- Subconsultas en la lista del `SELECT`.
- Asignaciones a variables de usuario.
- Solo valores literales.

Si pides `ALGORITHM = MERGE` en una vista que no lo permite, MySQL emite una advertencia y usa `UNDEFINED`.

En la práctica, una vista que solo filtra y une tablas cuesta lo mismo que escribir la consulta a mano. Una vista con `GROUP BY` se procesa con una tabla temporal cada vez que la consultas. Si necesitas ese resultado ya calculado, `CREATE VIEW` no tiene una opción para guardarlo: tendrás que crear una tabla de resumen y actualizarla tú.

## Beneficios de las vistas en MySQL

- Reutilizar consultas: el `JOIN` largo se escribe una vez y se usa en todas partes con un nombre que dice qué devuelve.
- Limitar qué datos ve cada usuario: le das `SELECT` sobre la vista y no sobre la tabla, y solo ve las columnas y filas que la vista incluye.
- Proteger a la aplicación de los cambios de esquema. Si divides una tabla en dos, puedes crear una vista con el nombre y las columnas de la tabla original, y las consultas de lectura que ya existían siguen funcionando mientras migras el resto.
- Validar escrituras: una vista actualizable con `WITH CHECK OPTION` rechaza los `INSERT` y `UPDATE` que dejarían filas fuera de su `WHERE`.
- Simplificar reportes: quien consulta `ventas_por_pais` no necesita saber cómo se relacionan `pedidos` y `clientes`.

También tienen límites: no admiten índices, las que agrupan se procesan con una tabla temporal en cada consulta, su lista de columnas no se actualiza cuando cambian las tablas, y un cambio en una tabla puede romperlas sin que nadie se entere hasta que alguien las consulta.

## Preguntas frecuentes sobre vistas en MySQL

### ¿Qué es una view en MySQL?

Es una consulta `SELECT` guardada con nombre que se consulta como si fuera una tabla. No almacena datos: los lee de las tablas cada vez que la consultas.

### ¿Cuál es la diferencia entre una tabla y una vista en MySQL?

Una tabla guarda filas y puede tener índices. Una vista solo guarda la definición de una consulta y no admite índices. Las dos comparten el espacio de nombres de la base de datos, así que una tabla y una vista no pueden llamarse igual.

### ¿Una vista en MySQL ocupa espacio?

Solo ocupa lo que ocupa su definición; los datos siguen en las tablas. Si MySQL la procesa con `TEMPTABLE`, crea una tabla temporal mientras se ejecuta la consulta.

### ¿Se puede hacer INSERT o UPDATE en una vista en MySQL?

Sí, si la vista es actualizable: sin agregaciones, sin `DISTINCT`, `GROUP BY`, `HAVING` ni `UNION`, y con cada fila de la vista correspondiendo a una fila concreta de una tabla. Para `INSERT` también tiene que incluir todas las columnas que no tienen valor por defecto. La columna `IS_UPDATABLE` de `INFORMATION_SCHEMA.VIEWS` te dice si lo es.

### ¿Las vistas en MySQL son más rápidas?

No. Una vista procesada con `MERGE` rinde igual que la misma consulta escrita a mano, y una con `GROUP BY` o `DISTINCT` se procesa con una tabla temporal cada vez que la consultas.

### ¿MySQL tiene vistas materializadas?

La sintaxis de `CREATE VIEW` en MySQL 8.4 no tiene ninguna opción para guardar el resultado. Si necesitas datos ya calculados, la alternativa es una tabla de resumen que actualizas tú.

### ¿Cómo ver las vistas de una base de datos en MySQL?

Con `SHOW FULL TABLES FROM tu_base WHERE Table_type = 'VIEW';` o consultando `INFORMATION_SCHEMA.VIEWS`. Para ver la definición de una vista concreta, usa `SHOW CREATE VIEW nombre;`, que requiere el privilegio `SHOW VIEW`.

### ¿Cómo eliminar una vista en MySQL?

Con `DROP VIEW IF EXISTS nombre;`. Borra solo la definición, no los datos. En MySQL 8.4, sin `IF EXISTS`, si alguna de las vistas de la lista no existe no se borra ninguna.

El `WHERE` y el `HAVING` que pones dentro de una vista siguen las mismas reglas que en cualquier consulta. Si quieres repasarlas, en [la diferencia entre WHERE y HAVING](/post/cual-es-la-diferencia-entre-where-y-having-en-mysql) están explicadas a partir del orden de ejecución.

## Fuentes

- [MySQL 8.4 Reference Manual: CREATE VIEW Statement](https://dev.mysql.com/doc/refman/8.4/en/create-view.html)
- [MySQL 8.4 Reference Manual: ALTER VIEW Statement](https://dev.mysql.com/doc/refman/8.4/en/alter-view.html)
- [MySQL 8.4 Reference Manual: DROP VIEW Statement](https://dev.mysql.com/doc/refman/8.4/en/drop-view.html)
- [MySQL 8.4 Reference Manual: View Processing Algorithms](https://dev.mysql.com/doc/refman/8.4/en/view-algorithms.html)
- [MySQL 8.4 Reference Manual: Updatable and Insertable Views](https://dev.mysql.com/doc/refman/8.4/en/view-updatability.html)
- [MySQL 8.4 Reference Manual: The View WITH CHECK OPTION Clause](https://dev.mysql.com/doc/refman/8.4/en/view-check-option.html)
- [MySQL 8.4 Reference Manual: Restrictions on Views](https://dev.mysql.com/doc/refman/8.4/en/view-restrictions.html)
- [MySQL 8.4 Reference Manual: Stored Object Access Control](https://dev.mysql.com/doc/refman/8.4/en/stored-objects-security.html)
- [MySQL 8.4 Reference Manual: Optimizing Derived Tables, View References, and Common Table Expressions](https://dev.mysql.com/doc/refman/8.4/en/derived-table-optimization.html)
- [MySQL 8.4 Reference Manual: The INFORMATION_SCHEMA VIEWS Table](https://dev.mysql.com/doc/refman/8.4/en/information-schema-views-table.html)
- [MySQL 8.4 Reference Manual: SHOW TABLES Statement](https://dev.mysql.com/doc/refman/8.4/en/show-tables.html)

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/vistas-en-mysql-que-son-y-como-crearlas](https://www.angelcruz.dev/post/vistas-en-mysql-que-son-y-como-crearlas)
