---json { "page_id": "75sg7krdu24veg07kvid0" } --- ====== How to execute a procedure in MySQL ? ====== ===== About ===== This ''howto'' shows you how to create and execute a [[:docs:system:database:sql_procedure|SQL Procedure]] in [[:docs:system:mysql:mysql|MySQL]]. This example has been taken from the [[https://docs.oracle.com/javase/tutorial/jdbc/basics/storedprocedures.html#creating_stored_procedure_mysql|official documentation examples]] ===== Steps ===== ==== Start MySQL ==== The next steps will be using the [[howto_connection|mysql howto connection]]. * We [[howto_connection#start_the_mysql_service|start the mysql docker image]]. tabul service start mysql * [[docs:tabul:connection:ping|Ping]] the connection to check that the database is up. tabul connection ping mysql The connection (mysql) has been pinged successfully Cleaning, should be after the start tabul data drop --no-strict-selection *@mysql ==== Creation of the schema and procedure ==== === The Coffee Break sample schema === In the [[https://docs.oracle.com/javase/tutorial/jdbc/basics/gettingstarted.html#step6|getting started]], they provide the `Coffee Break` database. This database is used by a proprietor of a small coffee house where coffee beans are sold by the pound and brewed coffee is sold by the cup. We have extracted the sql scripts. They are available at `msql/coffee-break-sample-db` By using the [[:docs:tabul:data:list|list command]] with a [[:howto:tabul:glob|star glob expression]], we can list all files tabul data list mysql/coffee-break-sample-db/*@howto path media_type ------------------------------------------------------------- ---------- mysql/coffee-break-sample-db/call-get-supplier-of-coffee.sql text/sql mysql/coffee-break-sample-db/call-show-suppliers.sql text/sql mysql/coffee-break-sample-db/drop-01-tables.sql text/sql mysql/coffee-break-sample-db/install-01-create-tables.sql text/sql mysql/coffee-break-sample-db/install-02-populate-tables.sql text/sql mysql/coffee-break-sample-db/install-03-create-procedures.sql text/sql mysql/coffee-break-sample-db/README.md text/plain === The Create Procedure Statements === MySQL uses a SQL-based syntax for its stored procedures. The script ''install-03-create-procedures.sql'' contains [[:docs:resource:sql_ddl|SQL DDL statements]] that will create 3 [[:docs:resource:sql_stored_procedure|stored procedures]]: * ''SHOW_SUPPLIERS'' - a procedure that returns a result set * ''RAISE_PRICE'' - a procedure that raise the prices of a coffee product * ''GET_SUPPLIER_OF_COFFEE'' - a procedure that returns the supplier of a coffee product The content is: tabul data cat mysql/coffee-break-sample-db/install-03-create-procedures.sql@howto drop procedure if exists SHOW_SUPPLIERS; drop procedure if exists GET_SUPPLIER_OF_COFFEE; drop procedure if exists RAISE_PRICE; # Creating procedure SHOW_SUPPLIERS create procedure SHOW_SUPPLIERS() begin select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME from SUPPLIERS, COFFEES where SUPPLIERS.SUP_ID = COFFEES.SUP_ID order by SUP_NAME, COF_NAME; end; # Creating procedure GET_SUPPLIER_OF_COFFEE create procedure GET_SUPPLIER_OF_COFFEE(IN coffeeName varchar(32), OUT supplierName varchar(40)) begin select SUPPLIERS.SUP_NAME into supplierName from SUPPLIERS, COFFEES where SUPPLIERS.SUP_ID = COFFEES.SUP_ID and coffeeName = COFFEES.COF_NAME; select supplierName; end; # Creating procedure RAISE_PRICE create procedure RAISE_PRICE(IN coffeeName varchar(32), IN maximumPercentage float, INOUT newPrice numeric(10,2)) begin main: BEGIN declare maximumNewPrice numeric(10,2); declare oldPrice numeric(10,2); select COFFEES.PRICE into oldPrice from COFFEES where COFFEES.COF_NAME = coffeeName; set maximumNewPrice = oldPrice * (1 + maximumPercentage); if (newPrice > maximumNewPrice) then set newPrice = maximumNewPrice; end if; if (newPrice <= oldPrice) then set newPrice = oldPrice; leave main; end if; update COFFEES set COFFEES.PRICE = newPrice where COFFEES.COF_NAME = coffeeName; select newPrice; END main; end; === Execution of the Installation Scripts === We will [[docs:resource:runtime#execution|execute it]] by: * making it a [[docs:resource:runtime#data uri|runtime data uri]] (ie adding the execution connection) * and [[:docs:tabul:data:execute|executing them it]] tabul data exec \ --processing-type batch \ '(mysql/coffee-break-sample-db/install*.sql@howto)@mysql' # The quotes are only mandatory in bash because parenthesis are a bash token (ie subshell) List of runtime executed runtime_data_uri exit_code count latency data_uri error_message --------------------------------------------------------------------------- --------- ----- ------- ------------------------------------------------------------------------------------- ------------- (mysql/coffee-break-sample-db/install-01-create-tables.sql@howto)@mysql 0 8 0.180s execute/20251110-204056-896-pipe-tabul-data-exec/install-01-create-tables.log@tmp (mysql/coffee-break-sample-db/install-02-populate-tables.sql@howto)@mysql 0 40 0.152s execute/20251110-204056-896-pipe-tabul-data-exec/install-02-populate-tables.log@tmp (mysql/coffee-break-sample-db/install-03-create-procedures.sql@howto)@mysql 0 6 0.16s execute/20251110-204056-896-pipe-tabul-data-exec/install-03-create-procedures.log@tmp === Listing the procedures with show procedures === On MySQL, you can list the procedure status with the [[https://dev.mysql.com/doc/refman/8.4/en/show-procedure-status.html|SHOW procedure]] SQL: show procedure status where db = 'howto'; -- https://dev.mysql.com/doc/refman/8.4/en/show-procedure-status.html This statement is in the file `mysql/show-procedure-status.sql` located in the [[:docs:connection:howto|howto connection]] and we can execute it with [[:docs:tabul:data:print|the print command]] tabul data print '(mysql/show-procedure-status.sql@howto)@mysql' # The quotes are only mandatory in bash because parenthesis are a bash token (ie subshell) (mysql/show-procedure-status.sql@howto)@mysql ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE DEFINER LAST_ALTERED CREATED SECURITY_TYPE ROUTINE_COMMENT CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION -------------- ---------------------- ------------ ------- ------------------- ------------------- ------------- --------------- -------------------- -------------------- ------------------ howto GET_SUPPLIER_OF_COFFEE PROCEDURE root@% 2025-11-10T20:40:58 2025-11-10T20:40:58 DEFINER utf8mb4 utf8mb4_general_ci latin1_swedish_ci howto RAISE_PRICE PROCEDURE root@% 2025-11-10T20:40:58 2025-11-10T20:40:58 DEFINER utf8mb4 utf8mb4_general_ci latin1_swedish_ci howto SHOW_SUPPLIERS PROCEDURE root@% 2025-11-10T20:40:58 2025-11-10T20:40:58 DEFINER utf8mb4 utf8mb4_general_ci latin1_swedish_ci ==== Literal Execution of a Procedure ==== In this example, we show you how to call a procedure without any argument that returns a result set. === The literal statement === The statement is: tabul data cat mysql/coffee-break-sample-db/call-show-suppliers.sql@howto call SHOW_SUPPLIERS; where: * ''call'' is the [[https://dev.mysql.com/doc/refman/8.4/en/call.html|MySQL call SQL statement]] * ''SHOW_SUPPLIERS'' is the ''select'' procedure created previously === Execution of the literal statement === We will [[docs:resource:runtime#execution|execute it]] by: * making it a [[docs:resource:runtime#data uri|runtime data uri]] (ie adding the execution connection) * and [[:docs:tabul:data:print|printing it]] tabul data print '(mysql/coffee-break-sample-db/call-show-suppliers.sql@howto)@mysql' # The quotes are only mandatory in bash because parenthesis are a bash token (ie subshell) (mysql/coffee-break-sample-db/call-show-suppliers.sql@howto)@mysql SUP_NAME COF_NAME --------------- ------------------ Acme, Inc. Colombian Acme, Inc. Colombian_Decaf Superior Coffee French_Roast Superior Coffee French_Roast_Decaf The High Ground Espresso ==== Parametrized Execution of a Procedure ==== === The parametrized statement === The [[:docs:system:database:sql_statement|SQL statement]] to execute a [[:docs:system:database:sql_procedure|sql procedure]] is: { call GET_SUPPLIER_OF_COFFEE(?,?) } -- To use an OUT parameter (ie the first ? parameter), the expression should be escaped (ie enclosed by { and }) -- Otherwise you get the error: This statement does not declare an OUT parameter. Use { ?= call ... } to declare one It's a [[:docs:system:database:sql_parameterized_statement|parameterized statement]] where: * ''{'' is the start character of a [[:docs:system:database:jdbc_escape|jdbc escape block]] * ''call'' is the [[https://dev.mysql.com/doc/refman/8.4/en/call.html|MySQL Call SQL statement]] that invokes a procedure * ''GET_SUPPLIER_OF_COFFEE( ?, ? )'' is the function with 2 [[:docs:system:database:sql_parameterized_statement#placeholder|sql parameter placeholder]] as input * ''}'' is the end character of a [[:docs:system:database:jdbc_escape|jdbc escape block]] === The Request Data Resource === To make this [[:docs:system:database:sql_statement|statement]] [[docs:resource:runtime|executable]], we need to create a [[:docs:resource:sql_request#manifest|sql request manifest]] so that we can define the [[:docs:system:database:sql_parameterized_statement#parameters|parameters]] The signature of the procedure as seen in the [[#the_create_procedure_statements|SQL file]] is: ```sql create procedure GET_SUPPLIER_OF_COFFEE(IN coffeeName varchar(32), OUT supplierName varchar(40)) ``` It has 2 parameters: - ''IN'' parameter ''coffeeName'' - ''OUT'' parameter ''supplierName'' You pass a ''coffeeName'' and you get a ''supplierName''. We define them in the below [[:docs:resource:sql_request#manifest|sql request manifest]]. kind: sql-request spec: # the executable data uri # * takes the sql file (call-get-supplier-of-coffee.sql) # * located in the same directory as this manifest (md) # * and execute it against (mysql) data-uri: (call-get-supplier-of-coffee.sql@md)@mysql # the data definition data-def: parameters: # the parameter for the first placeholder - direction: in # retrieve the value type: varchar # the type of the retrieved value value: Colombian # the value passed to the GET_SUPPLIER_OF_COFFEE function # the parameter for the second placeholder - direction: out # set the value type: varchar # the type of the value === The execution === We will [[docs:resource:runtime#execution|execute]] this [[:docs:resource:manifest|manifest]] by [[:docs:tabul:data:print|printing]] it tabul data print mysql/coffee-break-sample-db/call-get-supplier-of-coffee--sql-request.yml@howto Output: (call-get-supplier-of-coffee.sql@md)@mysql supplierName ------------ Acme, Inc. ==== Next ==== That's it. You should have learned how to call a [[:docs:system:database:sql_procedure|SQL Procedure]] in MySQL.