2011-01-27 16 views
7

estoy usando pyodbc a consulta a una base de datos SQL ServerSQL en el operador usando pyodbc y SQL Server

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)) 

pero estoy recibiendo el error abajo. ¿El parámetro de tupla necesita ser manejado de una manera diferente? ¿Hay una mejor manera de estructurar esta consulta?

('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)") 

ACTUALIZACIÓN:

que era capaz de conseguir esta consulta a trabajar usando el operador de la cadena de formato, que no es ideal, ya que presenta problemas de seguridad.

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)) 

Respuesta

12

No se puede parametrizar varios valores en una cláusula IN() utilizando un único parámetro de cadena. La única manera de lograr eso es:

  1. Sustitución de cadenas (como lo hizo).

  2. Cree una consulta parametrizada en el formulario IN (?, ?, . . ., ?) y luego pase en un parámetro por separado para cada marcador de posición. No soy un experto en Python para ODBC, pero me imagino que esto es particularmente fácil de hacer en un lenguaje como Python. Esto es más seguro porque obtiene el valor completo de la parametrización.

+1

Para su segunda opción, sería necesario crear dinámicamente la declaración SQL en función del tamaño de la tupla deseada para pasar a la instrucción IN? – user338714

+1

Puede hacer algo como: cursor.execute ("SELECT * FROM películas DONDE calificación IN ({})". format (','. join ('?' * len (ratings))) , calificaciones) – rleelr

2

El problema es tu tupla. La conexión ODBC espera una cadena para construir la consulta y está enviando una tupla de python. Y recuerde que debe obtener la cita de la cuerda correcta. Supongo que el número de clasificaciones que buscará varía. Probablemente haya una mejor manera, pero mi pyodbc tiende a ser simple y directo.

intente lo siguiente:

import datetime 
import pyodbc  
conn = pyodbc.connect("Driver={SQL Server};Server='dbserver',Database='db', 
         TrustedConnection=Yes") 

def List2SQLList(items): 
    sqllist = "%s" % "\",\"".join(items) 
    return sqllist 


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 ?""", 
       List2SQLList(ratings), str(st_dt), str(end_dt)) 
+0

I' m sigue recibiendo un error de "sintaxis incorrecta" para el primer parámetro. ¿Podría pyodbc tratar la lista como una cadena en lugar de una lista? – user338714

+0

Está poniendo alrededor de toda la cadena. Vea mi edición – WombatPM

+0

Todavía recibo un error de parámetro. Encontré una forma de hacer que la consulta funcionara usando el operador de formato de cadena (vea mi actualización más arriba), y desde este código solo se ejecutará localmente, probablemente se pasen por alto las preocupaciones de seguridad. Creo que cursor.executemany puede ser otra opción. – user338714

11

Para ampliar segunda opción de Larry - la creación dinámica de una cadena parametrizada, que utilizó la siguiente éxito:

placeholders = ",".join("?" * len(code_list)) 
sql = "delete from dbo.Results where RESULT_ID = ? AND CODE IN (%s)" % placeholders 
params = [result_id] 
params.extend(code_list) 
cursor.execute(sql, params) 

dicta la siguiente SQL con los parámetros adecuados:

delete from dbo.Results where RESULT_ID = ? AND CODE IN (?,?,?) 
Cuestiones relacionadas