是否可以以某种方式定义全局可用的例程?似乎每个例程都必须在数据库范围内创建。
当我尝试从控制台创建例程(没有发出之前use dbname
)时,出现错误:
ERROR 1046 (3D000): No database selected
我们有大量相同的数据库(数据不同),目标是为某些表名创建一些触发器。但是我们只想运行一个例程,所以我们不必为每个数据库都创建这些例程(由于它们是相同的,因此例程对于每个数据库都将起作用)。
是否可以以某种方式定义全局可用的例程?似乎每个例程都必须在数据库范围内创建。
当我尝试从控制台创建例程(没有发出之前use dbname
)时,出现错误:
ERROR 1046 (3D000): No database selected
我们有大量相同的数据库(数据不同),目标是为某些表名创建一些触发器。但是我们只想运行一个例程,所以我们不必为每个数据库都创建这些例程(由于它们是相同的,因此例程对于每个数据库都将起作用)。
Answers:
无法定义全局的存储过程或存储函数(或事件)。
一种方法是创建一个共享的通用模式,然后使用该模式的名称(CALL shared.the_procedure();
)限定对函数和过程的调用。
这是我使用自定义日期/时间计算函数(例如SELECT date_time.next_quarter_start_after(NOW())
)以及非常方便的common_schema框架(当然,该框架位于“ common_schema”中)所做的事情。
如果采用这种方法,则必须记住当例程运行时,“当前”数据库会自动更改,并且该DATABASE()
函数的返回值将返回定义该例程的模式名称,而不是会话的当前数据库。它在例程退出时变回原来的状态,因此,如果在触发器中使用它,它不会破坏周围的任何内容,但是如果您需要知道的话,您将无法从例程内部了解当前数据库的内容。
只是为了扩展@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的智能程度如何,因此以这种方式重定向它可能会花费一些成本,但我认为简化管理是值得的仅保留一个“全局”定义。
一个非常简单的方法是:
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);