【问题标题】:Dynamic Querying with Pandas and pyodbc - Looking for non-string method solution使用 Pandas 和 pyodbc 进行动态查询 - 寻找非字符串方法解决方案
【发布时间】:2017-11-17 02:57:33
【问题描述】:

我正在编写一个脚本来动态查询 MS Access 数据库并将结果返回到 pandas 数据框。将有两个参数会动态更改查询。我使用字符串格式化方法整理了以下解决方案。虽然此解决方案有效,但我正在寻找一种不使用字符串方法的更安全的解决方案。感谢您可以分享的任何知识!

谢谢。

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)

【问题讨论】:

  • 为什么您认为您当前的方法不安全?数组的实际内容仍然作为参数传递。您对字符串函数所做的唯一事情就是为每个IN 设置参数数量。您有什么具体的想法可以防止吗?
  • 只有参数是用户输入的时候才需要担心。所以你需要确保他们的条目是有效的条目并且不受sql注入的影响。
  • 作为数据库查询的新手,我偶然发现了很多关于 sql 注入的“热情”讨论。由于我的解决方案使用字符串方法来解析查询,我想我陷入了一些“分析瘫痪”。
  • 感谢 cmets,所以只要是我自己的程序生成字符串,而不是用户,就可以了。同样,如果参数是用户输入,我需要某种过滤器来防止这种情况发生。
  • 我想恭敬地不同意@krishKM。考虑这样一种情况,您的程序从 CSV、数据库或 API 中提取数据并包含字符串 in Bob's car - 不是来自用户输入,而是来自数据源。它包含一个单引号。虽然这可能不是灾难性的,但由于单引号,它仍然会产生错误。我已经看到过去使用的直接攻击媒介较少,也以非常邪恶的方式使用。 SQL 注入是一个没有正确答案的复杂主题(尽管有很多错误答案),因为通常需要考虑时间与可接受的风险。

标签: python-3.x pandas ms-access pyodbc


【解决方案1】:

考虑使用临时表 items1items2 来保存您的 item 值,然后简单地加入 pandas 导入。事实上,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)
'''

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多