Why doesn't this work (sqlite, python) - python

I tried to do this in the interpreter and I can get it to work but inside my function it doesn't
What I'm trying to do:
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
firstname = data[1] #the db is set as firstname in position 1 after the id(primekey)
I'm actually extracting all the data using this method just with different variables
The Error I get when I do it inside the function:
firstname = data[1]
TypeError: 'NoneType' object is not subscriptable
As a note: I put a print statement after the data object to see what it was returning, in the interpreter it returns the tuple i'm searching for, inside the function it's returning
'None'
FULL CODE:
def FindByPhone(self,phone):
'''Find Credit by phone number ONLY'''
dbconnect = sqlite3.connect(self.dbname)
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
first = data[1]
last = data[2]
phone = data[3]
credit = data[4]
cid = data[0]
self.SetVariables(first,last,phone,credit,cid)
cursor.close()
dbconnect.close()
return

I think the problem is that your function doesn't check if there was a matching row in the database. you will get this error if no row is being returned:
#!/usr/bin/python
try:
import sqlite3
except:
from pysqlite2 import dbapi2 as sqlite3
#prepare testcase
db="/tmp/soverflow.sqlite"
dbconnect = sqlite3.connect(db)
c = dbconnect.cursor()
c.execute("""create table credits
(id int not null primary key, firstname varchar(50), phone varchar(30),amount int not null)""")
c.execute("""INSERT INTO credits (id,firstname,phone,amount) VALUES (1,'guybrush','123-456',24)""")
c.execute("""INSERT INTO credits (id,firstname, phone,amount) VALUES (2,'elaine','1337-1337',18)""")
dbconnect.commit()
c.close()
def print_firstname(phone):
cursor = dbconnect.cursor()
cursor.execute("""SELECT * FROM credits WHERE phone = ?""",(phone,))
data = cursor.fetchone()
firstname = data[1]
cursor.close() # cleanup
print firstname
print "testing existing row"
print_firstname('1337-1337')
print "testing missing row"
print_firstname('nothere')
=>
./soverflow_sqlite.py
testing existing row
elaine
testing missing row
Traceback (most recent call last):
File "./soverflow_sqlite.py", line 31, in <module>
print_firstname('not-in-db')
File "./soverflow_sqlite.py", line 23, in print_firstname
firstname = data[1]
TypeError: 'NoneType' object is not subscriptable
Solution:
Add a check if there was a row returned from your query

Related

Inserting into database using pushbutton creates TypeError: argument 1 must be str, not tuple

I am having trouble making a pushbutton to insert elements into the table. Error states TypeError: argument 1 must be str, not tuple. I tried to convert it into int and do str but it keeps generating different errors. Could I get please get help figuring out what I have to do?
Below are my code and screenshot of DB and application
class MyCatScreen(QDialog):
def __init__(self):
super(MyCatScreen, self).__init__()
loadUi("myCatScreen.ui", self)
self.tableWidget.setColumnWidth(0,169)
self.tableWidget.setColumnWidth(1,169)
self.tableWidget.setColumnWidth(2,169)
self.tableWidget.setColumnWidth(3,169)
self.tableWidget.setHorizontalHeaderLabels(["Cat ID", "Cat Name", "Cat Age", "Cat Weight"])
self.loaddata()
self.catAdd.clicked.connect(self.addToDB)
def loaddata(self):
connection = sqlite3.connect('petData.db')
cur = connection.cursor()
# global cursor
# cursor = connection.cursor()
sqlquery = 'SELECT * FROM Cat_Info'
#numRow = cur.execute("SELECT count(Cat_ID) FROM Cat_Info")
#print(numRow)
#Attention needed!
#This needs to be changed to allocate dynamically
self.tableWidget.setRowCount(10)
tableRow = 0
for row in cur.execute(sqlquery):
print(row)
self.tableWidget.setItem(tableRow, 0, QtWidgets.QTableWidgetItem(str(row[0])))
self.tableWidget.setItem(tableRow, 1, QtWidgets.QTableWidgetItem(str(row[1])))
self.tableWidget.setItem(tableRow, 2, QtWidgets.QTableWidgetItem(str(row[2])))
self.tableWidget.setItem(tableRow, 3, QtWidgets.QTableWidgetItem(str(row[3])))
tableRow+=1
def addToDB(self):
name = self.catName.text()
age = self.catAge.text()
weight = int(self.catWeight.text())
newCat = (name, str(age), str(weight))
connection = sqlite3.connect('petData.db')
cur = connection.cursor()
sqlquery = 'INSERT into Cat_Info (Cat_Name, Cat_Age, Cat_Weight) VALUES(?,?,?),', (newCat)
cur.execute(sqlquery)
Traceback (most recent call last):
File "C:\Users\documents\sideProject\pyqt5\CatCare\main.py", line 126, in addToDB
cur.execute(sqlquery)
TypeError: argument 1 must be str, not tuple
application
SQLite DB
I think the error resides in how you executing queries
Here's how it has to be
sqlquery = 'INSERT into Cat_Info (Cat_Name, Cat_Age, Cat_Weight) VALUES(?,?,?),' <-- no parameters here
cur.execute(sqlquery, (name, age, weight))
It must be something in how your variables name, age, and weight defined, since you're still getting problems.
For example, this code works for me:
connection = sqlite3.connect('petData.db')
cur = connection.cursor()
# cur.execute('create table Cat_Info (Cat_Name, Cat_Age, Cat_Weight)')
name = 'cat1'
age = 1
weight = 10
sqlquery = 'insert into cat_info(cat_name, cat_age, cat_weight) values(?, ?, ?)'
cur.execute(sqlquery, (name, age, weight))
connection.commit()
for row in cur.execute('SELECT * FROM cat_info'):
print(row)
So, check out those variables' types

TypeError: Can't convert 'list' object to str implicitly SQLite3 Retrieving Data

def course_id(enrolment_id):
con = None
try:
con = lite.connect('C:/Users/Ethan/Desktop/SAT/SiemensAssessmentTool.db')
with con:
cur = con.cursor()
cur.execute("SELECT course_id FROM Enrolment WHERE enrolment_id = '"+ enrolment_id+ "';")
rows = cur.fetchall()
courseids=[]
for row in (rows):
courseids = row
return courseids
finally:
if con:
con.close()
What I'm trying to do with this code is retrieve a number of integers, as I will be connecting it to another function to find other data from the database. The error I get is when I connect it with other function:
def course_name(course_id):
con = None
try:
con = lite.connect('C:/Users/Ethan/Desktop/SAT/SiemensAssessmentTool.db')
with con:
cur = con.cursor()
cur.execute("SELECT course_name FROM Course WHERE course_id = '"+ course_id+ "';")
rows = cur.fetchall()
return rows
finally:
if con:
con.close()
And I get this error:
cur.execute("SELECT course_id FROM Enrolment WHERE enrolment_id = '"+ enrolment_id+ "';")
TypeError: Can't convert 'list' object to str implicitly
I'm guessing it has something to do with the course_id function, but I am not sure.. Thank you in advance
TypeError: Can't convert 'list' object to str implicitly
Clearly, the problem is that enrolment_id is a list, check what do you pass into the course_id() as an argument.
As a side note, you should not construct your query via string concatenation - this leads to problems with type conversions and makes your code vulnerable to SQL injections - parameterize the query instead:
cur.execute("SELECT course_id FROM Enrolment WHERE enrolment_id = ?", (enrolment_id, ))
There is also a problem in how you get the result of the query. Assuming you want a single course ID from the database, use fetchone():
courseid = cursor.fetchone()[0]
return courseid

Operational Error in SQL

I'm running sqlite3 and I cannot, for the life of me work out what is going wrong in my code. Baring in mind that it doesn't crash when creating other tables that come before it in the database. Part of me suspects it may be a case of capitalisation somewhere on an SQL statement but it was working normally a few days ago.
Create Table function
def create_table(db_name,table_name,sql):
with sqlite3.connect(db_name) as db:
cursor = db.cursor()
cursor.execute("select name from sqlite_master where name=?",(table_name,))
result = cursor.fetchall()
keep_table = True
if len(result) == 1:
response = input("The table {0} already exists, do you wish to recreate (y/n): ".format(table_name)) #option to recreate the database
if response == 'y':
keep_table = False
print("The {0} table will be recreated - all existing data will be lost".format(table_name))
cursor.execute("drop table if exists {0}".format(table_name))
db.commit()
elif response == 'n':
print("The existing table was kept")
else:
print("Incorrect input, please try again.") #validation measure
if len(result) == 1:
response = input("The table {0} already exists, do you wish to recreate (y/n): ".format(table_name))
if response == 'y':
keep_table = False
print("The {0} table will be recreated - all existing data will be lost".format(table_name))
cursor.execute("drop table if exists {0}".format(table_name))
db.commit()
else:
keep_table = False
if not keep_table:
cursor.execute(sql)
db.commit()
Tables that are causing the problem?
def create_customer_table():
sql = """create table Customer
(CustomerID integer,
FirstName text,
LastName text,
Street text,
Town text,
Postcode text,
TelephoneNumber text,
EmailAddress text
primary key(CustomerID))"""
create_table(db_name, "Customer", sql)
*ignore the fact it isn't indented, it is on my program.
def create_customer_order_table():
sql = """create table CustomerOrder
(OrderID integer,
CustomerID integer,
Date date,
Time integer
primary key(OrderID)
foreign key(CustomerID) references Customer(CustomerID))"""
create_table(db_name, "CustomerOrder", sql)
Here is the error I receive:
Traceback (most recent call last):
File "/Users/X/Downloads/manage_table_March_2015.py", line 110, in <module>
create_customer_table()
File "/Users/X/Downloads/manage_table_March_2015.py", line 78, in create_customer_table
create_table(db_name, "Customer", sql)
File "/Users/X/Downloads/manage_table_March_2015.py", line 33, in create_table
cursor.execute(sql)
ysqlite3.OperationalError: near "(": syntax error

Python throwing an error - String indices must be integers

I'm working on my python script using the version 2.6 for XBMC media application.
I have got a problem with my python script, I'm trying to pull the data off from the sqlite3 database but I'm getting an error TypeError: string indices must be integers.
The error are jumping on this line:
programming = channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"]
Here is the full code:
import xbmc
import xbmcgui
import xbmcaddon
import os
import urllib2
import StringIO
import sqlite3
from sqlite3 import dbapi2 as database
from xml.etree import ElementTree
import xml.etree.ElementTree as ET
from UserDict import DictMixin
import datetime
import time
class MyClass(xbmcgui.WindowXML):
def onAction(self, action):
#DOWNLOAD THE XML SOURCE HERE
url = ADDON.getSetting('allchannels.url')
req = urllib2.Request(url)
response = urllib2.urlopen(req)
data = response.read()
response.close()
profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))
if os.path.exists(profilePath):
profilePath = profilePath + 'source.db'
con = database.connect(profilePath)
cur = con.cursor()
cur.execute('CREATE TABLE programs(channel TEXT, title TEXT, start_date TIMESTAMP, stop_date TIMESTAMP, description TEXT)')
con.commit()
con.close
tv_elem = ElementTree.parse(StringIO.StringIO(data)).getroot()
profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))
profilePath = profilePath + 'source.db'
con = sqlite3.connect(profilePath)
cur = con.cursor()
channels = OrderedDict()
# Get the loaded data
for channel in tv_elem.findall('channel'):
channel_name = channel.find('display-name').text
for program in channel.findall('programme'):
title = program.find('title').text
start_time = program.get("start")
stop_time = program.get("stop")
cur.execute("INSERT INTO programs(channel, title, start_date, stop_date)" + " VALUES(?, ?, ?, ?)", [channel_name, title, start_time, stop_time])
con.commit()
print 'Channels store into database are now successfully!'
cur.execute('SELECT channel, title, start_date, stop_date FROM programs')
programList = list()
channelMap = dict()
results = cur.fetchall()
cur.close
for channel_result in results:
for row in channel_result:
programming = channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"]
print(programming)
I keep getting a same request of error in my XBMC log.
EDIT: When I try this:
programList = list()
channelMap = dict()
for c in channels:
if c.id:
channelMap[c.id] = c
strCh = '(\'' + '\',\''.join(channelMap.keys()) + '\')'
cur.execute('SELECT * FROM programs WHERE channel')
for row in cur:
programming = program(channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"])
programList.append(programming)
print(programming)
Here is the error on the xbmc log:
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <type 'exceptions.TypeError'>
Error Contents: tuple indices must be integers, not str
Traceback (most recent call last):
File "C:\Users\user\AppData\Roaming\XBMC\addons\script.tvguide\test.py", line 1679, in onAction
programming = program(channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"])
TypeError: tuple indices must be integers, not str
-->End of Python script error report<--
You are looping over each row in the result, then over each column. The columns are strings:
for channel_result in results:
for row in channel_result:
So channel_result is a row (a tuple by default), then you loop over that with for row in channel_result. This makes each row object a single column value.
You appear to expect row to be a dictionary instead; that is not the case here. You could just print the row directly; the columns are listed in the same order as the original SELECT:
for row in results:
programming = (channelMap[row[0]],) + row[1:]
If you really wanted a dictionary for each row, you'll have to tell sqlite3 to so by setting the row_factory attribute on the connection:
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
con = sqlite3.connect(profilePath)
con.row_factory = dict_factory
after which you use the one loop:
for row in results:
and row will be a dictionary with keys corresponding to the column names.
If I see it right, the error is pretty precise. Your return value should be a list of strings. And as such, you need to user integers for indices in that line. Python just simply doesn't know what to do with row['channel'], because there's no index 'channel' defined for row.
The easiest is probably to try and print the value of row there, then you should be able to debug it.
Here are a the docs: https://docs.python.org/2/library/sqlite3.html#sqlite3.Cursor

sqlite3.OperationalError: no such column. But that's not a column

I seem to be getting a rather odd error. And, for the life of me I can't figure out what's wrong. But on a piece of SQLite code, I'm getting this error:
Traceback (most recent call last):
File "test.py", line 38, in <module>
populateTables()
File "test.py", line 20, in populateTables
curs.execute("SELECT * FROM tracks WHERE ISRC = " + line[8])
sqlite3.OperationalError: no such column: USTCZ0993316
The odd part is that USTCZ0993316 is a piece of data that I want to compare to. I don't know why it seems to think it is a column. Here is a much small version that gives the same issue.
import sqlite3
import csv
def tableSetup(name):
if(name=="tracks"):
curs.execute("CREATE TABLE tracks(id INT UNIQUE, name TINYTEXT, album_id INT, client_id INT, acr_record_num INT, ISRC TINYTEXT UNIQUE, track_length TINYTEXT, client_share FLOAT)")
def populateTables():
tracks_csv=csv.reader(open('tables/tracks.csv', 'rU'), delimiter=";", quotechar='"')
tracks_csv.next()
for line in tracks_csv:
curs.execute("SELECT * FROM tracks WHERE id = " + line[0])
if not curs.fetchall():
if "\"" in line[1]:
line[1]=line[1].replace("\"","'")
curs.execute("INSERT INTO tracks VALUES("+line[0]+",\""+line[1]+"\","+line[2]+","+line[3]+","+line[4]+",\""+line[5]+"\",\""+line[7]+"\","+line[12]+")")
override_csv=csv.reader(open('tables/artist_override.csv', 'rU'), delimiter=",", quotechar='"')
override_csv.next()
for line in override_csv:
curs.execute("SELECT * FROM tracks WHERE ISRC = " + line[8])
print curs.fetchone()
#Set required Table Names
tables = ["tracks"]
testOut=open('tables/testOut.txt','w')
conn = sqlite3.connect('tables/test.db')
curs = conn.cursor()
# Create table if they don't already exist
curs.execute("SELECT name FROM sqlite_master WHERE type='table'")
tableResults = curs.fetchall()
print
for table in tables:
if not any(table == result[0] for result in tableResults):
tableSetup(table)
populateTables()
conn.commit()
curs.close()
If it doesn't have quotes then it's a column or a number.
curs.execute("SELECT * FROM tracks WHERE ISRC = ?", (line[8],))
[Edit: "%s" isn't proper syntax. It should be "?". Also, if you're going to be condescending, at least be right about it.]

Categories