【问题标题】:Python PYODBC INSERT - Too Few ParametersPython PYODBC INSERT - 参数太少
【发布时间】:2017-09-12 21:40:10
【问题描述】:

我已经经历过很多次了,我已经复制了数据库文件用于测试目的,甚至重命名了该字段以匹配 Python 脚本。所以我在 Python 中使用的字段名称与表字段名称完全匹配。

import pyodbc

def main():
 tble="SomeTable"
 fld1="SomeField"
 val1="TestValue"
 sqlStrng = """INSERT INTO %s (%s) VALUES(%s);""" %(tble, fld1,val1)

 contStrng = (
  r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
  r'DBQ=Some\Path\File.accdb;'
  )

 cnnctn = pyodbc.connect(contStrng)
 cursr = cnnct.cursor()

 cursr.execute(sqlStrng)

 cnnctn.commit()
 cnnctn.close()

这不是拼写问题。我制作了 Access 文件的测试副本,并创建了一个名为 SomeTable 的表,其中包含一个名为 SomeField 的字段。我有正确的路径,我已经通过运行 SELECT SQL 脚本验证了这一点,该脚本可以正常工作。

我尝试将 fld1 设为参数,然后使用执行命令发送它,但随后我被告知我需要 0 个参数。当我删除它时,我被告知我需要 1 个。

我开始想也许是这个文件?相同的代码适用于我拥有的另一个文件。但是我创建了一个全新的文件,结果相同。我必须错过一些东西。

【问题讨论】:

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


    【解决方案1】:

    如果你在分配它后立即print(sqlStrng),你会看到它的值是

    INSERT INTO SomeTable (SomeField) VALUES(TestValue);
    

    Access 数据库引擎将无法识别的名称视为参数,因此它希望获得 name TestValue 的参数值。如果您想插入 字符串值 'TestValue',那么您应该使用 pyodbc 参数占位符 (?) 并在 .execute 方法中将 val1 作为参数传递,如下所示:

    tble="SomeTable"
    fld1="SomeField"
    val1="TestValue"
    sqlStrng = """INSERT INTO [%s] ([%s]) VALUES(?);""" %(tble, fld1)
    
    contStrng = (
    r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
    r'DBQ=Some\Path\File.accdb;'
    )
    
    cnnctn = pyodbc.connect(contStrng)
    cursr = cnnct.cursor()
    
    cursr.execute(sqlStrng, val1)
    

    请注意,如果SomeField 是一个数字字段并且您使用了val1=123,您不会收到错误消息,因为123 将被视为数字文字,而不是无法识别的名称(未加引号的文本值)。

    【讨论】:

    • 这行得通,但你能告诉我为什么在一个实例中它工作正常,而在这个实例中却不行吗?我是编写 Python 代码的新手,而不是连接数据库的新手。我写的另一个插入函数在不同的表上做同样的事情,它没有问题。显然字段和值名称是不同的。感谢您的澄清;显然,在我的研究中,我误解了如何应用参数。
    • 您的原始方法的术语是“动态 SQL”,动态 SQL 容易出现“SQL 注入”漏洞,其中数据 可能导致 SQL 语法出现问题。其中最著名的漏洞与数据库的安全性和完整性有关(参考:“Little Bobby Tables”),但 SQL 注入问题也可能简单地导致程序因某些数据值而崩溃。这就是为什么使用“参数化查询”将数据值传递给查询很重要的原因,如我的回答所示。
    • 我想补充一点,因为我现在开始更频繁地使用 Python 并遇到了类似的问题。我试图做一个选择查询。我不断收到一条消息,说需要 4 个参数,但提供了 3 个。我添加了一个额外的随机一个,只是被告知查询只需要 3 个。问题是表名不能是参数:stackoverflow.com/questions/6669009/…。其他所有内容都可以是参数,但您需要编写 sql 并存储在字符串变量中,并将表变量传递给它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2021-02-07
    • 1970-01-01
    相关资源
    最近更新 更多