MySQL-Möglichkeit zum Erstellen globaler Routinen (gespeicherte Prozeduren und / oder Funktionen)

8

Ist es möglich, global verfügbare Routinen zu definieren? Es scheint, dass jede Routine in einem Bereich der Datenbank erstellt werden muss.

Beim Versuch, eine Routine über die Konsole zu erstellen (ohne vorherige Ausgabe use dbname), wird folgende Fehlermeldung angezeigt:

ERROR 1046 (3D000): No database selected

Wir haben Tonnen identischer Datenbanken (Daten sind unterschiedlich) und das Ziel ist es, einige Trigger für einige Tabellennamen zu erstellen. Wir möchten jedoch nur eine Routine ausführen, damit wir diese Routinen nicht für jede Datenbank erstellen müssen (da sie identisch sind, funktionieren die Routinen für jede Datenbank gleich).

bakytn
quelle
Sind Sie sicher, dass Sie Trigger in MySQL erstellen möchten? Lesen Sie dies einen Artikel von mir dba.stackexchange.com/questions/48797/…
Raymond Nijland

Antworten:

14

Es gibt keine Möglichkeit, gespeicherte Prozeduren oder gespeicherte Funktionen (oder Ereignisse) zu definieren, die global sind.

Ein Ansatz besteht darin, ein gemeinsames Schema zu erstellen und dann die Aufrufe der Funktionen und Prozeduren mit dem Namen dieses Schemas ( CALL shared.the_procedure();) zu qualifizieren.

Dies ist etwas, was ich mit meiner Sammlung von benutzerdefinierten Datums- / Zeitberechnungsfunktionen (z. B. SELECT date_time.next_quarter_start_after(NOW())) und mit dem sehr praktischen common_schema- Framework mache , das natürlich in "common_schema" lebt.

Wenn Sie diesen Ansatz wählen, müssen Sie sich daran erinnern, dass sich beim Ausführen einer Routine die "aktuelle" Datenbank automatisch ändert und der Rückgabewert der DATABASE()Funktion den Namen des Schemas zurückgibt, unter dem die Routine definiert wurde, nicht die aktuelle Datenbank Ihrer Sitzung . Es ändert sich zurück, wenn die Routine beendet wird. Wenn es also in einem Trigger verwendet wird, wird nichts um es herum zerstört, aber Sie können innerhalb der Routine nicht wissen, was die aktuelle Datenbank war, wenn Sie es wissen müssen.

Michael - sqlbot
quelle
+1 In der Tat werden gespeicherte Prozeduren oder gespeicherte Funktionen (oder Ereignisse) immer in einer Datenbank definiert
Raymond Nijland
3

Nur um die Antwort von @ Michael ein wenig zu erweitern, aber während das Verweisen auf ein allgemeines Schema der richtige Weg ist, können Sie "Aliase" in lokalen Datenbanken erstellen, um die Verwaltung zu vereinfachen.

Zum Beispiel arbeite ich mit einem MySQL-Derivat, das noch nicht über die UUID_TO_BINFunktion von MySQL 8 verfügt. Daher habe ich mein eigenes erstellt und es in einer Datenbank speziell für globale Inhalte gespeichert, die ich aufgerufen habe common. Um auf diese Funktion zu verweisen, muss ich sie jetzt common.UUID_TO_BINin all meinen Abfragen und gespeicherten Prozeduren verwenden. Kein großes Problem, aber nicht ganz so einfach wie das einfache Aufrufen UUID_TO_BIN(wie wenn die native Funktion verfügbar wäre).

Also habe ich auch einen "Alias" zu jeder meiner Datenbanken hinzugefügt:

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);

Auf diese Weise kann ich in jeder Datenbank, die ich diesen "Alias" hinzufüge, jetzt einfach aufrufen, UUID_TO_BIN(some_uuid, TRUE)ohne dass ein Datenbankname hinzugefügt wird, aber ohne den Aufwand, die gesamte Funktion zu duplizieren, dh wenn ich die Funktion aus irgendeinem Grund ändern oder optimieren musste, nur ich müssen dies an einem einzigen Ort tun ( common.UUID_TO_BIN), anstatt jede einzelne Datenbank zu aktualisieren.

Wenn ich später ein Upgrade auf eine Datenbank mit einem nativen UUID_TO_BINSystem durchführe, kann ich auch einfach alle meine "Alias" -Funktionen entfernen. Alle vorhandenen Abfragen und Prozeduren verwenden sie jetzt ohne weitere Änderungen. Oder wenn die globale Funktion in eine andere Datenbank verschoben werden soll, muss ich nur meine Aliase aktualisieren und nicht jede einzelne meiner Abfragen, die sie verwenden.

Ich bin mir nicht sicher, wie intelligent MySQL ist, wenn es darum geht, eine Funktion zu optimieren, die einfach eine andere Funktion aufruft. Daher kann die Umleitung auf diese Weise mit geringen Kosten verbunden sein, aber ich denke, es lohnt sich für die vereinfachte Verwaltung Beibehaltung nur einer einzigen "globalen" Definition.

Haravikk
quelle
1

Ein sehr einfacher Ansatz ist folgender:

  1. Stellen Sie sicher, dass Sie gemeinsame Variablen und Parameter haben, die an eine bestimmte Funktion übergeben werden.
  2. Rufen Sie einfach die Funktion auf, die Sie aus einer anderen Datenbank erstellt haben. Ex. select [databasename].empstatus(empid) as status;;

PHP-Skript:

$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
quelle