2017-11-17 10 views
0

私はMS Accessデータベースを動的にクエリし、結果をpandasデータフレームに返すスクリプトを作成しています。動的にクエリを変更する2つのパラメータがあります。文字列の書式設定メソッドを使用して、次のソリューションをまとめました。このソリューションは機能しますが、私は文字列メソッドを使用しないより安全なソリューションを探しています。あなたが共有できる知識を評価してください!Pandasとpyodbcによる動的クエリ - 文字列以外のメソッドの解決を探しています

ありがとうございます。

values1 = ('1','2') 
values2 = ('1','2','3') 

ServerName = r'pathtodb\\database.mdb' 
connStr = 'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=%s;' %ServerName 
cnxn = pyodbc.connect(connStr) 
query = 'SELECT * FROM TABLE WHERE item in ({0}) and item2 in ({1})' 
query = query.format(','.join('?' * len(values1)), ','.join('?' * len(values2))) 
param_list = values1 + values2 
df = pd.read_sql_query(query, cnxn, params=param_list) 
print(df) 
+2

は、なぜあなたは、あなたの現在の方法が安全でないと思いますか?配列の実際の内容は引き続きパラメータとして渡されます。文字列関数で唯一行うことは、各 'IN'のパラメータ数を設定することです。私たちが防ぐことができることを念頭に置いていますか? –

+1

パラメータが入力フォームユーザであるときだけ心配する必要があります。だからあなたは、彼らのエントリーがSQLインジェクションの有効なエントリーであることを確認する必要があります。 –

+0

データベースクエリに新しいので、SQLインジェクションに関する多くの "情熱的な"ディスカッションを偶然見つけました。私のソリューションは文字列メソッドを使用してクエリを解析するので、私は考えている "分析麻痺"のビットに入りました。 – davetunes

答えて

1

はあなたアイテム値を保持して、簡単にパンダのインポートのために参加するために、占める特別項目1と items2 、一時テーブルを使用することを検討してください。実際にはJOINのアプローチは、IN()節の長いリストより効率的です。

values1 = ('1','2') 
values2 = ('1','2','3') 

ServerName = r'C:\pathtodb\database.mdb' 
connStr = 'DRIVER={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={0};'.format(ServerName) 
cnxn = pyodbc.connect(connStr) 

cur = cnxn.cursor() 

# CLEAN OUT OLD DATA AND APPEND NEW DATA 
cur.execute('DELETE FROM items1') 
cnxn.commit() 
cur.executemany('INSERT INTO items1 ([item]) VALUES (?)', values1) 
cnxn.commit() 

cur.execute('DELETE FROM items2') 
cnxn.commit() 
cur.executemany('INSERT INTO items2 ([item]) VALUES (?)', values2) 
cnxn.commit() 

# IMPORT JOIN QUERY INTO PANDAS (PARENTHESES ARE REQUIRED) 
query = '''SELECT * FROM (TABLE t 
     INNER JOIN items1 i1 ON t.[item] = i1.[item]) 
     INNER JOIN items2 i2 ON t.[item2] = i2.[item] 
''' 

df = pd.read_sql_query(query, cnxn) 
print(df) 

代替クエリ:

query = '''SELECT * FROM TABLE 
     WHERE item IN (SELECT [item] FROM items1) 
      AND item2 IN (SELECT [item] FROM items2) 
''' 
関連する問題