简体   繁体   English

在尝试在 MySQL 中创建存储过程之前,如何检查它是否存在?

[英]How do I check if a stored procedure exists before trying to create it in MySQL?

I'm trying to do CREATE PROCEDURE IF NOT EXISTS in MySQL. CREATE PROCEDURE IF NOT EXISTS MySQL 中CREATE PROCEDURE IF NOT EXISTS我正在尝试执行CREATE PROCEDURE IF NOT EXISTS However it looks like MySQL does not natively support this, which seems like a major oversight to me.但是看起来 MySQL 本身并不支持这一点,这对我来说似乎是一个重大疏忽。

I've created a Spring Batch Java application which contains business schema definitions, which includes both table definitions and the stored procedure definitions.我创建了一个包含业务模式定义的 Spring Batch Java 应用程序,其中包括表定义和存储过程定义。 The table definitions are fine, since they say CREATE TABLE IF NOT EXISTS .表定义很好,因为他们说CREATE TABLE IF NOT EXISTS I would like the stored procedure definitions to be the same, since this business schema script will be run any time the application is launched.我希望存储过程定义相同,因为此业务模式脚本将在应用程序启动时运行。

MySQL does have DROP PROCEDURE IF EXISTS , but I worry that running that before a create runs into a possible race condition. MySQL 确实有DROP PROCEDURE IF EXISTS ,但我担心在创建之前运行它会遇到可能的竞争条件。 What if I've got multiple instances of this application running, and one of the other instances is running one of the stored procedures when I do the DROP and subsequent CREATE?如果我运行了此应用程序的多个实例,而在执行 DROP 和后续 CREATE 时,其他实例之一正在运行存储过程之一,该怎么办? That seems like an all around bad idea.这似乎是个坏主意。 I don't want it to interrupt anything already running.我不希望它中断任何已经在运行的东西。

Someone else must have encountered this same problem by now.其他人现在一定也遇到过同样的问题。 What's the solution?解决办法是什么?

Just query the routines table in the information_schema .只需查询information_schema 中例程表。 Example:例子:

select ROUTINE_BODY from routines where ROUTINE_NAME like '%BLA BLA%';

Or maybe create a function to see if the proc exists:或者创建一个函数来查看 proc 是否存在:

use db_where_you_wanna_see_if_proc_exists;
delimiter $$

CREATE FUNCTION PROC_EXISTS(_proc_name VARCHAR(45))
RETURNS BOOLEAN
DETERMINISTIC READS SQL DATA
BEGIN
    DECLARE _exists  TINYINT(1) DEFAULT 0;

    SELECT COUNT(*) INTO _exists
    FROM information_schema.routines 
    WHERE ROUTINE_SCHEMA =  DATABASE()
    AND ROUTINE_NAME =  _proc_name;

    RETURN _exists;

END$$

delimiter ;


SELECT PROC_EXISTS('proc_name') as _exists;

I would not recommend relying on your application to create your database structure.我不建议依赖您的应用程序来创建您的数据库结构。 From long personal experience, it only causes headaches down the line.从长期的个人经验来看,它只会导致令人头疼的问题。 CREATE TABLE IF NOT EXISTS is simple enough, but eventually you need to " ALTER TABLE if it doesn't match what I expect" and things start getting ugly. CREATE TABLE IF NOT EXISTS很简单,但最终你需要“如果它与我期望的不匹配,则ALTER TABLE ”并且事情开始变得丑陋。 That said, you can find stored routines in information_schema .也就是说,您可以在information_schema找到存储的例程。 routines . routines

The only way I can think to get around multiple processes running through this code at the same time is to add another table for use as a sort of lock.我能想到的绕过同时运行此代码的多个进程的唯一方法是添加另一个表以用作某种锁。 Each application executes UPDATE sentinelTable SET beingHandledBy = user() WHERE beingHandledBy IS NOT NULL;每个应用程序执行UPDATE sentinelTable SET beingHandledBy = user() WHERE beingHandledBy IS NOT NULL; followed by SELECT beingHandledBy = user() FROM sentinelTable;其次是SELECT beingHandledBy = user() FROM sentinelTable; the process that gets back a "true" result then continues with the database normalization code, and when finished sets beingHandledBy back to NULL.返回“真”结果的过程然后继续执行数据库规范化代码,并在完成后将beingHandledBy设置回NULL。

Edit: Actually, CONNECTION_ID() might be a better function to use instead of USER().编辑:实际上, CONNECTION_ID()可能是比 USER() 更好的函数。 If you have multiple instances or threads connecting independently from the same machine, they would have the same value for USER().如果您有多个实例或线程独立于同一台机器连接,则它们的 USER() 值将相同。

您可以使用以下查询: SHOW PROCEDURE STATUS WHERE NAME='procedureName' 还可以在此处查看这些答案: List of Stored Procedures/Functions Mysql Command Line

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM