10

I'm trying to compose a string SQL query using SQLALchemy 1.1.2. I followed the explanation from the docs about using textual SQL but encountered a syntax error when I ran the following code:

from sqlalchemy.sql import text

# Create a database connection called "connection"...

q = text('USE :name')
connection.execute(q, name='DATABASE_NAME')

Here's the error message:

"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 ''DATABASE_NAME'' at line 1") [SQL: u'USE %s;'] [parameters: 
(u'DATABASE_NAME',)]

Since I'm using the named colon format and passing the parameters as arguments to connection.execute I can't figure out why this problem is arising. I'm using a MySQL server, but if I read the docs correctly the text method should be DB-agnostic.

Thanks in advance for the help.

3
  • You cannot use a parameter with USE, just like you can't do SELECT * FROM :table. You'll have to string formatting, like 'USE %s' % 'DATABASE_NAME'. Commented Oct 25, 2016 at 21:54
  • I didn't see anything about this in the docs - so you're saying that the text method can compose other types of queries but not USE or SELECT queries? EDIT: I tried it with a SELECT query, like in the docs, and got the same error. Commented Oct 25, 2016 at 21:57
  • 1
    No. What I'm saying is that parameters as used here do not work on table names, only literals. While you can do SELECT * FROM some_table WHERE id > :my_id_param, you cannot do SELECT * FROM :my_table_name_param. Commented Oct 25, 2016 at 22:42

1 Answer 1

4

According to the documentation you need to use the bindparams like so:

q = text('USE :name')
q.bindparams(name="DATABASE_NAME")
connection.execute(q)

or like this:

q = text('USE :name')
q = q.bindparams(bindparam("name", String))

connection.execute(q, {"name": "DATABASE_NAME"})

This worked for me with no issues. Edit: I was wrong, it didn't work.

The problem is the bind params is going to auto wrap your value with a single quote. So what's happening is you get the final compiles statement (which is invalid syntax):

use 'DATABASE_NAME'

If you were to create the query: "Select * from mytable where column_a=:name"; this will work. Because it's wrapping the value with single quotes.

I would suggest for your use statement to do:

q = "USE {}".format("DATABASE_NAME") 

Or something similar.

Sign up to request clarification or add additional context in comments.

8 Comments

Strange. I'm still encountering the error. When I execute the first example, I get this: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'name' [SQL: u'USE %s'] Are you also using v1.1.2?
@jason-heine, can you specify the documentation version, and link (from the anchor text “the documentation” in your answer, if you like).
@bignose I had used the link the OP provided. However, I have updated my answer to include this link as well. Thanks
@JasonHeine Isn't using string formatting to parameterize a SQL query a big security vulnerability? Thanks for following up and updating your answer btw.
@JonathanCox Yes, it can be a security vulnerability. I typically set the database name in the connection, or create the table using classes, and then set the schema there. so table = Table('table_name', MetaData(), Columns, schema='my_database')
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.