web-dev-qa-db-ja.com

MySQLがグローバルルーチン(ストアドプロシージャや関数)を作成する可能性

どういうわけかグローバルに利用可能なルーチンを定義することは可能ですか?すべてのルーチンはデータベースのスコープ内で作成する必要があるようです。

コンソールからルーチンを作成しようとすると(事前に_use dbname_を発行せずに)エラーが発生します。

ERROR 1046 (3D000): No database selected

同一のデータベースがたくさんあり(データは異なります)、いくつかのテーブル名に対していくつかのトリガーを作成することが目標です。ただし、実行するルーチンは1つだけにしたいので、データベースごとにこれらのルーチンを作成する必要はありません(これらは同じなので、ルーチンは各データベースで同じように動作します)。

8
bakytn

グローバルなストアドプロシージャまたはストアドファンクション(またはイベント)を定義する方法はありません。

1つのアプローチは、共有の共通スキーマを作成してから、そのスキーマの名前(CALL shared.the_procedure();)を使用して、関数とプロシージャの呼び出しを修飾することです。

これは、カスタムの日付/時刻計算関数のコレクション(SELECT date_time.next_quarter_start_after(NOW())など)と、これまでにないほど便利な common_schema フレームワークで行うものですが、もちろん、 `common_schema`に住んでいます。

そのアプローチを取る場合、ルーチンが実行されているとき、「現在の」データベースは自動的に変更され、DATABASE()関数の戻り値は、ルーチンが使用されていたスキーマの名前を返すことを覚えておく必要がありますセッションの現在のデータベースではなく、定義されています。ルーチンが終了すると元に戻ります。そのため、トリガーで使用しても、周囲を壊すことはありませんが、必要な場合に、ルーチン内から現在のデータベースが何であるかを知る方法はありません。

14

@Michaelの答えを少し拡張するだけですが、一般的なスキーマを参照する方法ですが、ローカルデータベースに「エイリアス」を作成して、これを少し管理しやすくすることができます。

たとえば、MySQL 8の_UUID_TO_BIN_関数がまだないMySQL派生物を使用しているので、独自に作成し、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がどれほど賢いかわからないので、このようにリダイレクトすることに関連するわずかなコストがかかる可能性がありますが、管理を簡素化するには価値があると思いますが、単一の「グローバル」定義のみを保持します。

3
Haravikk

非常に簡単なアプローチはこれです:

  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);
1
Mactamps Brown