Possibilité MySQL de créer des routines globales (procédures et / ou fonctions stockées)

8

Est-il possible de définir d'une manière ou d'une autre des routines disponibles à l'échelle mondiale? Il semble que chaque routine doit être créée dans une étendue de la base de données.

Lorsque j'ai essayé de créer une routine à partir de la console (sans émission préalable use dbname), j'obtiens une erreur:

ERROR 1046 (3D000): No database selected

Nous avons des tonnes de bases de données identiques (les données sont différentes) et l'objectif est de créer des déclencheurs pour certains noms de tables. Mais nous voulons exécuter une seule routine afin de ne pas avoir à créer ces routines pour chaque base de données (car elles sont identiques, les routines fonctionneraient de la même manière pour chaque base de données).

Bakytn
la source
Êtes-vous sûr de vouloir créer des déclencheurs dans mysql? lire ceci un article sur le mien dba.stackexchange.com/questions/48797/…
Raymond Nijland

Réponses:

14

Il n'existe aucun moyen de définir des procédures stockées ou des fonctions (ou événements) stockés qui sont globaux.

Une approche consiste à créer un schéma commun partagé, puis à qualifier les appels aux fonctions et procédures avec le nom de ce schéma ( CALL shared.the_procedure();).

C'est quelque chose que je fais avec ma collection de fonctions de calcul de date / heure personnalisées (par exemple, SELECT date_time.next_quarter_start_after(NOW())) et avec le cadre commun_schema toujours aussi pratique , qui, bien sûr, vit dans `common_schema`.

Si vous adoptez cette approche, vous devez vous rappeler que lorsqu'une routine est en cours d'exécution, la base de données "actuelle" change automatiquement et la valeur de retour de la DATABASE()fonction renvoie le nom du schéma sous lequel la routine a été définie, pas la base de données actuelle de votre session . Il change à la fin de la routine, donc s'il est utilisé dans un déclencheur, il ne casse rien autour de lui mais vous n'avez aucun moyen de savoir de l'intérieur de la routine ce qu'était la base de données actuelle, si vous aviez besoin de savoir.

Michael - sqlbot
la source
+1 En effet, les procédures stockées ou les fonctions stockées (ou événements) sont toujours définies dans une base de données
Raymond Nijland
3

Juste pour développer un peu la réponse de @ Michael, mais tout en référençant un schéma commun est le chemin à parcourir, vous pouvez créer des "alias" dans les bases de données locales pour rendre cela un peu plus facile à gérer.

Par exemple, je travaille avec un dérivé de MySQL qui n'a pas encore la UUID_TO_BINfonction de MySQL 8 , j'ai donc créé la mienne et l'ai stockée dans une base de données spécifiquement pour les éléments globaux que j'ai appelés common. Donc, pour référencer cette fonction, je dois maintenant l'utiliser common.UUID_TO_BINdans toutes mes requêtes et procédures stockées. Pas un gros problème, mais pas aussi simple que d'appeler simplement UUID_TO_BIN(comme je le ferais si la fonction native était disponible).

Donc, ce que j'ai fait, c'est aussi ajouté un "alias" à chacune de mes bases de données comme ceci:

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 cette façon, dans chaque base de données, j'ajoute cet "alias", je peux maintenant simplement appeler UUID_TO_BIN(some_uuid, TRUE)sans ajouter de nom de base de données, mais sans les tracas de duplication de la fonction entière, c'est-à-dire si j'avais besoin de changer ou d'optimiser la fonction pour une raison quelconque, je ne fais que doivent le faire en un seul endroit ( common.UUID_TO_BIN) plutôt que de mettre à jour chaque base de données.

Si je passe ultérieurement à une base de données avec un natif, UUID_TO_BINje peux également supprimer simplement toutes mes fonctions "alias" et toutes mes requêtes et procédures existantes vont maintenant l'utiliser sans aucune autre modification. Ou si la fonction globale devait être déplacée vers une autre base de données, je n'ai qu'à mettre à jour mes alias, plutôt que chacune de mes requêtes qui l'utilisent.

Je ne sais pas à quel point MySQL est intelligent lorsqu'il s'agit d'optimiser une fonction qui appelle simplement une autre fonction, donc il peut y avoir un léger coût associé à la rediriger de cette façon, mais je pense que cela en vaut la peine pour la gestion simplifiée, tout en ne conservant qu'une seule définition «globale».

Haravikk
la source
1

Une approche très simple est la suivante:

  1. Assurez-vous que vous disposez de variables et de paramètres communs qui seront transmis à une certaine fonction.
  2. Et appelez simplement la fonction que vous avez créée à partir d'une autre base de données. 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
la source