13

I understand that the correct way to format a sql query in Python is like this:

cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", var1, var2, var3)

so that it prevents sql injection. My question is if there is a way to put the query in a variable and then execute it? I have tried the example below but receive an error. Is it possible to do this?

sql="INSERT INTO table VALUES (%s, %s, %s)", var1, var2, var3
cursor.execute(sql)

4 Answers 4

28

Here is the call signature for cursor.execute:

Definition: cursor.execute(self, query, args=None)

    query -- string, query to execute on server
    args -- optional sequence or mapping, parameters to use with query.

So execute expects at most 3 arguments (args is optional). If args is given, it is expected to be a sequence. so

sql_and_params = "INSERT INTO table VALUES (%s, %s, %s)", var1, var2, var3
cursor.execute(*sql_and_params)

is not going to work, because

cursor.execute(*sql_and_params)

expands the tuple sql_and_params into 4 arguments (and again, execute only expects 3).

If you really must use

sql_and_params = "INSERT INTO table VALUES (%s, %s, %s)", var1, var2, var3

then you'll have to break it apart when feeding it to cursor.execute:

cursor.execute(sql_and_params[0],sql_and_params[1:])

But I think it feels much more pleasant to just use two variables:

sql = "INSERT INTO table VALUES (%s, %s, %s)"
args= var1, var2, var3
cursor.execute(sql, args)
Sign up to request clarification or add additional context in comments.

Comments

6

You're pretty close.

sql_and_params = "INSERT INTO table VALUES (%s, %s, %s)", var1, var2, var3
cursor.execute(*sql_and_params)

The asterisk means that the variable isn't to be considered as one parameter but instead unpacked into many parameters.

2 Comments

why did you use , instead of %? For example to do this: sql_and_params = "INSERT INTO table VALUES (%s, %s, %s)" % (var1, var2, var3)
@bzupnick using simple string formatting (the % operator), or substitution, would potentially allow SQL injection, not to mention failing to add quotation marks to the literals if needed. Parameterized queries are highly superior to formatted/substituted queries.
1

This worked for me. Querying Microsoft SQL Server using pyodbc.

cusotmer_list = ['ABC', '123']

# parameterized query placeholders
placeholders = ",".join("?" * len(customer_list))

# query table
query = 
"""
SELECT
[ID],
[Customer]
FROM xyz.dbo.abc
WHERE [Customer] IN (%s)
""" % placeholders

# read query results in pandas dataframe
df = pd.read_sql(sql=query, con=cnxn, params=customer_list)

Comments

1

the best way for pass parameters to SQL query in Python is:

"INSERT INTO table VALUES (:1, :2, :3)  ", [val1, val2, val3]

or another example:

"UPDATE table T SET T.column2 = :1 where T.column1= :2 ", [val1,val2]

Comments

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.