Posibilidad de MySQL para crear rutinas globales (procedimientos almacenados y / o funciones)

8

¿Es posible de alguna manera definir rutinas disponibles globalmente? Parece que cada rutina debe crearse en un ámbito de la base de datos.

Cuando intenté crear una rutina desde la consola (sin emisión previa use dbname) recibo un error:

ERROR 1046 (3D000): No database selected

Tenemos toneladas de bases de datos idénticas (los datos son diferentes) y el objetivo es crear algunos desencadenantes para algunos nombres de tabla. Pero queremos ejecutar solo una rutina para no tener que crear esas rutinas para cada base de datos (dado que son idénticas, las rutinas funcionarían igual para cada base de datos).

bakytn
fuente
¿Estás seguro de que quieres crear disparadores en mysql? lea esto en un artículo de la mía dba.stackexchange.com/questions/48797/…
Raymond Nijland

Respuestas:

14

No hay forma de definir procedimientos almacenados o funciones almacenadas (o eventos) que sean globales.

Un enfoque es crear un esquema común compartido y luego calificar las llamadas a las funciones y procedimientos con el nombre de ese esquema ( CALL shared.the_procedure();).

Esto es algo que hago con mi colección de funciones de cálculo de fecha / hora personalizadas (p. Ej. SELECT date_time.next_quarter_start_after(NOW())), Y con el marco common_schema , muy práctico , que, por supuesto, vive en `common_schema`.

Si adopta ese enfoque, debe recordar que cuando se ejecuta una rutina, la base de datos "actual" cambia automáticamente y el valor de retorno de la DATABASE()función devuelve el nombre del esquema bajo el cual se definió la rutina, no la base de datos actual de su sesión . Cambia de nuevo cuando sale la rutina, por lo que si se usa en un disparador, no rompe nada que lo rodea, pero no tiene una forma de saber desde dentro de la rutina cuál era la base de datos actual, si necesita saberlo.

Michael - sqlbot
fuente
+1 De hecho, los procedimientos almacenados o las funciones (o eventos) almacenados siempre se definen dentro de una base de datos
Raymond Nijland
3

Solo para ampliar un poco la respuesta de @Michael, pero si bien hacer referencia a un esquema común es el camino a seguir, puede crear "alias" en las bases de datos locales para que sea un poco más fácil de administrar.

Por ejemplo, estoy trabajando con un derivado de MySQL que aún no tiene la UUID_TO_BINfunción de MySQL 8 , así que he creado el mío y lo he almacenado en una base de datos específicamente para cosas globales que he llamado common. Entonces, para hacer referencia a esta función, ahora tengo que usarla common.UUID_TO_BINen todas mis consultas y procedimientos almacenados. No es un gran problema, pero no es tan fácil como simplemente llamar UUID_TO_BIN(como lo haría si la función nativa estuviera disponible).

Entonces, lo que he hecho también ha agregado un "alias" a cada una de mis bases de datos de esta manera:

CREATE FUNCTION `UUID_TO_BIN`(a_uuid CHAR(36), a_reorder BOOL) RETURNS binary(16)
    DETERMINISTIC
RETURN `common`.UUID_TO_BIN(a_uuid, a_reorder);

De esta manera, en cada base de datos agrego este "alias" ahora puedo simplemente llamar UUID_TO_BIN(some_uuid, TRUE)sin agregar ningún nombre de base de datos, pero sin la molestia de duplicar toda la función, es decir, si necesito cambiar u optimizar la función por alguna razón, solo tiene que hacerlo en un solo lugar ( common.UUID_TO_BIN) en lugar de actualizar cada base de datos.

Si luego actualizo a una base de datos con un nativo UUID_TO_BIN, también puedo simplemente eliminar todas mis funciones de "alias" y todas mis consultas y procedimientos existentes ahora lo usarán sin ninguna otra modificación. O si la función global se moviera a una base de datos diferente, solo tengo que actualizar mis alias, en lugar de cada una de mis consultas que la usan.

No estoy seguro de cuán inteligente es MySQL cuando se trata de optimizar una función que simplemente llama a otra función, por lo que puede haber un pequeño costo asociado con la redirección de esta manera, pero creo que vale la pena por la administración simplificada, mientras conservando una sola definición "global".

Haravikk
fuente
1

Un enfoque muy simple es este:

  1. Asegúrese de tener variables y parámetros comunes que se pasarán a una determinada función.
  2. Y simplemente llame a la función que ha realizado desde otra base de datos. ex. select [databasename].empstatus(empid) as status;

Script PHP:

$empid=trim($_REQUEST['empid']);
$conn=mysqli_connect($db_host, $db_user, $db_pass, $db_name);
$sqld="SELECT [otherdatabasename].empstatus('$empid') as employee_status";
$rs=mysqli_query($conn,$sqld);
$rw= mysqli_fetch_array($rs);
Mactamps Brown
fuente