sqlite3.InterfaceError:绑定参数0时出错 - 可能是不支持的类型?

Vex*_*ior 2 python sql database sqlite

尝试将数据从 Python(3.9.1) 编译到 SQLite3 时出现错误。

import sqlite3

conn = sqlite3.connect('newdB.db')

#Creates the table 'tbl_newdb' with an incrementing ID, and 'db_type' columns.
with conn:
    cur = conn.cursor()
    cur.execute("CREATE TABLE IF NOT EXISTS tbl_newdb( \
        ID INTEGER PRIMARY KEY AUTOINCREMENT, \
        db_type TEXT)")
    conn.commit()
conn.close()

conn = sqlite3.connect('newdB.db')

#Our list of data we will be grabbing from to fill the tables.
with conn:
    cur = conn.cursor()
    fileList = "information.docx","Hello.txt","myImage.png","myMovie.mpg","World.txt","data.pdf","myPhoto.jpg"
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)",(fileList,))
    conn.commit()
conn.close()
Run Code Online (Sandbox Code Playgroud)

这是我从 IDLE shell 收到的错误消息:

 line 22, in <module>
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)",(str(fileList,)))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 103 supplied.
Run Code Online (Sandbox Code Playgroud)

小智 5

TLDR:execute采用两个参数,一个 SQL 查询和一个输入列表,其中(?)SQL 中的每个参数都有一个元素。

您想要的是executemany接受输入列表的列表。解决方案如下所示:

import sqlite3

# Create a database in memory for testing
conn = sqlite3.connect('newdB.db')

# Execute with the databse connection
with conn:
    cur = conn.cursor()

    # Create your table in the in-memory database
    cur.execute("""
    CREATE TABLE IF NOT EXISTS tbl_newdb(
        ID INTEGER PRIMARY KEY AUTOINCREMENT,
        db_type TEXT
    )
    """)
    conn.commit()

# A list of parameters to pass to queries
# Notice we are making a list of lists
# `execute` takes a list of inputs for a single execution
parameterList = [
    ["information.docx"],
    ["Hello.txt"],
    ["myImage.png"],
    ["myMovie.mpg"],
    ["World.txt"],
    ["data.pdf"],
    ["myPhoto.jpg"],
]

with conn:
    # Execute the same query multiple times
    # Because we are passing one value to our sql, each list in parameterList
    # only has one element.
    cur.executemany(
        "INSERT INTO tbl_newdb(db_type) VALUES(?)",
        parameterList
    )
    conn.commit()

    # Print debugging information to prove we inserted things correctly
    cur.execute("SELECT db_type FROM tbl_newdb")
    print(cur.fetchall())

# Close the connection after creating the table
conn.close()
Run Code Online (Sandbox Code Playgroud)

注意我使用了 use[...]语法而不是元组(...,)语法。两者都可以,为了清晰起见,我只是更喜欢方括号,因为我们有很多单元素列表。

您还可以cur.exeutemany(...)用 for 循环替换,如下所示:

一些解释:execute接受两个参数,一个 SQL 查询和一个参数列表。您可以将参数列表视为(?)SQL 查询中每个参数的替换。第一个(?)将替换为参数列表中的第一个元素,第二个将(?)替换为列表中的第二个元素,依此类推。

让我们弄清楚我们是如何到达这里的。当我第一次运行你的代码时,我得到了这个输出:

Traceback (most recent call last):
  File "alt.py", line 20, in <module>
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)",(fileList,))
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
Run Code Online (Sandbox Code Playgroud)

unsupported type向我暗示,您正在将fileList它已经是一个元组,并将其包装在另一个元组中。所以我将该execute行更改为:

cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)", fileList)
Run Code Online (Sandbox Code Playgroud)

接下来我们得到这个错误:

Traceback (most recent call last):
  File "alt.py", line 20, in <module>
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)", fileList)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 7 supplied.
Run Code Online (Sandbox Code Playgroud)

这很奇怪。它正在获取我列出的 7 件事并试图将它们塞进一个绑定中?有趣的。如果我们缩短fileList为只有一个元素怎么办?从小事做起,看看我们能取得什么成果。我将上面的行更改execute

fileList = "information.docx"
Run Code Online (Sandbox Code Playgroud)

我们得到一个类似但不同的错误:

Traceback (most recent call last):
  File "alt.py", line 20, in <module>
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)", fileList)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 16 supplied.
Run Code Online (Sandbox Code Playgroud)

唔。16 是其中的字符数"information.docx",因此 Python 必须将该字符串视为参数列表。让我们将其包装在一个列表中,看看会发生什么:

fileList = ["information.docx"]
Run Code Online (Sandbox Code Playgroud)

这样我们就取得了第一次成功!

如果我们向列表中添加另一个元素会发生什么?

fileList = ["information.docx", "other_file.txt"]
Run Code Online (Sandbox Code Playgroud)
Traceback (most recent call last):
  File "alt.py", line 20, in <module>
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)", fileList)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 2 supplied.
Run Code Online (Sandbox Code Playgroud)

科学!它在一个元素上成功,但在两个元素上失败。这意味着第二个参数execute需要是一个列表,其中的元素数量与(?)SQL 查询中的参数数量相同。

现在我们有几个选择。我们可以阅读 SQLite Python 文档并发现 executemany,或者我们可以执行 for 循环:

for f in fileList:
    parameters = [f]
    cur.execute("INSERT INTO tbl_newdb (db_type) VALUES (?)", parameters)
conn.commit()
Run Code Online (Sandbox Code Playgroud)

SQLite 非常快,因此executemany和 for 循环都产生相似的性能。