ALTER PROCEDURE

ALTER PROCEDURE modifica las características de un procedimiento almacenado existente. No puede modificar el cuerpo ni los parámetros del procedimiento; para eso necesitas eliminarlo y recrearlo.

Es un comando con alcance limitado que muchos desarrolladores ni siquiera conocen, ya que el patrón habitual para modificar un procedimiento es DROP + CREATE. Sin embargo, ALTER PROCEDURE tiene su utilidad: permite cambiar metadatos y comportamiento del procedimiento sin necesidad de tener el código fuente completo a mano ni perder los permisos EXECUTE asociados.

Sintaxis

ALTER PROCEDURE nombre_procedimiento
[COMMENT 'texto']
[LANGUAGE SQL]
[{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }]
[SQL SECURITY { DEFINER | INVOKER }]

Qué puede cambiar ALTER PROCEDURE

CaracterísticaDescripción
COMMENTTexto descriptivo del procedimiento
SQL SECURITYDEFINER o INVOKER
Característica SQLCONTAINS SQL, NO SQL, READS SQL DATA, MODIFIES SQL DATA

Qué NO puede cambiar

ALTER PROCEDURE no puede modificar tres aspectos fundamentales:

  • El cuerpo del procedimiento (las sentencias SQL entre BEGIN y END)
  • Los parámetros (ni añadir, ni quitar, ni cambiar tipos)
  • El nombre (MySQL no tiene RENAME PROCEDURE)

Para cambiar cualquiera de estos tres, la única opción es eliminar el procedimiento con DROP y recrearlo con CREATE. Esta es una limitación histórica de MySQL que contrasta con otros motores como Oracle o SQL Server, que ofrecen CREATE OR REPLACE PROCEDURE.

Cambiar el comentario

El caso de uso más práctico de ALTER PROCEDURE es añadir o actualizar la documentación del procedimiento sin tocar su código:

DELIMITER //
 
CREATE PROCEDURE sp_ejemplo()
BEGIN
    SELECT COUNT(*) AS total FROM productos;
END //
 
DELIMITER ;
-- Añadir un comentario
ALTER PROCEDURE sp_ejemplo
COMMENT 'Cuenta el total de productos en la base de datos';
-- Verificar el cambio
SELECT ROUTINE_NAME, ROUTINE_COMMENT
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'tienda_mysql'
AND ROUTINE_NAME = 'sp_ejemplo';
ROUTINE_NAMEROUTINE_COMMENT
sp_ejemploCuenta el total de productos en la base de datos

Documentar procedimientos con COMMENT es especialmente valioso en bases de datos con decenas de procedimientos, donde el nombre por sí solo no siempre comunica qué hace cada uno. Herramientas de administración como MySQL Workbench muestran estos comentarios al listar procedimientos, facilitando la navegación.

Cambiar SQL SECURITY

Cambiar el modo de seguridad es probablemente el uso más importante de ALTER PROCEDURE en entornos de producción. Permite ajustar los permisos sin necesidad de eliminar y recrear el procedimiento (lo que haría perder los GRANT EXECUTE asociados):

-- Crear procedimiento con DEFINER (por defecto)
DELIMITER //
 
CREATE PROCEDURE sp_ver_precios()
SQL SECURITY DEFINER
BEGIN
    SELECT nombre, precio FROM productos WHERE activo = TRUE;
END //
 
DELIMITER ;
-- Cambiar a INVOKER
ALTER PROCEDURE sp_ver_precios
SQL SECURITY INVOKER;
ModoComportamiento
DEFINERSe ejecuta con los permisos del usuario que creó el procedimiento
INVOKERSe ejecuta con los permisos del usuario que llama al procedimiento

Cambiar de DEFINER a INVOKER es útil cuando quieres que el procedimiento respete los permisos del usuario que lo llama, por ejemplo, si diferentes usuarios deben ver diferentes datos según sus privilegios. Cambiar de INVOKER a DEFINER es útil cuando quieres dar acceso controlado a datos que el usuario normalmente no podría consultar. Para una explicación detallada del modelo de seguridad, consulta el artículo de control de acceso.

Cambiar característica SQL

Las características SQL describen qué tipo de operaciones realiza el procedimiento. Aunque MySQL no las verifica activamente (no te impedirá ejecutar un INSERT en un procedimiento marcado como READS SQL DATA), sí pueden afectar a la replicación y a optimizaciones internas:

-- Indicar que el procedimiento solo lee datos
ALTER PROCEDURE sp_ver_precios
READS SQL DATA
COMMENT 'Lista precios de productos activos';
CaracterísticaSignificado
CONTAINS SQLContiene sentencias SQL pero no lee ni modifica datos (por defecto)
NO SQLNo contiene sentencias SQL
READS SQL DATASolo lee datos con SELECT
MODIFIES SQL DATAPuede modificar datos con INSERT, UPDATE, DELETE

En la práctica, estas características son informativas: sirven para documentar la intención del procedimiento y pueden ser consultadas por herramientas de análisis. Sin embargo, en entornos con replicación basada en sentencias (statement-based replication), MySQL puede usar estas características para tomar decisiones sobre cómo replicar las llamadas al procedimiento.

Múltiples cambios a la vez

Puedes modificar varias características en una sola sentencia ALTER:

ALTER PROCEDURE sp_ver_precios
SQL SECURITY INVOKER
READS SQL DATA
COMMENT 'Procedimiento público para consultar precios';

Esto es más eficiente que ejecutar tres ALTER PROCEDURE separados y garantiza que los cambios se apliquen de forma atómica.

Patrón para modificar el cuerpo

Como ALTER PROCEDURE no puede cambiar el cuerpo, el patrón estándar para actualizaciones completas es DROP + CREATE:

-- 1. Guardar la definición actual (por seguridad)
SHOW CREATE PROCEDURE sp_ver_precios\G
 
-- 2. Eliminar
DROP PROCEDURE IF EXISTS sp_ver_precios;
 
-- 3. Recrear con los cambios
DELIMITER //
 
CREATE PROCEDURE sp_ver_precios()
SQL SECURITY INVOKER
READS SQL DATA
COMMENT 'Lista precios de productos activos con stock'
BEGIN
    SELECT nombre, precio, stock
    FROM productos
    WHERE activo = TRUE AND stock > 0
    ORDER BY precio;
END //
 
DELIMITER ;

El paso 1 (guardar la definición) es importante como red de seguridad: si el nuevo CREATE falla por un error de sintaxis, no pierdes la definición anterior. En un flujo de trabajo con control de versiones, este paso no es tan necesario porque siempre puedes recuperar la versión anterior del repositorio.

La desventaja del DROP + CREATE es que los permisos EXECUTE se pierden con el DROP. Si el procedimiento tenía GRANT EXECUTE para varios usuarios, deberás volver a otorgarlos después del CREATE. Por eso, para cambios que solo afectan a las características (no al cuerpo), ALTER PROCEDURE es la opción preferible.

Permisos necesarios

Para usar ALTER PROCEDURE necesitas:

  • Privilegio ALTER ROUTINE en el procedimiento, o
  • Ser el DEFINER del procedimiento
-- Verificar el DEFINER de un procedimiento
SELECT ROUTINE_NAME, DEFINER
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'tienda_mysql'
AND ROUTINE_TYPE = 'PROCEDURE';

Si no eres el DEFINER y no tienes ALTER ROUTINE, la sentencia fallará con un error de permisos.

Limpieza

DROP PROCEDURE IF EXISTS sp_ejemplo;
DROP PROCEDURE IF EXISTS sp_ver_precios;

En el siguiente artículo veremos el control de acceso en procedimientos almacenados y cómo gestionar permisos.

Escrito por Eduardo Lázaro