Возможность MySQL для создания глобальных подпрограмм (хранимых процедур и / или функций)

8

Можно ли как-то определить глобально доступные процедуры? Кажется, что каждая подпрограмма должна быть создана в области базы данных.

Когда я пытался создать подпрограмму из консоли (без предварительной выдачи use dbname), я получаю сообщение об ошибке:

ERROR 1046 (3D000): No database selected

У нас есть множество идентичных баз данных (данные разные), и цель состоит в том, чтобы создать несколько триггеров для некоторых имен таблиц. Но мы хотим запустить только одну подпрограмму, поэтому нам не нужно создавать эти подпрограммы для каждой базы данных (поскольку они идентичны, подпрограммы будут работать одинаково для каждой базы данных).

bakytn
источник
Вы уверены, что хотите создать триггеры в MySQL? Прочитайте это в моей статье dba.stackexchange.com/questions/48797/…
Рэймонд

Ответы:

14

Невозможно определить хранимые процедуры или хранимые функции (или события), которые являются глобальными.

Один из подходов состоит в том, чтобы создать общую общую схему, а затем сопоставить вызовы функций и процедур с именем этой схемы ( CALL shared.the_procedure();).

Это то, что я делаю с моей коллекцией пользовательских функций вычисления даты / времени (например, SELECT date_time.next_quarter_start_after(NOW())) и с очень удобной платформой common_schema , которая, конечно, живет в `common_schema`.

Если вы выберете такой подход, вы должны помнить, что при выполнении подпрограммы «текущая» база данных автоматически изменяется, и возвращаемое значение DATABASE()функции возвращает имя схемы, в которой была определена подпрограмма, а не текущая база данных вашего сеанса. , Он возвращается обратно при выходе из подпрограммы, поэтому, если он используется в триггере, он не нарушает ничего вокруг него, но у вас нет способа узнать изнутри подпрограммы, какой была текущая база данных, если вам нужно было это знать.

Майкл - sqlbot
источник
+1 Действительно хранимые процедуры или хранимые функции (или события) всегда определяются в базе данных
Raymond Nijland
3

Просто чтобы немного расширить ответ @ Michael, но, несмотря на то, что ссылка на общую схему - это путь, вы можете создать «псевдонимы» в локальных базах данных, чтобы сделать это немного проще в управлении.

Например, я работаю с производной MySQL, у которой еще нет функции MySQL 8 UUID_TO_BIN, поэтому я создал свою собственную и сохранил ее в базе данных специально для глобальных вещей, которые я назвал common. Поэтому для ссылки на эту функцию я теперь должен использовать common.UUID_TO_BINвсе свои запросы и хранимые процедуры. Не большая проблема, но не так просто, как простой вызов UUID_TO_BIN(как если бы была доступна нативная функция).

Итак, что я сделал, так это добавил «псевдоним» к каждой из моих баз данных примерно так:

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

Таким образом, в каждую базу данных я добавляю этот «псевдоним», который я теперь могу просто вызывать UUID_TO_BIN(some_uuid, TRUE)без добавления какого-либо имени базы данных, но без необходимости дублировать всю функцию, т. Е. Если по какой-то причине мне нужно было изменить или оптимизировать функцию, я только должны делать это в одном месте ( common.UUID_TO_BIN), а не обновлять каждую базу данных.

Если я позже обновлю базу данных с нативным, UUID_TO_BINя также могу просто удалить все мои «псевдонимные» функции, и все мои существующие запросы и процедуры теперь будут использовать ее без каких-либо дальнейших изменений. Или, если глобальная функция должна была быть перемещена в другую базу данных, мне нужно только обновить мои псевдонимы, а не каждый из моих запросов, которые ее используют.

Я не уверен, насколько умным является MySQL, когда речь заходит об оптимизации функции, которая просто вызывает другую функцию, поэтому возможна небольшая плата за перенаправление таким образом, но я думаю, что это стоит того, чтобы упростить управление, хотя сохраняя только одно «глобальное» определение.

Haravikk
источник
1

Очень простой подход заключается в следующем:

  1. Убедитесь, что у вас есть общие переменные и параметры, которые будут переданы определенной функции.
  2. И просто вызовите функцию, которую вы сделали из другой базы данных. ех. select [databasename].empstatus(empid) as status;

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);
Мактампс Браун
источник