Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create function through MySQLdb

Tags:

python

mysql

How can I define a multi-statement function or procedure in using the MySQLdb lib in python?

Example:

import MySQLdb

db = MySQLdb.connect(db='service')

c = db.cursor()

c.execute("""DELIMITER //
CREATE FUNCTION trivial_func (radius float) 
    RETURNS FLOAT

    BEGIN
    IF radius > 1 THEN
        RETURN 0.0;
    ELSE
        RETURN 1.0;
    END IF;
END //

DELIMITER ;""")

Which creates the following traceback:

Traceback (most recent call last):
  File "proof.py", line 21, in <module>
    DELIMITER ;""")
  File "build/bdist.macosx-10.5-i386/egg/MySQLdb/cursors.py", line 173, in execute
  File "build/bdist.macosx-10.5-i386/egg/MySQLdb/connections.py", line 35, in defaulterrorhandler
_mysql_exceptions.ProgrammingError: (1064, "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 //\nCREATE FUNCTION trivial_func (radius float) \n    RETURNS FLOAT\n\n   ' at line 1")

If I copy the same SQL directly into a mysql shell client, it works as expected

like image 975
ʞɔıu Avatar asked Apr 13 '09 21:04

ʞɔıu


People also ask

Can you create functions in MySQL?

MySQL provides a set of built-in function which performs particular tasks for example the CURDATE() function returns the current date. You can create a stored function using the CREATE FUNCTION statement.

How do I create a stored function in MySQL?

First, specify the name of the stored function that you want to create after CREATE FUNCTION keywords. Third, specify the data type of the return value in the RETURNS statement, which can be any valid MySQL data types. Fourth, specify if a function is deterministic or not using the DETERMINISTIC keyword.

How do I run a function in MySQL?

It's very simple to run the MySQL function. Instead of procedure we can add any multiple line function in above example. @Sebastianb, under the "delimiter //" prompt we can call functions as well. using CALL is just an example for reference of procedures.

How do you create a function in MariaDB?

You can create your own function in MariaDB: Syntax: CREATE. [ DEFINER = { CURRENT_USER | user_name } ]


2 Answers

The DELIMITER command is a MySQL shell client builtin, and it's recognized only by that program (and MySQL Query Browser). It's not necessary to use DELIMITER if you execute SQL statements directly through an API.

The purpose of DELIMITER is to help you avoid ambiguity about the termination of the CREATE FUNCTION statement, when the statement itself can contain semicolon characters. This is important in the shell client, where by default a semicolon terminates an SQL statement. You need to set the statement terminator to some other character in order to submit the body of a function (or trigger or procedure).

CREATE FUNCTION trivial_func (radius float) 
    RETURNS FLOAT

    BEGIN
    IF radius > 1 THEN
        RETURN 0.0; <-- does this semicolon terminate RETURN or CREATE FUNCTION?
    ELSE
        RETURN 1.0;
    END IF;
END

Since the API typically allows you to submit one SQL statement at a time, there's no ambiguity -- the interface knows that any semicolons inside the body of your function definition don't terminate the whole CREATE FUNCTION statement. So there's no need to change the statement terminator with DELIMITER.

like image 81
Bill Karwin Avatar answered Sep 28 '22 03:09

Bill Karwin


To add to the answer by Bill Karwin, the following python code sample can be used to properly execute a string where DELIMITER is used, such as a database creation script.

import MySQLdb

db = MySQLdb.connect(db='service')
cursor = db.cursor()

dbString = """DELIMITER //
CREATE FUNCTION trivial_func (radius float) 
RETURNS FLOAT

BEGIN
IF radius > 1 THEN
    RETURN 0.0;
ELSE
    RETURN 1.0;
END IF;
END //

DELIMITER ;"""

# Find special delimiters
delimiters = re.compile('DELIMITER *(\S*)',re.I)
result = delimiters.split(dbString)

# Insert default delimiter and separate delimiters and sql
result.insert(0,';') 
delimiter = result[0::2]
section   = result[1::2]

# Split queries on delimiters and execute
for i in range(len(delimiter)):
    queries = section[i].split(delimiter[i])
    for query in queries:
        if not query.strip():
            continue
        cursor.execute(query)

This will execute one delimited statement at a time, changing delimiters when needed.

like image 21
Aaron Swan Avatar answered Sep 28 '22 05:09

Aaron Swan