【问题标题】:Error fromatting parameter for Pandas read_sql_queryPandas read_sql_query 的参数错误
【发布时间】:2021-04-02 00:33:36
【问题描述】:

在将字符串参数传递到 pd.read_sql_query 时如何解决此错误?使用 Python 2.7。

table = 'mytable1'
query = (
        "SELECT * "
        "FROM ? "
    )
df = pd.read_sql_query(sql=query, con=conn, params=(table))

pandas.io.sql.DatabaseError: Execution failed on sql 'SELECT * FROM ? ': near "?": syntax error

我尝试将? 替换为%%s,但它返回相同的错误。

以下相等示例按预期工作:

query = (
        "SELECT * "
        "FROM mytable1 "
        "WHERE name = ? "
    )
df = pd.read_sql_query(sql=query, con=conn, params=('cat',))

注意params中的逗号好像是必须的,否则返回这个错误:Incorrect number of bindings supplied. The current statement uses 1, and there are 7 supplied.

我也尝试过params=(table,) 我的问题,但没有运气。我知道我也可以使用"FROM '{t}' ").format(t=table) 来执行此操作,但我想了解如何使用 Pandas 的内置参数选项。

【问题讨论】:

  • 也许用%替换?
  • params = [table]?
  • @QuangHoang,是的,同样的错误,这个错误是持久的!
  • Python 中的(table)(table,) 之间存在差异。后者是一个元组,而formal是一个字符串,即table
  • @QuangHoang 是的,但文档说它可以采用列表或元组!

标签: python sql pandas parameters


【解决方案1】:

问题在于params 旨在替换值,而不是 SQL 关键字(FROMSELECT 等)或表或列。

你不能这样指定表,你必须使用字符串替换。

query = (
        f"SELECT * "
        "FROM {table} "
    )

但是,要非常、非常、非常小心。这样做,而不是使用参数,你会发现一大堆漏洞,SQL Injections

如果您从外部来源获取表名,请不要这样做。

(哦,这个限制的可能原因是,除了出于安全原因绝对必要之外,参数化查询允许数据库引擎检查查询、查看索引、统计信息等所有内容并制定“执行计划” "。随后的调用可以重用该执行计划并仅替换新变量。如果查询在访问哪些表和列方面发生变化,则无法做到这一点。)

【讨论】:

  • 有道理,我开始怀疑了。字符串格式是否减轻了注入问题,尽管 * ?换句话说,query = ("SELECT * FROM '{table}' ").format(table=t) 好吗?
  • 不是,不是。您可以提前指定正则表达式测试,例如table 上的 re.match('[A-Za-z0-9_]+')。这应该让你保持安全,因为它避免了嵌入引号之类的小技巧。但是有图书馆可以做到这一点。尽管如此,只要有可能,就使用参数化查询而不是测试用户输入的安全性。碰巧你不能在这里。
  • @QuangHoang 是的,因为我已经在答案中提到了两次。这不会改变您不能使用参数化查询指定 SQL 关键字或模式对象的事实。 OP 的用例是否证明了风险是由他们决定的。
  • 请放心,风险可忽略不计 :) 尝试编写将成分与食谱和关系数据库相匹配的脚本似乎是可行的方法。我不专业地使用数据库,但出于普遍的好奇心,我喜欢了解正确和错误方式之间的区别(例如 SQL 注入问题)。
猜你喜欢
  • 2018-06-25
  • 2016-08-18
  • 1970-01-01
  • 2015-12-27
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多