Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, MySQLdb and escaping table names?

I may be missing something obvious, but I can't figure out how my code is different from various examples I see in the online documentation for MySQLdb.

I'm fairly new to programming python, more experienced with perl. What I'm trying to do is get into certain good habits early on (like in perl I always start with 'use strict; use warnings'), so I'm trying to ensure I create re-usable functions in an independent file (funct.py) to save me time later on down the line.

I've got this function for selecting random rows from a table:

def returnRandom(conn,countcol,table,field):
    cursor = conn.cursor()
    cursor.execute('SELECT MAX(%s) FROM %s',(countcol,table))
    maxRow = cursor.fetchone()[0]
    cursor.execute("SELECT MIN(%s) FROM %s",(countcol,table))
    minRow = cursor.fetchone()[0]
    randomId = random.randrange(minRow,maxRow+1,1)
    cursor.execute("SELECT ? FROM ? WHERE id >=? LIMIT 1",field,table,randomId)
    return cursor.fetchone()[0]

It's being called like this:

msg = funct.returnRandom(conn,"id","testtable","data")

Unfortunately it errors out with: _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 ''testtable'' at line 1")

If I put testtable in in place of the %s on the execute line, The query will run but it looks like it runs

SELECT MAX('id') FROM testtable;

which of course returns 'id'.

Given both of those it looks like it's quoting the %s entries when it tries to execute them. I was wondering if anyone could explain how I get it to stop doing that, or how I should actually being doing what I'm trying to achieve? I want the function to be as generic as possible, so relying on data being passed to it by when it's called.

edit: I should add, if I substitute in ? marks:

....
    cursor.execute('SELECT MAX(?) FROM ?',(countcol,table))
File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 151, in execute
    query = query % db.literal(args)
TypeError: not all arguments converted during string formatting
like image 805
Twirrim Avatar asked Jul 07 '11 23:07

Twirrim


People also ask

What is MYSQLdb in Python?

What is MYSQLdb? MySQLdb is an interface for connecting to a MySQL database server from Python. It implements the Python Database API v2. 0 and is built on top of the MySQL C API.

How to Insert multiple rows in sql using python?

To insert multiple rows into a table, use the executemany() method.


1 Answers

You cannot use DB-API for metadata; you will need to make replacements yourself outside of the execute() call.

query = 'SELECT MAX(%%s) FROM `%s`' % (table,)
cursor.execute(query, (countcol,))

Obviously you should not do this if table comes from an outside source.

like image 93
Ignacio Vazquez-Abrams Avatar answered Oct 13 '22 01:10

Ignacio Vazquez-Abrams