1

I've been trying to dynamically drop tables, procedures, and functions in MySQL. I'm doing this because I am dynamically creating them for a project, when the project version changes I need to clean up and rebuild it.

I can dynamically drop tables, however; I cannot dynamically drop procedures and functions.

Here is an example of the code I am using:

DELIMITER ;;
DROP PROCEDURE IF EXISTS md_remove_project; ;;
CREATE PROCEDURE         md_remove_project()
begin
    DECLARE TableName text;
    DECLARE ProcName  text;
    DECLARE done      int DEFAULT false;
    DECLARE statement text;

    DECLARE table_cursor CURSOR FOR
        SELECT table_name FROM tmp_md_tables;

    DECLARE proc_cursor CURSOR FOR
        SELECT routine_name FROM tmp_md_procedures;

    DECLARE func_cursor CURSOR FOR
        SELECT routine_name FROM tmp_md_functions;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;       

    # Drop all the 'md' tables..............................................
    # This Works...
    DROP TABLE IF EXISTS   tmp_md_tables;
    CREATE TEMPORARY TABLE tmp_md_tables
    SELECT
        table_name
    FROM
        information_schema.tables
    WHERE
        table_name LIKE 'md_%';

    OPEN table_cursor;
    table_loop: LOOP
        FETCH table_cursor INTO TableName;
        IF done THEN
            LEAVE table_loop;
        END IF;

        SET @statement = CONCAT('DROP TABLE IF EXISTS ', TableName, ';');
        PREPARE STATEMENT FROM @statement;
        EXECUTE STATEMENT;
        DEALLOCATE PREPARE STATEMENT;        
    END LOOP;
    CLOSE table_cursor;
    DROP TABLE IF EXISTS tmp_md_tables;
    #-----------------------------------------------------------------------
    # Drop all the 'md' procedures............................................
    DROP TABLE IF EXISTS   tmp_md_procedures;
    CREATE TEMPORARY TABLE tmp_md_procedures
    SELECT
        routine_name
    FROM
        information_schema.routines
    WHERE
        routine_type = 'PROCEDURE'
        and
        routine_name LIKE 'md_%';

    SET done = false;
    OPEN proc_cursor;
    proc_loop: LOOP
        FETCH proc_cursor INTO ProcName;

        IF ProcName = 'md_remove_project' THEN
            ITERATE proc_loop;
        END IF;

        IF done THEN
            leave proc_loop;
        END IF;

        SET @statement = CONCAT('DROP PROCEDURE IF EXISTS ', ProcName, ';');
        PREPARE STATEMENT FROM @statement;
        EXECUTE STATEMENT;
        DEALLOCATE PREPARE STATEMENT;
    END LOOP;
    CLOSE proc_cursor;
    DROP TABLE IF EXISTS tmp_md_procedures;
END;
;;
DELIMITER ;

#CALL md_remove_project;

So I create a table with the procedures named md_%, then I loop through the table. For each routine_name, I prepare a statement to drop the procedure. Then I get the following message:

Error Code: 1295. This command is not supported in the prepared statement protocol yet

Are there any other solutions to drop procedures like 'md_%' ???

Thank You.

Mark Davich
  • 512
  • 1
  • 5
  • 16

1 Answers1

0

When using mysqli_... functions, there is no need to attempt to change the delimiter. The change delimiter command is only needed when using the MySQL (command line) Client. The command is, in fact, a MySQL client command (the client never sends it to the server).

The server is smart enough to recognize the CREATE PROCEDURE command and knowns it ends with END;

As a result, you can simply do two queries: first the DROP PROCEDURE IF EXISTS ... followed by the CREATE PROCEDURE ... END; query.

If you must do them in a single call, you could use mysqli::multi_query but I would recommend against it (because of possible serious security implications).

Jacco
  • 23,534
  • 17
  • 88
  • 105
  • I am building a visual project that accesses a database. I am dynamically creating a new database from the original. As the the visual project (front end) changes new tables and procedures are added to the new database while some tables and procedures are no longer necessary (and therefor need to be dropped). The main question I have is: What are the alternatives to: `SET @statement = CONCAT('DROP PROCEDURE IF EXISTS ', ProcName, ';'); PREPARE STATEMENT FROM @statement; EXECUTE STATEMENT; DEALLOCATE PREPARE STATEMENT;` – Mark Davich Mar 21 '16 at 19:21