Migration of stored procedures and functions from MS SQL to MySQL
Following the trend of shifting from proprietor software to open-source equivalents, many companies and organizations run database migration from Microsoft SQL to MySQL. One of the most complicated steps of the migration procedure is conversion of stored procedures and functions according to syntax of the target database management system.
Although MS SQL and MySQL have similar syntax of stored procedures, there are differences that must be processed properly during migration. This article explores those differences and explains how to handle it.
Structure of Code. SQL Server accepts procedure definitions in the following format:
CREATE PROCEDURE name
arg1 type,
arg2 type,
…
AS
statement1
statement2
…
GO
Unlike Microsoft SQL, MySQL requires procedure body to be enclosed betweenBEGIN and ENDkeywords. So, the stored procedure given as example above must be converted into MySQL format as follows:
CREATE PROCEDURE name (
arg1 type,
arg2 type,
…
)
BEGIN
statement1;
statement2;
…
END;
Passing Parameters.Stored procedures in MS SQL and MySQL accept input and output parameters. SQL Server requires special declaration for output parameters only using keyword OUTPUT, but in MySQL both input and output parameters must be specified withIN and OUT keywords.
IF…THEN…ELSE… Statements. Unlike SQL Server, MySQL requires IF-blocks include THEN keyword and to be finished with END IF; when include more than one statement. Pay attention at the semicolon symbol after END IF, it is required:
IF (expression) THEN
statement1;
statement2;
…
ELSE
statement1;
statement2;
…
END IF;
IF EXISTS Statements. SQL Server provides statement IF EXIST to check whether query returns any rows. For example:
IF EXISTS(SELECT prod_id FROM products WHERE price > 100)
BEGIN
do something
END
MySQL does not support the statement, it must be converted into COUNT(*) function:
IF (SELECT COUNT(*) FROM products WHERE price > 100) > 0 THEN
do something
END IF;
Clauses in SELECT Statements.MS SQL accepts variables in clauses of SELECT-statements, but MySQL requires constants only. The work around is to use PREPARE-statement as it is illustrated on example of the following SQLServer query:
SELECT
a.subject,
a.createdate,
a.views,
a.user
FROM
classifieds a
WHERE
id = “@id”
LIMIT
“@startrow”,”@maxrows”;
The same SELECT-statement with variable clauses can be implemented in MySQL through the following code:
PREPARE STMT FROM
‘select a.subject,
a.createdate,
a.views,
a.user
from classifieds a
where id = ?
limit ?,?’;
EXECUTE STMT USING
“@id”,”@startrow”,”@maxrows”;
Error Handling.Technique of handling errors in SQL Server receives errors below a certain level in system variable @@ERROR while the stored procedure continues. At the same time errors above that level terminates execution immediately and returns the error code. MySQL terminates stored procedures in case of any error and return the corresponding code. To force MySQL error handling act similar toSQL Server it is necessary to define custom error handler as follows:
DECLARE “@ERROR” INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET “@ERROR” = 1;
END;
And the source code of stored procedures must be modified to use @ERROR variable instead of @@ERROR. For example, the original code:
IF @@ERROR <>0 GOTO ERROUT
UPDATE MessageBoardEntries SET ReplyCount = ReplyCount – 1
WHERE EntryID = @EntryID
IF @@ERROR <>0 GOTO ERROUT
UPDATE MessageBoardCategories SET PostCount = PostCount -1
WHERE CategoryID = @CategoryID
IF @@ERROR <>0 GOTO ERROUT
must be replaced with:
DECLARE “@ERROR” INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET “@ERROR” = 1;
END;
INSERT groupmessageboardreplies (
parentid,
authorid,
body )
VALUES (
“@entryid”,
“@authorid”,
“@body” );
IF “@ERROR” = 0 THEN
UPDATE groupmessageboardentries
set replycount = replycount + 1,
lastpostdate = NOW(),
lastposter = “@authorid”
WHERE entryid = “@entryid” ;
END IF
IF “@ERROR” = 0 THEN
UPDATE groupmessageboards
set lastpostdate = NOW(),
postcount = postcount + 1,
lastposterid = “@authorid”,
lastpostentryid = “@entryid”
WHERE groupid = “@groupid” ;
END IF;
StringsConcatenation.MS SQL provides concatenation operator as ‘+’ sign:
SET @result = ‘||’ + @col_value + ‘||’
In default configuration MySQL provides CONCAT() function for the same purpose:
SET result = CONCAT(‘||’, col_value, ‘||’);
Also, MySQL can be run in ANSI mode that supports the same syntax of string concatenation as Microsoft SQL. To set ANSI mode either run mysqld with “–ansi’ option or execute these two statements:
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET GLOBAL sql_mode = ‘ANSI’;
SELECT Into Variables.SQL Server allows selecting query results into local variables through the following syntax:
SELECT @v1 = col1, @v2 = col2 FROM …
For the same purpose MySQL uses the syntax of SELECT queries as follows:
SELECT col1, col2 INTO v1, v2 FROM …
Dynamic SQL.MS SQL provides operator EXEC(@var)to execute dynamic SQL queries through. In MySQL it can be done using the following code:
SET @sess_v = var;
PREPARE stmt FROM @sess_v;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Transactions.MicrosoftSQL provides several statements to handle transactions:
- BEGIN TRANSACTION / TRAN – begin transaction
- COMMIT TRANSACTION / TRAN – commit transaction
- ROLLBACK TRANSACTION / TRAN – rollback transaction
MySQL equivalents of the same statements are: START TRANSACTION, COMMIT, ROLLBACK.