Artículo publicado por Eloy8857 el 02 Jun 09
Ha sido leído en 28644 ocasiones
En este artículo se estudiaremos la implementación de las más importantes mejoras que un desarrollador puede encontrar en el uso de MySQL 5 respecto a la versión 4.
Trataremos el concepto de vistas (VIEW) , como consultas almacenadas sobre las cuales luego podremos realizar consultas como si fuesen tablas de registros; y también de stored programs , que abarca desde desencadenadores (TRIGGER, que son como procedimientos que se asocian a un evento en las tablas) hasta funciones almacenadas y procedimientos almacenados.
Veremos no sólo la utilidad de cada objeto, sino también el contexto en el que se deben usar y sus peculiaridades. Y como información adicional tendréis también un resumen de los statements que podéis usar en el cuerpo de los stored programas (declaraciones, bloques, cursores, bucles...) así como un ejemplo en el que se usa un poco de todas esas estructuras.
Se definen para facilitar y restringir el acceso a los datos de las tablas a usuarios limitados.
La estructura es estática y se hace en tiempo de creación: los futuros campos / cambios sobre las tablas no se reflejan en la vista.
Entonces si una vista tiene un SELECT FROM tabla* y después de definirla añadimos un campo a la tabla original, no lo veremos en la vista.
Si después cambiamos la definición de algún campo de la tabla original entonces se generará un error/warning al utilizarla pues seguramente tendrá que truncar valores: los campos eliminados los pasará a NULL, y un DECIMAL cambiado a INT tendrá que truncarlo. En estos casos hay que redefinir la vista porque se volverá muy lenta al consultarla, aunque use algoritmo MERGE.
Su uso es igual que una tabla,
SELECT * FROM myview,
pudiendo usarse en operaciones JOIN, subconsultas y cualquier otro lugar donde una tabla es válida. La única excepción es que excepto SELECT, sólo admiten INSERT, UPDATE o DELETE sobre ellas y en circunstancias especiales.
Para que una vista admita transacciones (UPDATE, DELETE e INSERT) debe cumplir ciertos requisitos. Cito los más habituales:
Su algoritmo debe ser MERGE explícitamente o UNDEFINED pero que el sistema pueda usar MERGE a la hora de realizar la transacción.
Permisos (GRANT)
CREATE VIEW
(para hacer CREATE, DROP y ALTER VIEW) y
SHOW VIEW
(para ejecutar SHOW VIEW, que muestra el detalle de la vista). Para usarlas en el FROM de un SELECT hace falta tener
GRANT SELECT
sobre la vista, o SELECT * sobre la BD de la vista.
INFORMATION_SCHEMA
Para obtener toda la información de todas las vistas:
SELECT * FROM INFORMATION_SCHEMA.VIEWS
Definición
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
El ALTER VIEW se realiza de forma idéntica.
ALGORITHM
MERGE: se traduce la definición de la vista con su equivalente tabla/tablas sin uso de tablas temporales.
No puede ser MERGE si hay DISTINCT, GROUP BY, funciones de agregado, subconsultas en el SELECT...
La manera más sencilla de comprenderlo es dividiendo la consulta en partes.
La parte del SELECT se puede añadir siempre pero sin funciones de agregado (MAX(), MIN(), AVG()...) porque implicaría no poder usar GROUP BY al consultar la vista. Las subconsultas se podrían añadir en el MERGE, lo que pasa es que una subconsulta en el SELECT implica SIEMPRE que se use una tabla temporal, y por lo tanto no se puede hacer MERGE.
La parte FROM admite de todo menos subconsultas, que no se permiten ahí en las vistas (aún así, crearían tabla temporal).
Un ejemplo de la traducción que hace el sistema en un MERGE:
CREATE ALGORITHM MERGE VIEW myview c1, c2
AS SELECT campo1, campo2
FROM tabla WHERE idt > 2000;
SELECT c1, NOW()
FROM myview
WHERE c2 IS NOT NULL
GROUP BY c2;
SELECT campo1, NOW()
FROM tabla
WHERE (idt > 2000) AND (c2 IS NOT NULL)
GROUP BY c2;
Se observa que el sistema puede solapar la vista "myview" con "tabla" sin ningún problema. Además podemos hacer un GROUP BY sobre la vista manteniéndose el MERGE. Otra cosa sería que la consulta hacia una vista implique la creación de una tabla temporal
SELECT *, (subquery) FROM myview;
En este caso el sistema seguiría haciendo el MERGE pero luego tendría que crear una tabla temporal por la subconsulta del SELECT. Es una regla que se aplica a cualquier SELECT.
TEMPTABLE : se crea una tabla temporal al consultar la vista. Si se fuerza a TEMPTABLE, siempre se creará la temporal aunque se pudiera usar MERGE.
UNDEFINED (por defecto) : el sistema selecciona MERGE y si no puede, TEMPTABLE. Si conocemos el algoritmo que se va a usar es mejor indicarlo explícitamente (sobre todo si es TEMPTABLE, para ahorrar que compruebe si puede hacer MERGE).
DEFINER
Los privilegios se comprueban sobre el usuario indicado, que puede no existir (se produciría un warning aunque permitiría crear la vista). Hace falta privilegio SUPER para indicar un usuario distinto a CURRENT_USER.
SQL SECURITY
Los privilegios requeridos para la ejecución de la vista deben ser cumplidos por el indicado. Si la vista tiene SELECT * FROM tabla el sistema comprobará si DEFINER o INVOKER (según se indique) tiene permiso para acceder a "tabla".
CHECK OPTION
No permite hacer INSERT o UPDATE (cuando la definición lo permite) si no se cumplen las condiciones del WHERE de la definición de la vista.
Es decir, si el UPDATE o INSERT que vamos a realizar ocasiona que el registro actualizado/insertado no apareciese al consultar la vista, deniega la operación mostrando un error. Evidentemente esto sólo se aplica a INSERT/UPDATE sobre la vista, no sobre la tabla de la definición de la vista.
CASCADED (por defecto) extiende la restricción a las vistas que se usen en la definición de la vista, y LOCAL sólo a la vista en definición.
El rendimiento es prácticamente igual que el de una consulta normal, teniendo en cuenta que si forzamos TEMPTABLE cuando se podría usar MERGE, entonces el resultado será peor.
Sobre esto cabe destacar que el uso de tablas temporales no tiene por qué ser más lento, de hecho el optimizador de mysql las usa cuando ve que es la mejor opción. Pero claro, el consumo de memoria será mayor en estos casos, aparte de que tiene que volcar los datos a la memoria, usarlos y luego liberar esa memoria.
Siempre se puede hacer un EXPLAIN sobre el statement de la vista para comprobar cómo resuelve la consulta el servidor. Ahí podremos ver si hay un fallo en el diseño de la consulta o es lenta ya de por sí (en la doc de mysql hay mucha información del uso de EXPLAIN para optimización). Si la consulta es buena y al usar la vista tarda en devolver resultados, seguramente sea la consulta sobre la vista lo que debas optimizar (usa EXPLAIN también para ello).
Repaso de las características más importantes que ofrece la versión 5 de MySQL con respecto a versiones anteriores: triggers, procedimientos almacenados, etc.