MySQL Stored Procedures
Check
To show all Stored Procedures...
SHOW PROCEDURE STATUS;
To show all Stored Procedures for a specified database...
SHOW PROCEDURE STATUS WHERE db = 'database_name';
To show all Stored Procedures for a specified database by querying the data dictionary...
SELECT routine_name
FROM information_schema.routines
WHERE routine_type = 'PROCEDURE'
AND routine_schema = 'database_name';
To view the definition of a Stored Procedure...
SHOW CREATE PROCEDURE procedure_name\G;
Create
If you haven't been granted the privileges to create procedures already, then you need...
GRANT CREATE ROUTINE ON myDB.* TO myUser;
DELIMITER $$
CREATE DEFINER = 'myUser'
PROCEDURE IF NOT EXISTS myProc(myParam)
COMMENT 'Procedure to output a row to a text file'
LANGUAGE SQL
NOT DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
SELECT myRow
FROM myTable
INTO OUTFILE 'myOutfile';
END$$
DELIMITER ;
Another example showing how to pass and use a date parameter to a stored procedure...
DELIMITER //
DROP PROCEDURE IF EXISTS myProc;
CREATE PROCEDURE myProc(IN myDate DATE)
BEGIN
SELECT @myCommand := CONCAT("SELECT 'myHeading1',
'myHeading2'
UNION (SELECT myCol1,
myCol2
INTO OUTFILE '/tmp/myOutput", DATE_FORMAT(myDate,'%d%m%Y'),'.csv',"'
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
FROM myDB.myTable
WHERE DATE_FORMAT(myCol2, '%d/%m/%Y') = DATE_FORMAT(?,'%d/%m/%Y')
ORDER BY myCol1)");
PREPARE stmt FROM @myCommand;
EXECUTE stmt USING @myDate;
DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
If you have saved your DDL to a script file, you can run it using...
source myscript.sql
Make appropriate Grants...
GRANT EXECUTE ON PROCEDURE myDB.myProc TO aUser;
GRANT ALTER ROUTINE ON PROCEDURE myDB.myProc TO aUser;
GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE myDB.myProc TO aUser;
GRANT ALL PRIVILEGES ON PROCEDURE myDB.myProc TO aUser;
aUser will be able to Execute myProc
aUser will be able to ALTER PROCEDURE myProc()
aUser will be able to Execute and Alter myProc
As above
Execute
call myProc();
call myProc(myParamValue);
Duplicate
To dump just stored procedures, functions and triggers for a specific database...
mysqldump -h myhost -u myuser -p --no-create-db --no-data --no-create-info --routines --databases mydatabase > routines.sql
To load them into a new instance (with same usernames)...
For different usernames just edit the routines.sql script before running itmysql -u root -p
source routines.sql
DROP
DROP PROCEDURE myProc;
DROP PROCEDURE IF EXISTS myProc;
Troubleshooting
Case Study #1
Why does the same SQL statment run more slowly in a stored procedure than when executed standalone?
DELIMITER $$
CREATE DEFINER=`myuser`@`%`
PROCEDURE `myproc`(IN inid VARCHAR(5))
BEGIN
SELECT mycolumn
FROM mytable
WHERE myid = 'inid';
END$$
DELIMITER ;
call myProc(12345);
This executes in approximately 30 secondsSELECT mycolumn
FROM mytable
WHERE myid = '12345;
This executes in less than 1 secondUnfortunately it's not yet (January 2023) possible to EXPLAIN a stored procedure, so we can't see whether the same execution plan is being used.
However, a fair guess would be that an index is being used standalone but not by the procedure... but why?
Perhaps stackoverflow has the answer?
https://stackoverflow.com/questions/16752922/mysql-stored-procedure-is-slower-20-times-than-standard-queryThe accepted answer suggests a bug related to differences in database characterset versus table characterset.
Let's look at table status...
SHOW TABLE STATUS LIKE 'mytable'\G
Let's have a look at the CREATE TABLE statement for this table...
SHOW CREATE TABLE mytable\G
So, this table is created with a default characterset of utf8...
Does this differ from our database?...
status
Connection id: 48486048Current database:Current user: root@localhostSSL: Not in useCurrent pager: stdoutUsing outfile: ''Using delimiter: ;Server version: 8.0.23-commercial MySQL Enterprise Server - CommercialProtocol version: 10Connection: Localhost via UNIX socketServer characterset: utf8mb4Db characterset: utf8mb4Client characterset: utf8mb4Conn. characterset: utf8mb4UNIX socket: /mysql/mysql.sockBinary data as: HexadecimalUptime: 559 days 2 hours 13 min 34 sec
Threads: 5 Questions: 325482610 Slow queries: 7908120 Opens: 1698 Flush tables: 3 Open tables: 1370 Queries per second avg: 6.737
Hmm, could the root cause of this be related to a mismatch between utf8 and utf8mb4?
Changing the table characterset and collation to match the database seems like a good idea but obviously carries some risk... what other impact could changing the characterset of a table have? How did it end up different in the first place, and was this a concious decision?... and, in a production environment, this really should go through Change Management. How can we work around the issue quickly whilst we ponder the above?
Let's force a conversion in our stored procedure....
DELIMITER $$
CREATE DEFINER=`myuser`@`%`
PROCEDURE `myproc`(IN inid VARCHAR(5))
BEGIN
SELECT mycolumn
FROM mytable
WHERE myid = CONVERT(inid utf8) COLLATE utf8_general_ci;
END$$
DELIMITER ;
call myProc(12345);
This now executes in less than 1 secondThis is an ok workaround, but real fix would be to change the table so that the character sets and collation match.
Note that the root cause here is the change in default character set (from utf8 to utf8mb4) between MySQL 5.7 and MySQL 8.0. The utf8 character set is an alias for utf8mb3 which is deprecated in MySQL 8.0. Eventually, utf8 is mooted to become an alias for utf8mb4, so this problem could disappear in later versions.
Bibliography
https://www.mysqltutorial.org/listing-stored-procedures-in-mysql-database.aspx https://www.mysqltutorial.org/introduction-to-sql-stored-procedures.aspxhttps://dpursanov.medium.com/privileges-for-only-specific-stored-procedures-in-mysql-mariadb-5473a8c319d0
CREATEhttps://dev.mysql.com/doc/refman/8.0/en/create-procedure.htmlhttps://dba.stackexchange.com/questions/126312/is-there-an-alternative-to-create-or-replace-procedure-in-mysqlhttps://stackoverflow.com/questions/54001025/unknown-column-in-where-clause-with-stored-procedure-via-mysql
Duplicatehttps://www.eversql.com/exporting-mysql-schema-structure-to-xml-using-mysql-clients/
Troubleshootinghttps://stackoverflow.com/questions/16752922/mysql-stored-procedure-is-slower-20-times-than-standard-queryhttps://dev.mysql.com/doc/refman/8.0/en/charset-collate.htmlhttps://www.eversql.com/mysql-utf8-vs-utf8mb4-whats-the-difference-between-utf8-and-utf8mb4/