I'm running Workbench 5.2.47.
I have a long procedure I wrote with basic data checking. If a record did not exist in the database, the record would be inserted.
The procedure saved with no problems, but MySQL 5.5 throws an error when I try running it.
It is long, and has a lot of company sensitive data in it, or I would post it here.
I am trying to debug the procedure by executing small chunks of the code, but I can't seem to get Workbench to allow anything I try.
MySQL shows how to create a stored procedure in 5.1.5 Working with Stored Procedures.
Let me show you something very basic I am trying to write:
DELIMITER $$
DROP PROCEDURE IF EXISTS my_test;
CREATE PROCEDURE my_test()
BEGIN
SELECT * FROM Employees;
END $$
DELIMITER ;
With that, Workbench gives me the error, "syntax error, unexpected CREATE, expecting $end".
I don't understand that, but I need to get something done, so I am moving on.
I make a simpler query:
SET #Count=(SELECT Count(*) FROM tbl_object_users WHERE username='jp2code');
IF (#Count < 1) THEN
INSERT INTO tbl_object_users (username, date_time) VALUES ('jp2code', NOW());
END IF;
Again, I get an error, this time on my IF statement.
Next, I go into PhpMyAdmin to try running something from there using its database:
SET #Count=Count(id) FROM `tbl_object_users` WHERE `username`='jp2code';
It, too, tells me I have an error in my SQL syntax.
I did download and install the newest Workbench 6, but it did not solve the problem - and I did not like the interface, so I uninstalled it and went back to Workbench 5.2.
What is going on? SQL isn't that hard, so what is with these hurdles?
Problem with this:
DELIMITER $$
DROP PROCEDURE IF EXISTS my_test;
CREATE PROCEDURE my_test() ...
is that MySQL isn't seeing the semicolon at the end of the DROP PROCEDURE statement line as the end of the statement. This is because the preceding line told MySQL that the statement terminator was something other than a semicolon. You told MySQL that statements were going to be terminated with two dollar signs. So MySQL is reading the DROP PROCEDURE line, looking for the statement terminator. And the whole blob it reads is NOT a valid MySQL statement, it generates a syntax error.
The fix: either move the DROP PROCEDURE line before the DELIMITER $$ line; or terminate the DROP PROCEDURE statement with the specified delimiter rather than a semicolon.
The second problem you report is a syntax error. That's occurring because MySQL doesn't recognize IF as the beginning of a valid SQL statement.
The IF statement is valid only within the context of a MySQL stored program (for example, within a CREATE PROCEDURE statement.)
The fix: Use an IF statement only within the context of a MySQL stored program.
The third problem you report is also a syntax error. That's occurring because you don't have a valid syntax for a SET statement; MySQL syntax for SET statement to assign a value to user variable is:
SET #uservar = expr
MySQL is expecting an expression after the equals sign. MySQL is not expecting a SQL statement.
To assign a value to a user variable as the result from a SELECT statement, do the assignment within the SELECT statement, for example:
SELECT #Count := Count(id) FROM `tbl_object_users` WHERE `username`='jp2code'
Note that the assignment operator inside the SELECT statement is := (colon equals), not just =.
try this
DELIMITER $$
DROP PROCEDURE IF EXISTS my_test$$
CREATE PROCEDURE my_test()
BEGIN
SELECT * FROM `customer_to_pay`;
END $$
DELIMITER ;
I often see people are using Delimiters. I tried myself to find out what are delimiters and what is their purpose. After 20 minutes of googling, I was not able to find an answer which satisfies me. So, my question is now: What are delimiters and when should I use them?
Delimiters other than the default ; are typically used when defining functions, stored procedures, and triggers wherein you must define multiple statements. You define a different delimiter like $$ which is used to define the end of the entire procedure, but inside it, individual statements are each terminated by ;. That way, when the code is run in the mysql client, the client can tell where the entire procedure ends and execute it as a unit rather than executing the individual statements inside.
Note that the DELIMITER keyword is a function of the command line mysql client (and some other clients) only and not a regular MySQL language feature. It won't work if you tried to pass it through a programming language API to MySQL. Some other clients like PHPMyAdmin have other methods to specify a non-default delimiter.
Example:
DELIMITER $$
/* This is a complete statement, not part of the procedure, so use the custom delimiter $$ */
DROP PROCEDURE my_procedure$$
/* Now start the procedure code */
CREATE PROCEDURE my_procedure ()
BEGIN
/* Inside the procedure, individual statements terminate with ; */
CREATE TABLE tablea (
col1 INT,
col2 INT
);
INSERT INTO tablea
SELECT * FROM table1;
CREATE TABLE tableb (
col1 INT,
col2 INT
);
INSERT INTO tableb
SELECT * FROM table2;
/* whole procedure ends with the custom delimiter */
END$$
/* Finally, reset the delimiter to the default ; */
DELIMITER ;
Attempting to use DELIMITER with a client that doesn't support it will cause it to be sent to the server, which will report a syntax error. For example, using PHP and MySQLi:
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$result = $mysqli->query('DELIMITER $$');
echo $mysqli->error;
Errors with:
You have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near 'DELIMITER $$' at line 1
The DELIMITER statement changes the standard delimiter which is semicolon ( ;) to another. The delimiter is changed from the semicolon( ;) to double-slashes //.
Why do we have to change the delimiter?
Because we want to pass the stored procedure, custom functions etc. to the server as a whole rather than letting mysql tool to interpret each statement at a time.
When you create a stored routine that has a BEGIN...END block, statements within the block are terminated by semicolon (;). But the CREATE PROCEDURE statement also needs a terminator. So it becomes ambiguous whether the semicolon within the body of the routine terminates CREATE PROCEDURE, or terminates one of the statements within the body of the procedure.
The way to resolve the ambiguity is to declare a distinct string (which must not occur within the body of the procedure) that the MySQL client recognizes as the true terminator for the CREATE PROCEDURE statement.
You define a DELIMITER to tell the mysql client to treat the statements, functions, stored procedures or triggers as an entire statement. Normally in a .sql file you set a different DELIMITER like $$. The DELIMITER command is used to change the standard delimiter of MySQL commands (i.e. ;). As the statements within the routines (functions, stored procedures or triggers) end with a semi-colon (;), to treat them as a compound statement
we use DELIMITER. If not defined when using different routines in the same file or command line, it will give syntax error.
Note that you can use a variety of non-reserved characters to make your own custom delimiter. You should avoid the use of the backslash (\) character because that is the escape character for MySQL.
DELIMITER isn't really a MySQL language command, it's a client command.
Example
DELIMITER $$
/*This is treated as a single statement as it ends with $$ */
DROP PROCEDURE IF EXISTS `get_count_for_department`$$
/*This routine is a compound statement. It ends with $$ to let the mysql client know to execute it as a single statement.*/
CREATE DEFINER=`student`#`localhost` PROCEDURE `get_count_for_department`(IN the_department VARCHAR(64), OUT the_count INT)
BEGIN
SELECT COUNT(*) INTO the_count FROM employees where department=the_department;
END$$
/*DELIMITER is set to it's default*/
DELIMITER ;
I am having a strange problem with MySQL Stored Procedure.
I have written a simple stored procedure as follows:
{
DELIMITER $$
CREATE DEFINER=`username`#`%` PROCEDURE `sp_create_my_log`(IN source TEXT,
OUT my_id INT)
BEGIN
--
-- insert record and return primary key
INSERT INTO my_log (source) VALUES (source);
SET my_id = LAST_INSERT_ID();
COMMIT;
END
}
This stored procedure is running absolutely fine on my local machine (MySQL Server 5.1, Windows XP). But when I try to run it on the server, I get the following error:
java.sql.SQLException: Parameter index of 2 is out of range (1, 0)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
at com.mysql.jdbc.CallableStatement$CallableStatementParamInfo.checkBounds(CallableStatement.java:274)
at com.mysql.jdbc.CallableStatement.checkParameterIndexBounds(CallableStatement.java:710)
at com.mysql.jdbc.CallableStatement.checkIsOutputParam(CallableStatement.java:672)
at com.mysql.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:1846)
at org.apache.commons.dbcp.DelegatingCallableStatement.registerOutParameter(DelegatingCallableStatement.java:95)
at org.apache.commons.dbcp.DelegatingCallableStatement.registerOutParameter(DelegatingCallableStatement.java:95)
at com.mycomp.myprj.importer.ImporterImpl.onPreLoad(ImporterImpl.java:160)
at com.mycomp.myprj.importer.csv.FileImporter.load(FileImporter.java:43)
at com.mycomp.myprj.importer.csv.MyImporter.main(MyImporter.java:82)
0.843 seconds
Any idea why this is happening?
Just a wild guess (I'm more an Oracle than a MySQL kind of guy):
- Did you perhaps declare your parameter in Java wrong? (my_id is declared as an out parameter in the stored procedure, do the signatures in Java and MySQL match?)
- What happens if you call your procedure from the MySQL command line interface?
Kind regards, Frank
My current process for debugging stored procedures is very simple. I create a table called "debug" where I insert variable values from the stored procedure as it runs. This allows me to see the value of any variable at a given point in the script, but is there a better way to debug MySQL stored procedures?
The following debug_msg procedure can be called to simply output a debug message to the console:
DELIMITER $$
DROP PROCEDURE IF EXISTS `debug_msg`$$
DROP PROCEDURE IF EXISTS `test_procedure`$$
CREATE PROCEDURE debug_msg(enabled INTEGER, msg VARCHAR(255))
BEGIN
IF enabled THEN
select concat('** ', msg) AS '** DEBUG:';
END IF;
END $$
CREATE PROCEDURE test_procedure(arg1 INTEGER, arg2 INTEGER)
BEGIN
SET #enabled = TRUE;
call debug_msg(#enabled, 'my first debug message');
call debug_msg(#enabled, (select concat_ws('','arg1:', arg1)));
call debug_msg(TRUE, 'This message always shows up');
call debug_msg(FALSE, 'This message will never show up');
END $$
DELIMITER ;
Then run the test like this:
CALL test_procedure(1,2)
It will result in the following output:
** DEBUG:
** my first debug message
** DEBUG:
** arg1:1
** DEBUG:
** This message always shows up
I do something very similar to you.
I'll usually include a DEBUG param that defaults to false and I can set to true at run time. Then wrap the debug statements into an "If DEBUG" block.
I also use a logging table with many of my jobs so that I can review processes and timing. My Debug code gets output there as well. I include the calling param name, a brief description, row counts affected (if appropriate), a comments field and a time stamp.
Good debugging tools is one of the sad failings of all SQL platforms.
How to debug a MySQL stored procedure.
Poor mans debugger:
Create a table called logtable with two columns, id INT and log VARCHAR(255).
Make the id column autoincrement.
Use this procedure:
delimiter //
DROP PROCEDURE `log_msg`//
CREATE PROCEDURE `log_msg`(msg VARCHAR(255))
BEGIN
insert into logtable select 0, msg;
END
Put this code anywhere you want to log a message to the table.
call log_msg(concat('myvar is: ', myvar, ' and myvar2 is: ', myvar2));
It's a nice quick and dirty little logger to figure out what is going on.
Yes, there is a specialized tools for this kind of thing - MySQL Debugger.
There are GUI tools for debugging stored procedures / functions and scripts in MySQL. A decent tool that dbForge Studio for MySQL, has rich functionality and stability.
Debugger for mysql was good but its not free. This is what i use now:
DELIMITER GO$
DROP PROCEDURE IF EXISTS resetLog
GO$
Create Procedure resetLog()
BEGIN
create table if not exists log (ts timestamp default current_timestamp, msg varchar(2048)) engine = myisam;
truncate table log;
END;
GO$
DROP PROCEDURE IF EXISTS doLog
GO$
Create Procedure doLog(in logMsg nvarchar(2048))
BEGIN
insert into log (msg) values(logMsg);
END;
GO$
Usage in stored procedure:
call dolog(concat_ws(': ','#simple_term_taxonomy_id', #simple_term_taxonomy_id));
usage of stored procedure:
call resetLog ();
call stored_proc();
select * from log;
Another way is presented here
http://gilfster.blogspot.co.at/2006/03/debugging-stored-procedures-in-mysql.html
with custom debug mySql procedures and logging tables.
You can also just place a simple select in your code and see if it is executed.
SELECT 'Message Text' AS `Title`;
I got this idea from
http://forums.mysql.com/read.php?99,78155,78225#msg-78225
Also somebody created a template for custom debug procedures on GitHub.
See here
http://www.bluegecko.net/mysql/debugging-stored-procedures/
https://github.com/CaptTofu/Stored-procedure-debugging-routines
Was mentioned here
How to catch any exception in triggers and store procedures for mysql?
I'm late to the party, but brought more beer:
http://ocelot.ca/blog/blog/2015/03/02/the-ocelotgui-debugger/
and
https://github.com/ocelot-inc/ocelotgui
I tried, and it seems pretty stable, supporting Breakpoints and Variable inspection.
It's not a complete suite (just 4,1 Mb) but helped me a lot!
How it works:
It integrates with your mysql client (I'm using Ubuntu 14.04), and after you execute:
$install
$setup yourFunctionName
It installs a new database at your server, that control the debugging process. So:
$debug yourFunctionName('yourParameter')
will give you a chance to step by step walk your code, and "refreshing" your variables you can better view what is going on inside your code.
Important Tip: while debugging, maybe you will change (re-create the procedure). After a re-creation, execute: $exit and $setup before a new $debug
This is an alternative to "insert" and "log" methods.
Your code remains free of additional "debug" instructions.
Screenshot:
I just simply place select statements in key areas of the stored procedure to check on current status of data sets, and then comment them out (--select...) or remove them before production.
MySQL Connector/Net 6.6 has a feature to Debug Stored Procedures and Functions
Installing the Debugger
To enable the stored procedure debugger:
For Connector/Net 6.6: Install Connector/Net 6.6 and choose the Complete option.
For Connector/Net 6.7 and later: Install the product MySQL for Visual Studio, to which the stored procedure debugger belongs.
Starting the Debugger
To start the debugger, follow these steps:
Choose a connection in the Visual Studio Server Explorer.
Expand the Stored Procedures folder. Only stored procedures can be debugged directly. To debug a user-defined function, create a stored
procedure that calls the function.
Click on a stored procedure node, then right-click and from the context menu choose Debug Routine.
MySql Connector/NET also includes a stored procedure debugger integrated in visual studio as of version 6.6,
You can get the installer and the source here:
http://dev.mysql.com/downloads/connector/net/
Some documentation / screenshots:
https://dev.mysql.com/doc/visual-studio/en/visual-studio-debugger.html
You can follow the annoucements here:
http://forums.mysql.com/read.php?38,561817,561817#msg-561817
UPDATE: The MySql for Visual Studio was split from Connector/NET into a separate product, you can pick it (including the debugger) from here https://dev.mysql.com/downloads/windows/visualstudio/1.2.html (still free & open source).
DISCLAIMER: I was the developer who authored the Stored procedures debugger engine for MySQL for Visual Studio product.
The first and stable debugger for MySQL is in dbForge Studio for MySQL
I had use two different tools to debug procedures and functions:
dbForge - many functional mysql GUI.
MyDebugger - specialized tool for debugging ... handy tool for debugging.vote http://tinyurl.com/voteimg
MySQL user defined variable (shared in session) could be used as logging output:
DELIMITER ;;
CREATE PROCEDURE Foo(tableName VARCHAR(128))
BEGIN
SET #stmt = CONCAT('SELECT * FROM ', tableName);
PREPARE pStmt FROM #stmt;
EXECUTE pStmt;
DEALLOCATE PREPARE pStmt;
-- uncomment after debugging to cleanup
-- SET #stmt = null;
END;;
DELIMITER ;
call Foo('foo');
select #stmt;
will output:
SELECT * FROM foo
Toad mysql. There is a freeware version
http://www.quest.com/toad-for-mysql/
Answer corresponding to this by #Brad Parks
Not sure about the MySQL version, but mine was 5.6, hence a little bit tweaking works:
I created a function debug_msg which is function (not procedure) and returns text(no character limit) and then call the function as SELECT debug_msg(params) AS my_res_set, code as below:
CREATE DEFINER=`root`#`localhost` FUNCTION `debug_msg`(`enabled` INT(11), `msg` TEXT) RETURNS text CHARSET latin1
READS SQL DATA
BEGIN
IF enabled=1 THEN
return concat('** DEBUG:', "** ", msg);
END IF;
END
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `proc_func_call`(
IN RegionID VARCHAR(20),
IN RepCurrency INT(11),
IN MGID INT(11),
IN VNC VARCHAR(255)
)
BEGIN
SET #enabled = TRUE;
SET #mainQuery = "SELECT * FROM Users u";
SELECT `debug_msg`(#enabled, #mainQuery) AS `debug_msg1`;
SET #lastQuery = CONCAT(#mainQuery, " WHERE u.age>30);
SELECT `debug_msg`(#enabled, #lastQuery) AS `debug_msg2`;
END $$
DELIMITER