简体   繁体   中英

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. However it looks like MySQL does not natively support this, which seems like a major oversight to me.

I've created a Spring Batch Java application which contains business schema definitions, which includes both table definitions and the stored procedure definitions. The table definitions are fine, since they say 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. 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? 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 . Example:

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

Or maybe create a function to see if the proc exists:

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. That said, you can find stored routines in information_schema . 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; followed by 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.

Edit: Actually, CONNECTION_ID() might be a better function to use instead of USER(). If you have multiple instances or threads connecting independently from the same machine, they would have the same value for USER().

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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