14

pyodbcを使用してSQLServerデータベースにクエリを実行しています

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

しかし、以下のエラーを受け取っています。タプルパラメーターを別の方法で処理する必要がありますか?このクエリを構造化するためのより良い方法はありますか?

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

アップデート:

文字列フォーマット演算子を使用してこのクエリを機能させることができましたが、セキュリティ上の懸念があるため理想的ではありません。

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

4 に答える 4

21

Larryの2番目のオプションであるパラメーター化された文字列を動的に作成することを拡張するために、私は以下を正常に使用しました。

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)

適切なパラメータを使用して次のSQLを提供します。

delete from dbo.Results where RESULT_ID = ? AND CODE IN (?,?,?)
于 2013-05-24T10:07:16.320 に答える
18

IN ()単一の文字列パラメータを使用して、句内の複数の値をパラメータ化することはできません。それを達成する唯一の方法は次のとおりです。

  1. 文字列の置換(あなたがしたように)。

  2. フォームにパラメーター化されたクエリを作成し、プレースホルダーごとに個別IN (?, ?, . . ., ?)のパラメーターを渡します。私はPythontoODBCの専門家ではありませんが、Pythonのような言語でこれを行うのは特に簡単だと思います。パラメータ化の完全な値を取得できるため、これはより安全です。

于 2011-01-28T03:37:29.670 に答える
3

ラリーとgeographikaの答えを拡張するには:

ratings = ('PG-13', 'PG', 'G')
st_dt = datetime(2010, 1, 1)
end_dt = datetime(2010, 12, 31)

placeholders = ', '.join('?' * len(ratings))
vars = (*ratings, st_dt, end_dt)
query = '''
    select title, director, producer
    from movies
    where rating in (%s)
       and release_dt between ? and ?
''' % placeholders

cursor.execute(query, vars)

プレースホルダーを使用すると、次のクエリが返されます。

    select title, director, producer
    from movies
    where rating in (?, ?, ?)
       and release_dt between ? and ?

を渡すとratings、すべてのアイテムを1つに収めようとします?。ただし、を渡すと*ratings、の各項目が句ratings内でその場所になります。in()したがって、タプルをに渡し(*ratings, st_dt, end_dt)ますcursor.execute()

于 2019-09-19T14:34:54.877 に答える
2

問題はタプルです。ODBC接続は、クエリを構成する文字列を想定しており、Pythonタプルを送信しています。また、文字列の引用符を正しく取得する必要があることを忘れないでください。あなたが探している評価の数はさまざまだと思います。おそらくもっと良い方法がありますが、私のpyodbcは単純で単純な傾向があります。

次のことを試してください。

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))
于 2011-01-27T19:01:23.120 に答える