"Incorrect number of bindings supplied" cPython 3.5 SQLite3 VS15

"Incorrect number of bindings supplied" cPython 3.5 SQLite3 VS15

import csv
import sqlite3

fileName = 'australianpublicholidays.csv'
accessMode = 'r'

# Create a database in RAM
holidayDatabase = sqlite3.connect(':memory:')

# Create a cursor
c = holidayDatabase.cursor()

# Create a table
c.execute('''CREATE TABLE holidays 
(date text, holidayName text, information text, moreInformation text, applicableTo text)''')

# Read the file contents in to the table
with open(fileName, accessMode) as publicHolidays :
    listOfPublicHolidays = csv.reader(publicHolidays)

    for currentRow in listOfPublicHolidays :
        for currentEntry in currentRow :
            c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)

# Close the database
holidayDatabase.close()

下面一行

    c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)

导致此错误

Incorrect number of bindings supplied. The current statement uses 5, and there are 4 supplied.

我已经通过删除嵌套的 for 循环更正了错误

Replaced the following

# Read the file contents in to the table
with open(fileName, accessMode) as publicHolidays :
    listOfPublicHolidays = csv.reader(publicHolidays)

    for currentRow in listOfPublicHolidays :
        for currentEntry in currentRow :
            c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)

With the following

with open(fileName, accessMode) as publicHolidays :
    listOfPublicHolidays = csv.reader(publicHolidays)

    for currentRow in listOfPublicHolidays :
            c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentRow)

但是我还不清楚错误的原因。

currentRow 已经是一个序列。它是行中所有字段的列表。 如果你要打印 currentRow,你会得到这样的输出 (假设这是你的数据集 https://data.gov.au/dataset/australian-holidays-machine-readable-dataset:

['Date', 'Holiday Name', 'Information', 'More Information', 'Applicable To']
['20150101', "New Year's Day", "New Year's Day is the first day of the calendaryear and is celebrated each January 1st", '', 'NAT']
['20150126', 'Australia Day', 'Always celebrated on 26 January', 'http://www.australiaday.org.au/', 'NAT']
['20150302', 'Labour Day', 'Always on a Monday, creating a long weekend. It celebrates the eight-hour working day, a victory for workers in the mid-late 19th century.',http://www.commerce.wa.gov.au/labour-relations/public-holidays-western-australia', 'WA']
...

当你这样做时

for currentEntry in currentRow :
    c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)

您实际上得到了列表第一个元素中所有字符的列表。 因为您没有跳过 header 行,所以您实际上得到了单词 "Date" 中的字符列表。等于 4 个字符并导致错误:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current sta
tement uses 5, and there are 4 supplied.

如果您使用 next(listOfPublicHolidays, None) 跳过 header 行,如:

with open(fileName, accessMode) as publicHolidays :
    listOfPublicHolidays = csv.reader(publicHolidays)
    next(listOfPublicHolidays, None)
    for currentRow in listOfPublicHolidays :
        for currentEntry in currentRow :
        c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)

您会收到以下错误消息,因为 currentEntry 将是 "20150101" 中字符的列表,长度为 8:

Traceback (most recent call last):
  File "holidaysorig.py", line 25, in <module>
    c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', tuple(currentEntry)
)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 5, and there are 8 supplied.

这就是当您删除 for currentEntry in currentRow : 块并将其重写为:

时(大部分情况下)它起作用的原因
import csv
import sqlite3

fileName = 'australianpublicholidays.csv'
accessMode = 'r'

# Create a database in RAM
holidayDatabase = sqlite3.connect(':memory:')

# Create a cursor
c = holidayDatabase.cursor()

# Create a table
c.execute('''CREATE TABLE holidays 
(date text, holidayName text, information text, moreInformation text, applicableTo text)''')

# Read the file contents in to the table
with open(fileName, accessMode) as publicHolidays :
    listOfPublicHolidays = csv.reader(publicHolidays)
    for currentRow in listOfPublicHolidays :
        c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentRow)

# Close the database
holidayDatabase.close()

注意: 在我的机器上,我收到以下错误:

(holidays) C:\Users\eyounjo\projects\holidays>python holidaysorig.py
Traceback (most recent call last):
  File "holidaysorig.py", line 22, in <module>
    c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentRow)
sqlite3.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.

所以我将你的脚本重写如下来处理上面的问题:

import csv, codecs
import sqlite3

# Encoding fix
def latin_1_encoder(unicode_csv_data):
    for line in unicode_csv_data:
        yield line.encode('latin-1')

fileName = 'australianpublicholidays.csv'
accessMode = 'r'

# Create a database in RAM
holidayDatabase = sqlite3.connect(':memory:')

# Create a cursor
c = holidayDatabase.cursor()

# Create a table
c.execute('''CREATE TABLE holidays 
(date text, holidayName text, information text, moreInformation text, applicableTo text)''')

# Read the file contents in to the table
# Encoding fix
with codecs.open(fileName, accessMode, encoding='latin-1') as publicHolidays :
    listOfPublicHolidays = csv.reader(latin_1_encoder(publicHolidays))
    # Skip the header row
    next(listOfPublicHolidays, None)
    entries = []
    for currentRow in listOfPublicHolidays:
        # Work-around for "You must not use 8-bit bytestrings" error
        entries.append(tuple([unicode(field, 'latin-1') for field in currentRow]))
    c.executemany('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', entries)

# Close the database
holidayDatabase.close()