MySQL possibilidade de criar rotinas globais (procedimentos armazenados e / ou funções)

8

É possível definir de alguma forma rotinas disponíveis globalmente? Parece que toda rotina deve ser criada em um escopo do banco de dados.

Quando tentei criar uma rotina a partir do console (sem emissão prévia use dbname), estou recebendo um erro:

ERROR 1046 (3D000): No database selected

Temos toneladas de bancos de dados idênticos (os dados são diferentes) e o objetivo é criar alguns gatilhos para alguns nomes de tabela. Mas queremos executar apenas uma rotina para não precisarmos criar essas rotinas para cada banco de dados (uma vez que são idênticas, as rotinas funcionariam da mesma forma para cada banco de dados).

bakytn
fonte
Tem certeza de que deseja criar gatilhos no mysql? leia isto um artigo fora do meu dba.stackexchange.com/questions/48797/…
Raymond Nijland

Respostas:

14

Não há como definir procedimentos armazenados ou funções armazenadas (ou eventos) que são globais.

Uma abordagem é criar um esquema comum compartilhado e qualificar as chamadas para as funções e procedimentos com o nome desse esquema ( CALL shared.the_procedure();).

Isso é algo que faço com minha coleção de funções personalizadas de cálculo de data / hora (por exemplo, SELECT date_time.next_quarter_start_after(NOW())) e com a sempre tão útil estrutura common_schema , que, é claro, vive em `common_schema`.

Se você seguir essa abordagem, lembre-se de que, quando uma rotina está em execução, o banco de dados "atual" muda automaticamente e o valor de retorno da DATABASE()função retorna o nome do esquema sob o qual a rotina foi definida, e não o banco de dados atual da sua sessão . Ele muda de volta quando a rotina sai, portanto, se usado em um gatilho, não quebra nada ao seu redor, mas você não tem como saber de dentro da rotina qual era o banco de dados atual, se necessário.

Michael - sqlbot
fonte
+1 funções facto armazenados procedimentos ou armazenados (ou eventos) são sempre definidas dentro de uma base de dados
Raymond Nijland
3

Apenas para expandir um pouco a resposta do @ Michael, mas enquanto referenciar um esquema comum é o caminho a seguir, você pode criar "aliases" nos bancos de dados locais para facilitar um pouco o gerenciamento.

Por exemplo, estou trabalhando com um derivado do MySQL que ainda não possui a UUID_TO_BINfunção do MySQL 8 , então criei o meu e o armazenei em um banco de dados especificamente para coisas globais que chamei common. Portanto, para fazer referência a essa função, agora tenho que usar common.UUID_TO_BINem todas as minhas consultas e procedimentos armazenados. Não é um problema enorme, mas não tão fácil quanto simplesmente chamar UUID_TO_BIN(como faria se a função nativa estivesse disponível).

Então, o que eu fiz também foi adicionado um "alias" a cada um dos meus bancos de dados da seguinte forma:

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

Dessa forma, em cada banco de dados que adiciono esse "pseudônimo", agora posso simplesmente chamar UUID_TO_BIN(some_uuid, TRUE)sem nenhum nome de banco de dados adicionado, mas sem o incômodo de duplicar a função inteira, ou seja, se eu precisar alterar ou otimizar a função por algum motivo, apenas precisa fazer isso em um único lugar ( common.UUID_TO_BIN) em vez de atualizar todos os bancos de dados.

Se eu atualizar posteriormente para um banco de dados com um nativo UUID_TO_BIN, também posso simplesmente remover todas as minhas funções de "alias" e todas as minhas consultas e procedimentos existentes agora o usarão sem nenhuma modificação adicional. Ou, se a função global fosse movida para um banco de dados diferente, só preciso atualizar meus aliases, em vez de todas as minhas consultas que a utilizam.

Não sei ao certo quão inteligente é o MySQL quando se trata de otimizar uma função que simplesmente chama outra função; portanto, pode haver um pequeno custo associado ao redirecioná-lo dessa maneira, mas acho que vale a pena pelo gerenciamento simplificado. mantendo apenas uma única definição "global".

Haravikk
fonte
1

Uma abordagem muito simples é esta:

  1. Verifique se você possui variáveis ​​e parâmetros comuns que serão passados ​​para uma determinada função.
  2. E simplesmente chame a função que você criou de outro banco de dados. 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
fonte