Python - SQLite : Update two record with same identify value - python

i have a script like below :
import psutil
import sqlite3
DISK = {'1': ['C:\\', 'C:\\', 'NTFS', 'rw,fixed', '75.0Gb', '54.0Gb', '20.0Gb', '72.2%'], '2': ['D:\\', 'D:\\', 'NTFS', 'rw,fixed', '399.0Gb', '208.0Gb', '191.0Gb', '52.2%']}
conn = sqlite3.connect("Test.db")
c = conn.cursor()
result = c.execute("SELECT * FROM clientinfo WHERE IP = ?", ("192.168.10.111",))
if (len(result.fetchall()) > 0):
for x in DISK :
c.execute("UPDATE disk SET Device = ?, 'Mount Point' = ?, 'fstyle' = ?, 'opts' = ?, 'total' = ?, 'used' = ?, 'free' = ?, 'percent' = ? WHERE Client_IP = ?", (DISK[x][0], DISK[x][1], DISK[x][2], DISK[x][3], DISK[x][4], DISK[x][5], DISK[x][6], DISK[x][7], "192.168.10.111"))
else :
for x in DISK :
c.execute("INSERT INTO disk('Client_IP', 'Device', 'Mount Point', 'fstyle', 'opts', 'total', 'used', 'free', 'percent') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", ("192.168.10.111", DISK[x][0], DISK[x][1], DISK[x][2], DISK[x][3], DISK[x][4], DISK[x][5], DISK[x][6], DISK[x][7]))
conn.commit()
conn.close()
Script will check in db if there is any record about IP "192.168.10.111". If db already have record about IP "192.168.10.111", Script will update data from dict DISK to table disk of db.
If db don't have record about IP "192.168.10.111", Script will create record to insert **DISK"" to database.
INSERT command work well but the UPDATE command don't work like i want. After INSERT command run, in table disk i will have two record about disk C and disk D with same value of column Client_IP (192.168.10.111).
After UPDATE, two record of IP "192.168.10.111" get same value on every column ehich is very wrong. One record must be contain information about disk C and another record cotain disk D information.
How can i make the UPDATE work right ? length of dict DISK depend on how many mounted devices the computer has. So i need to use for loop to UPDATE but not static UPDATE.
Please tell me how to fix this,
Many thanks,
Francis

Your SELECT query column value is incorrect based on your UPDATE and INSERT queries later on. Instead of IP, should't it be CLIENT_IP? Also, you need to change your string query formatting. Remove the single quotes form your column names. Lastely, you can shorten your code by using a simple list comprehension and cursor.executemany:
import sqlite3
DISK = {'1': ['C:\\', 'C:\\', 'NTFS', 'rw,fixed', '75.0Gb', '54.0Gb', '20.0Gb', '72.2%'], '2': ['D:\\', 'D:\\', 'NTFS', 'rw,fixed', '399.0Gb', '208.0Gb', '191.0Gb', '52.2%']}
conn = sqlite3.connect("Test.db")
c = conn.cursor()
if not list(c.execute('SELECT * FROM lientinfo WHERE CLIENT_IP = ?', ("192.168.10.111",))):
c.executemany("INSERT INTO disk (Client_IP, Device, Mount Point, fstyle, opts, total, used, free, percent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", [["192.168.10.111", *i] for i in DISK.values()])
else:
c.executemany('UPDATE disk SET Device = ?, Mount Point = ?, fstyle = ?, opts = ?, total = ?, used = ?, free = ?, percent = ? WHERE Client_IP = ?', [[*i, "192.168.10.111"] for i in DISK.values()])

Related

Python Sqlite3 not updating database

I'm working in a project, and i'm facing a issue when trying to update my database...
I'm running the following command:
con = sqlite3.connect("DATASETS/SQLite.db")
cur = con.cursor()
with open("DATASETS/test.csv","r") as fin:
dr = csv.DictReader(fin, ["element1", "element2", "element3", "element4", "element5", "element6", "element7", "element8", "id"])
to_db = [(i["element1"], i["element2"], i["element3"], i["element4"], i["element5"], i["element6"], i["element7"], i["element8"], i["id"]) for i in dr]
cur.executemany("UPDATE Table SET element1 = ?, element2 = ?, element3 = ?, element4 = ?, element5 = ?, element6 = ?, element7 = ?, element8 = ? WHERE ID = ?;", to_db)
con.commit()
con.close()
The data is beeing filtered in a dataset csv with 6000+ rows and delimiter ",".
The code runs without errors, but, when i opened the DB to check, there ware not even a single row that was updated.
I do not know if this is a VSCode bug, a version error (Python 3.8.3), or anything like this, and i wnated to ask if anyone has already saw this.
Thanks!!

Updating SQL with Python - Incorrect number of bindings

I keep getting this error
Traceback (most recent call last):
File "test.py", line 7, in <module>
c.execute("INSERT INTO file_routes (file_route) VALUES (?)", (file_route))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 4 supplied.
I create the table with this
createTable_filenames = """
CREATE TABLE IF NOT EXISTS
file_routes(
routes_id INTEGER PRIMARY KEY,
file_route TEXT
)
"""
This is the code I am trying to run and it doesn't work
import sqlite3
conn = sqlite3.connect('fantasyresults.db')
c = conn.cursor()
file_route = "test"
c.execute("INSERT INTO file_routes (file_route) VALUES (?)", (file_route))
conn.commit()
I don't understand why this code works, I set up the structure the same way.
c.execute than ("INSERT INTO <tablename> (<column id>) VALUES (?)", (<variable>))
c.execute("INSERT INTO draftkings (account_id, sport, game_type, entry_key, entry_name, opponent, contest_key, contest_date, position, points, winnings, winnings_tickets, contest_entries, entry_fee, prize_pool, places_paid)VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (account_id, sport, game_type, entry_key, entry_name, opponent, contest_key, contest_date, position, points, winnings, winnings_tickets, contest_entries, entry_fee, prize_pool, places_paid))
Any help is much appreciated, I don't know what I am not seeing here.
The problem is that it is considering the parameter as string instead of tuple as that's the expected behavior in python for a tuple with single element.
Try updating the parameter tuple as
(file_route, )
have a comma after the parameter.

Can't insert this JSON data to SQL Server?

I'm trying to insert the following JSON data into a table on our SQL Server with python code.
('{"ITEMCODE":"A00975605","DISPLAYREVISIONNO":1,"ITEMNAME":"ABCDEFGHIJKLMN","ITEMNAME_ID":"~0000PCLAZ","ITEMTYPE":2,"ITEMTYPEEX":0,"PRODUCTTYPE":12,"LOTTYPE":"S1","EDITIONNOTYPE":0,"ISINVENTORY":2,"HOSTMANAGETYPE":-1,"SHIPMENTJUDGETYPE":null,"UNITVOLUME":1000,"TAREWEIGHT":0,"DEFAULTRECIPECODE":null,"ISQUALITYCHECK":1,"ISALLOCATEMORELOT":0,"ISINSERTLOTCHECK":-1,"RECEIPTVOLUMELIMIT":"10","RECEIPTZONECODE":"FS01","WAREHOUSEZONECODE":null,"SHIPMENTZONECODE":null,"LABELCODE":null,"THEME":null,"ARTICLENO":null,"ARTICLENAME":null,"ARTICLENAME_ID":null,"PACKAGEINDICATOR":null,"PRODUCTIONFLOWNO":null,"RECEIPTFLOWNO":null,"TESTFLOWNO":null,"RECORDREVIEWFLOWNO":null,"SHIPMENTGMPFLOWNO":null,"SHIPMENTGQPFLOWNO":null,"NOTE":null,"NOTE_ID":null,"STRENGTHUNITFLAG":0,"MEDICINEDIVISION":null,"EVALUATIONCLASS":"6200","SAMPLINGVALUEFORLIST":null,"STOCKVALUEFORLIST":null,"FILLINGVOLUME":null,"FILLINGVOLUMEMAXIMUMLIMIT":null,"FILLINGVOLUMEMINIMUMLIMIT":null,"FILTRATIONTYPE":null,"STERILIZATIONTYPE":null,"BOTTLEWASHING":null,"STRENGTHUNITFLAGEX":0,"DEFAULTMAKERCODE":"H75776","PRODUCTCODEFORBCD ":null,"STOCKCONDITIONCODE":5,"METALUSE":null,"AUTOALLOCFLAG":1,"INNERPACKAGEVOLUME ":1000,"AREACODE":"A1","STANDARDSTRENGTHUNITRATIO":1}',)
('{"ITEMCODE":"A00975612","DISPLAYREVISIONNO":1,"ITEMNAME":"BCDEFGHIJKLMNO","ITEMNAME_ID":"~0000PCLHS","ITEMTYPE":2,"ITEMTYPEEX":0,"PRODUCTTYPE":12,"LOTTYPE":"S1","EDITIONNOTYPE":0,"ISINVENTORY":2,"HOSTMANAGETYPE":-1,"SHIPMENTJUDGETYPE":null,"UNITVOLUME":1000,"TAREWEIGHT":0,"DEFAULTRECIPECODE":null,"ISQUALITYCHECK":1,"ISALLOCATEMORELOT":0,"ISINSERTLOTCHECK":-1,"RECEIPTVOLUMELIMIT":"10","RECEIPTZONECODE":"FS01","WAREHOUSEZONECODE":null,"SHIPMENTZONECODE":null,"LABELCODE":null,"THEME":null,"ARTICLENO":null,"ARTICLENAME":null,"ARTICLENAME_ID":null,"PACKAGEINDICATOR":null,"PRODUCTIONFLOWNO":null,"RECEIPTFLOWNO":null,"TESTFLOWNO":null,"RECORDREVIEWFLOWNO":null,"SHIPMENTGMPFLOWNO":null,"SHIPMENTGQPFLOWNO":null,"NOTE":null,"NOTE_ID":null,"STRENGTHUNITFLAG":0,"MEDICINEDIVISION":null,"EVALUATIONCLASS":"6200","SAMPLINGVALUEFORLIST":null,"STOCKVALUEFORLIST":null,"FILLINGVOLUME":null,"FILLINGVOLUMEMAXIMUMLIMIT":null,"FILLINGVOLUMEMINIMUMLIMIT":null,"FILTRATIONTYPE":null,"STERILIZATIONTYPE":null,"BOTTLEWASHING":null,"STRENGTHUNITFLAGEX":0,"DEFAULTMAKERCODE":"H75776","PRODUCTCODEFORBCD ":null,"STOCKCONDITIONCODE":5,"METALUSE":null,"AUTOALLOCFLAG":1,"INNERPACKAGEVOLUME ":1000,"AREACODE":"A1","STANDARDSTRENGTHUNITRATIO":1}',)
('{"ITEMCODE":"A00977746","DISPLAYREVISIONNO":1,"ITEMNAME":"CDEFGHIJKLMNOP","ITEMNAME_ID":"~0000PCJZN","ITEMTYPE":2,"ITEMTYPEEX":0,"PRODUCTTYPE":12,"LOTTYPE":"S1","EDITIONNOTYPE":0,"ISINVENTORY":2,"HOSTMANAGETYPE":-1,"SHIPMENTJUDGETYPE":null,"UNITVOLUME":1000,"TAREWEIGHT":0,"DEFAULTRECIPECODE":null,"ISQUALITYCHECK":1,"ISALLOCATEMORELOT":0,"ISINSERTLOTCHECK":-1,"RECEIPTVOLUMELIMIT":"10","RECEIPTZONECODE":"FS01","WAREHOUSEZONECODE":null,"SHIPMENTZONECODE":null,"LABELCODE":null,"THEME":null,"ARTICLENO":null,"ARTICLENAME":null,"ARTICLENAME_ID":null,"PACKAGEINDICATOR":null,"PRODUCTIONFLOWNO":null,"RECEIPTFLOWNO":null,"TESTFLOWNO":null,"RECORDREVIEWFLOWNO":null,"SHIPMENTGMPFLOWNO":null,"SHIPMENTGQPFLOWNO":null,"NOTE":null,"NOTE_ID":null,"STRENGTHUNITFLAG":0,"MEDICINEDIVISION":null,"EVALUATIONCLASS":"6200","SAMPLINGVALUEFORLIST":null,"STOCKVALUEFORLIST":null,"FILLINGVOLUME":null,"FILLINGVOLUMEMAXIMUMLIMIT":null,"FILLINGVOLUMEMINIMUMLIMIT":null,"FILTRATIONTYPE":null,"STERILIZATIONTYPE":null,"BOTTLEWASHING":null,"STRENGTHUNITFLAGEX":0,"DEFAULTMAKERCODE":"H75776","PRODUCTCODEFORBCD ":null,"STOCKCONDITIONCODE":5,"METALUSE":null,"AUTOALLOCFLAG":1,"INNERPACKAGEVOLUME ":1000,"AREACODE":"A1","STANDARDSTRENGTHUNITRATIO":1}',)
('{"ITEMCODE":"A00977753","DISPLAYREVISIONNO":1,"ITEMNAME":"DEFGHIJKLMNOPQ","ITEMNAME_ID":"~0000PCJZP","ITEMTYPE":2,"ITEMTYPEEX":0,"PRODUCTTYPE":12,"LOTTYPE":"S1","EDITIONNOTYPE":0,"ISINVENTORY":2,"HOSTMANAGETYPE":-1,"SHIPMENTJUDGETYPE":null,"UNITVOLUME":1000,"TAREWEIGHT":0,"DEFAULTRECIPECODE":null,"ISQUALITYCHECK":1,"ISALLOCATEMORELOT":0,"ISINSERTLOTCHECK":-1,"RECEIPTVOLUMELIMIT":"10","RECEIPTZONECODE":"FS01","WAREHOUSEZONECODE":null,"SHIPMENTZONECODE":null,"LABELCODE":null,"THEME":null,"ARTICLENO":null,"ARTICLENAME":null,"ARTICLENAME_ID":null,"PACKAGEINDICATOR":null,"PRODUCTIONFLOWNO":null,"RECEIPTFLOWNO":null,"TESTFLOWNO":null,"RECORDREVIEWFLOWNO":null,"SHIPMENTGMPFLOWNO":null,"SHIPMENTGQPFLOWNO":null,"NOTE":null,"NOTE_ID":null,"STRENGTHUNITFLAG":0,"MEDICINEDIVISION":null,"EVALUATIONCLASS":"6200","SAMPLINGVALUEFORLIST":null,"STOCKVALUEFORLIST":null,"FILLINGVOLUME":null,"FILLINGVOLUMEMAXIMUMLIMIT":null,"FILLINGVOLUMEMINIMUMLIMIT":null,"FILTRATIONTYPE":null,"STERILIZATIONTYPE":null,"BOTTLEWASHING":null,"STRENGTHUNITFLAGEX":0,"DEFAULTMAKERCODE":"H75776","PRODUCTCODEFORBCD ":null,"STOCKCONDITIONCODE":5,"METALUSE":null,"AUTOALLOCFLAG":1,"INNERPACKAGEVOLUME ":1000,"AREACODE":"A1","STANDARDSTRENGTHUNITRATIO":1}',)
('{"ITEMCODE":"A00977760","DISPLAYREVISIONNO":1,"ITEMNAME":"EFGHIJKLMNOPQR","ITEMNAME_ID":"~0000PCJZR","ITEMTYPE":2,"ITEMTYPEEX":0,"PRODUCTTYPE":12,"LOTTYPE":"S1","EDITIONNOTYPE":0,"ISINVENTORY":2,"HOSTMANAGETYPE":-1,"SHIPMENTJUDGETYPE":null,"UNITVOLUME":1000,"TAREWEIGHT":0,"DEFAULTRECIPECODE":null,"ISQUALITYCHECK":1,"ISALLOCATEMORELOT":0,"ISINSERTLOTCHECK":-1,"RECEIPTVOLUMELIMIT":"10","RECEIPTZONECODE":"FS01","WAREHOUSEZONECODE":null,"SHIPMENTZONECODE":null,"LABELCODE":null,"THEME":null,"ARTICLENO":null,"ARTICLENAME":null,"ARTICLENAME_ID":null,"PACKAGEINDICATOR":null,"PRODUCTIONFLOWNO":null,"RECEIPTFLOWNO":null,"TESTFLOWNO":null,"RECORDREVIEWFLOWNO":null,"SHIPMENTGMPFLOWNO":null,"SHIPMENTGQPFLOWNO":null,"NOTE":null,"NOTE_ID":null,"STRENGTHUNITFLAG":0,"MEDICINEDIVISION":null,"EVALUATIONCLASS":"6200","SAMPLINGVALUEFORLIST":null,"STOCKVALUEFORLIST":null,"FILLINGVOLUME":null,"FILLINGVOLUMEMAXIMUMLIMIT":null,"FILLINGVOLUMEMINIMUMLIMIT":null,"FILTRATIONTYPE":null,"STERILIZATIONTYPE":null,"BOTTLEWASHING":null,"STRENGTHUNITFLAGEX":0,"DEFAULTMAKERCODE":"H75776","PRODUCTCODEFORBCD ":null,"STOCKCONDITIONCODE":5,"METALUSE":null,"AUTOALLOCFLAG":1,"INNERPACKAGEVOLUME ":1000,"AREACODE":"A1","STANDARDSTRENGTHUNITRATIO":1}',)
And if I could solve this with executing a SQL statement, I would be so happy.
Because our Application server with python and SQL Server are completely different machines. They are actually far apart each other.
Attempting the code below, I have run into an error. Could anyone give me some advice?
def jsonINSERT(_cn, _cur, jdata):
SQL = """
INSERT INTO TSTTBL VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"""
_cur.executemany(SQL, jdata)
_cn.commit()
return
'The SQL contains 56 parameter markers, but 1 parameters were supplied', 'HY000'
I did like this eventually.
def jsonINSERT(_cn, _cur, sql, jdata):
_cur.executemany(sql, jdata)
_cn.commit()
return
#From Oracle
fetch_dat = cur.fetchall()
#To take tuple off
fetch_dat = [json.loads(t[0]) for t in fetch_dat]
#To declare columns for the query
columns = tuple(fetch_dat[0].keys())
params = ['?' for _ in range(len(columns))]
#To declare value for the query
data = [tuple(e.values()) for e in fetch_dat]
#Composing the sql!
sql = 'INSERT INTO TSTTBL ({}) VALUES ({})'.format(','.join(columns), ','.join(params))
jsonINSERT(mscn, mscur, sql, data)
Many ways to go about this, but I think an example will help, you may need something like this:
db.execute("INSERT INTO `t1` VALUES (%s)", json_vals)
OR essentially,
db.execute(yourQueryHere, json_vals)

Loop breaks when executing function

I have the code below:
def scrapeFacebookPageFeedStatus(access_token):
query = "SELECT page_id FROM falken"
result_list = c.execute(query)
for single_row in result_list:
str_single_row = str(single_row)
str_norm_single_row = str_normalize(str_single_row)
print(str_norm_single_row)
When I execute the code above, It displays every single_row values from result_list.
But when I pass single_row to a function like below:
def scrapeFacebookPageFeedStatus(access_token):
query = "SELECT page_id FROM falken"
result_list = c.execute(query)
for single_row in result_list:
str_single_row = str(single_row)
str_norm_single_row = str_normalize(str_single_row)
print(str_norm_single_row)
statuses = getFacebookPageFeedData(str_norm_single_row, access_token, 100)
for status in statuses['data']:
query = "INSERT INTO falken_posts VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
c.execute(query,(processFacebookPageFeedStatus(status, access_token)))
conn.commit()
It only passes the first value of single_row to the function and the loop stops.
getFacebookPageFeedData function
def getFacebookPageFeedData(page_id, access_token, num_statuses):
base = "https://graph.facebook.com/v2.6"
node = "/%s/posts" % page_id
fields = "/?fields=message,link,created_time,type,name,id," + \
"comments.limit(0).summary(true),shares,reactions" + \
".limit(0).summary(true)"
parameters = "&limit=%s&access_token=%s" % (num_statuses, access_token)
url = base + node + fields + parameters
# retrieve data
data = json.loads(request_until_succeed(url))
return data
It retrieves data from Facebook Graph API of posts from pages.
processFacebookPageFeedStatus function
def processFacebookPageFeedStatus(status, access_token):
status_id = status['id']
status_message = '' if 'message' not in status.keys() else \
unicode_normalize(status['message'])
link_name = '' if 'name' not in status.keys() else \
unicode_normalize(status['name'])
status_type = status['type']
status_link = '' if 'link' not in status.keys() else \
unicode_normalize(status['link'])
status_published = datetime.datetime.strptime(
status['created_time'],'%Y-%m-%dT%H:%M:%S+0000')
status_published = status_published + \
datetime.timedelta(hours=-5) # EST
status_published = status_published.strftime(
'%Y-%m-%d %H:%M:%S')
num_reactions = 0 if 'reactions' not in status else \
status['reactions']['summary']['total_count']
num_comments = 0 if 'comments' not in status else \
status['comments']['summary']['total_count']
num_shares = 0 if 'shares' not in status else status['shares']['count']
reactions = getReactionsForStatus(status_id, access_token) if \
status_published > '2016-02-24 00:00:00' else {}
num_likes = 0 if 'like' not in reactions else \
reactions['like']['summary']['total_count']
num_likes = num_reactions if status_published < '2016-02-24 00:00:00' \
else num_likes
It stores needed data from status dictionary and stores it to variables for inserting into database.
sqlite's cursor.execute() returns the cursor itself. So after this line:
result_list = c.execute(query)
result_list is actually an alias for c.
Now you start iterating over c:
for single_row in result_list:
# code here
and then call c.execute() again:
query = "INSERT INTO falken_posts VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
c.execute(query,(processFacebookPageFeedStatus(status, access_token)))
which discards c's previous result set with the result of this new query. Since this query doesn't select anything, c becomes an empty iterator, and your loop stops there.
The cure is plain and simple: use another cursor for the insert queries so you don't overwrite c's result set:
# create a second cursor for insert statements
writer = conn.cursor()
# no need to recreate this same string anew for each iteration,
# we can as well define it here once for all
insert_query = "INSERT INTO falken_posts VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
# no need for result_list - just iterate over `c`
c.execute(query)
for single_row in c:
# code here
writer.execute(insert_query,(processFacebookPageFeedStatus(status, access_token)))
As a side note, if performances are an issue, you may also want to commit only once after the whole loop instead of after each insert statement.

"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()
The following line
c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)
is causing this error
Incorrect number of bindings supplied. The current statement uses 5,
and there are 4 supplied.
currentRow is already a sequence. It's a list of all of the fields in the row.
If you were to print out currentRow, you'd get output like this (assuming this is your data set 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']
...
When you do
for currentEntry in currentRow :
c.execute('INSERT INTO holidays VALUES (?, ?, ?, ?, ?)', currentEntry)
You're actually getting a list of all of the characters in the first element in the list.
Because you didn't skip the header row, you're actually getting a list of the characters in the word "Date". Which equals 4 characters and is causing the error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current sta
tement uses 5, and there are 4 supplied.
If you were to skip the header line using next(listOfPublicHolidays, None) as in:
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)
you would get the following error message because currentEntry would be a list of the characters in "20150101", having a length of 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.
That's why it works (for the most part) when you remove the for currentEntry in currentRow : block and rewrite it as:
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()
NOTE: On my machine, I got the following errors:
(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.
So I rewrote your script as the following to deal with the above:
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()
I have corrected the error by removing the nested for loop
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)
However the cause of the error is still unclear to me.

Categories

Resources