I’m using pyodbc to query to an SQL Server database
import datetime import pyodbc conn = pyodbc.connect("Driver={SQL Server};Server='dbserver',Database='db', TrustedConnection=Yes") cursor = conn.cursor() ratings = ("PG-13", "PG", "G") st_dt = datetime(2010, 1, 1) end_dt = datetime(2010, 12, 31) cursor.execute("""Select title, director, producer From movies Where rating In ? And release_dt Between ? And ?""", ratings, str(st_dt), str(end_dt))
but am receiving the error below. Does the tuple parameter need to be handled in a different way? Is there a better way to structure this query?
('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Line 9: Incorrect syntax near '@P1'. (170) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server] Statement(s) could not be prepared. (8180)")
UPDATE:
I was able to get this query to work using the string formatting operator, which isn’t ideal as it introduces security concerns.
import datetime import pyodbc conn = pyodbc.connect("Driver={SQL Server};Server='dbserver',Database='db', TrustedConnection=Yes") cursor = conn.cursor() ratings = ("PG-13", "PG", "G") st_dt = datetime(2010, 1, 1) end_dt = datetime(2010, 12, 31) cursor.execute("""Select title, director, producer From movies Where rating In %s And release_dt Between '%s' And '%s'""" % (ratings, st_dt, end_dt))
Advertisement
Answer
You cannot parameterize multiple values in an IN ()
clause using a single string parameter. The only way to accomplish that is:
String substitution (as you did).
Build a parameterized query in the form
IN (?, ?, . . ., ?)
and then pass in a separate parameter for each place holder. I’m not an expert at Python to ODBC but I imagine that this is particularly easy to do in a language like Python. This is safer because you get the full value of parameterization.