I am writing a program in which two variables are selected from QCombobBoxes which are populated with results from a MySQL query. I then take these variable and insert them into a MySQLdb statement that inserts the variables into a different MySQL table. The first variable works fine, however on the second I get this error,
TypeError: 'NoneType' object has no attribute '__getitem__'
The code is identical for both variables, with the exception of different names
name = str(self.item_name.currentText())
cur.execute("SELECT item_id FROM Items WHERE name = '%s';"), name
db.commit()
results = cur.fetchone()
item_name = results[0]
personnel_name = str(self.purchaser_name.currentText())
cur.execute("SELECT personnel_id FROM Personnel WHERE name = '%s';"), personnel_name
db.commit()
results = cur.fetchone()
purchaser_id = results[0]
After playing with it, it looks like cur.execute("SELECT item_id FROM Items WHERE name = '%s';"), name is inserting an extra pair of quotation marks around the value that replaces %s Does anyone know why it's doing this and how to stop it? I coded both variables exactly the same, and it seems that name is getting an extra pair of quotes from MySQL
This is code that populates QComboBox:
#Get list of items currently in the database
cur = db.cursor()
cur.execute("SELECT name FROM Items")
db.commit()
results = cur.fetchall()
for name in results:
self.item_name.addItem(name[0])
#Get list of purchaser names
cur.execute("SELECT name FROM Personnel")
db.commit()
results = cur.fetchall()
for name in results:
self.purchaser_name.addItem(name[0])
If I manually insert a variable, it works fine. ex: cur.execute("SELECT item_id FROM Items WHERE name = 'Wire';") Only when I use string formatting with %s does the error occurr.
c.execute("SELECT * FROM sometable WHERE some_condition=?","My Condition")
you should always use the ? placeholders for this kind of thing
[edit]
try 1. cur.execute("SELECT item_id FROM Items WHERE name = '%s';"%(name,))
or 2. cur.execute("SELECT item_id FROM Items WHERE name = %s;", (name,))
from my brief reading, I think that mysql driver will automatically quote %s arguments
my conclusion is that cur.execute("SELECT item_id FROM Items WHERE name = %s;", (name,)) is the most correct way to do this(to avoid injection etc).
Related
in my python code I insert a value into a table.
In the table, there is a sequence which automatically assigns an ID.
After the insert, I want to get this it back in to my python application:
import cx_Oracle, sys
with cx_Oracle.connect(user=ORA_USER,password=ORA_PWD,dsn=ORA_DSN) as conn:
with conn.cursor() as cur:
cur.execute("Insert into my_table columns(data) values ('Hello')")
conn.commit()
with cx_Oracle.connect(user=ORA_USER,password=ORA_PWD,dsn=ORA_DSN) as conn:
with conn.cursor() as cur:
r = cur.execute("select id from my_table where data = 'Hello'")
print(r)
if r is None:
print("Cannot retrieve ID")
sys.exit()
Unfortunately, the result set r is always "None" even though the value has been inserted properly (checked via sqldeveloper).
What am I doing wrong?
I even open a new connection to be sure to grab the value...
After calling execute() for a SELECT statement you need to call fetchone(), fetchmany() or fetchall() as shown in the cx_Oracle documentation SQL Queries.
Or you can use an iterator:
with connection.cursor() as cursor:
try:
sql = """select systimestamp from dual"""
for r in cursor.execute(sql):
print(r)
sql = """select 123 from dual"""
(c_id,) = cursor.execute(sql).fetchone()
print(c_id)
except oracledb.Error as e:
error, = e.args
print(sql)
print('*'.rjust(error.offset+1, ' '))
print(error.message)
However to get an automatically generated ID returned without the overhead of an additional SELECT, you can change the INSERT statement to use a RETURNING INTO clause. There is an example in the cx_Oracle documentation DML RETURNING Bind Variables that shows an UPDATE. You can use similar syntax with INSERT.
With the table:
CREATE TABLE mytable
(myid NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
mydata VARCHAR2(20));
You can insert and get the generated key like:
myidvar = cursor.var(int)
sql = "INSERT INTO mytable (mydata) VALUES ('abc') RETURNING myid INTO :bv"
cursor.execute(sql, bv=myidvar)
i, = myidvar.getvalue()
print(i)
If you just want a unique identifier you get the ROWID of an inserted row without needing a bind variable. Simple access cursor.lastrowid after executing an INSERT.
I've been given a messy Excel file that I am trying to transfer into tidied SQL tables. I am building a Python program to do the transfer. There is a list of names, some of which are repeated. I've already gotten the column with all the names into a list of tuples like:
[(John Christopher, ), (Elizabeth Smith, ), (etc, )]
I've built an SQL table called Players and have an empty column named "id". I'm trying to iterate through this list and assign a unique id to each player in the Table and then also delete the duplicate names in my table.
However I keep getting this error:
cursor.execute("UPDATE Players SET id = "+str(id)+" WHERE name = "+str(item[0]))
sqlite3.OperationalError: near "Christopher": syntax error
What is my issue?
Here is the code:
import sqlite3
player_list_start = cursor.execute("SELECT name FROM Players")
saved_list = player_list_start.fetchall()
# number id should start on
id = 1
# list of players to keep track if they are already in the table
names = []
for item in saved_list:
if item[0] not in names:
cursor.execute("UPDATE Players SET id = "+str(id)+" WHERE name = "+str(item[0]))
connection.commit()
names.append(item[0])
id += 1
else:
cursor.execute("DELETE FROM Players WHERE name = "+str(item[0])+" AND id = NULL")
connection.commit()
It definitely says sqlite3.OperationalError: near "Christopher": syntax error .
The following line will generate syntactically wrong SQL statement because it does not quote strings (especially including spaces).
cursor.execute("DELETE FROM Players WHERE name = "+str(item[0])+" AND id = NULL")
Use
cursor.execute("DELETE FROM Players WHERE name = '"+str(item[0])+"' AND id = NULL")
or
cursor.execute("DELETE FROM Players WHERE name = ? AND id = NULL", (str(item[0]),))
I am attempting to retrieve data associated given a particular last name. This last name, however, is stored within a listbox along with a first name and separator comma. As such, the name is retrieved from the listbox first by cursor selection, and only the last name is used to search by partitioning the rest:
lastname, sep, firstname = (self.patient_list.get(self.patient_list.curselection())).partition(',')
Once this is done, I am trying to get a printout of the data rows for this chosen last name. However, I am coming across the issue:
TypeError: argument 1 must be a string or unicode object: got tuple instead
I am wondering how to proceed with this issue. I have attempted a few solutions, such as the tuple function within the argument in load_query, as well as str on lastname, but it is a string...
I am also wondering if it is even necessary to select from a PostgreSQL db by this method. Can I try binding a listbox element to a row of data in the db? Or avoid partitioning the element, since that seems to be of trouble perhaps...
Full code:
def load_profile(self, event):
conn = pg.connect(user='postgres',
password='123!',
host='localhost',
port='5430',
database='carepartnerdb')
cur = conn.cursor()
#gets lastname from listbox, removes all else past the comma
#used to associate to DB
lastname, sep, firstname = (self.patient_list.get(self.patient_list.curselection())).partition(',')
load_query = (""" SELECT * FROM profiles_table WHERE patient_lastname=%s """, lastname)
cur.execute(load_query)
conn.commit()
#data = cur.fetchall()
#print(data)
cur.close()
conn.close()
load_query is a tuple, so cur.execute(load_query) will raise the exception as execute() expects a string (the query string) as the first argument.
You should change:
load_query = (""" SELECT * FROM profiles_table WHERE patient_lastname=%s """, lastname)
cur.execute(load_query)
to:
load_query = "SELECT * FROM profiles_table WHERE patient_lastname = %s"
cur.execute(load_query, (lastname,))
Also SELECT statement does not require commit().
For my school project I decided to make a physics revision tool. The tool lets users log in and saves information about their performance on certain questions. As a result of this I realised I needed to name each table used to store each individual users scores so I thought using .format would be appropriate. It seemed to be working fine until the point where i needed to add code that would add information to the table. From the testing i have done on the code so far, i think the problem is because i am using .format it won't actually create any columns. I don't know how to get around that please help. Appropriate sections of code have been provided:
def quesprep():
intro.destroy()
con= sqlite3.connect("login.db")
c= con.cursor()
c.execute("SELECT accid FROM credentials WHERE accountname = ?", (user,))
global results
results=c.fetchall()
con.commit()
con.close()
con= sqlite3.connect("store.db")
c= con.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS {}(mod integer, ques integer,score integer)""".format(results))
c.execute("INSERT INTO {} Values(mod=2,ques=1, score=0)".format(results))
con.commit()
con.close()
ques()
def mod2q1page():
questionspage.destroy()
con= sqlite3.connect("login.db")
c= con.cursor()
c.execute("SELECT accid FROM credentials WHERE accountname = ?", (user,))
global results
results=c.fetchall()
con.commit()
con= sqlite3.connect("store.db")
c= con.cursor()
c.execute("INSERT OR IGNORE INTO {} VALUES(mod=2, ques=2, score=0)" .format(results))
There seems to be several things wrong here.
Format takes a variable inside the {} ... like {0}, {1} etc
Placeholders are the preferred route to take with formatting sql queries ... like you did in your SELECT
I am not sure what the issue is here but if you are trying to add columns, you need to ALTER the table ... not INSERT. INSERT will add a row item. If you can post the error, perhaps we can help a little more. To start you out though, try placeholders in lieu of format.
Also, fetchall returns a list of tuples ... need to send a tuple in sql, not a list.
for x in results:
c.execute("INSERT INTO ? (col1, col2, col3) VALUES (1, 2, 3);", x)
Edit:
I stand corrected - I ran this code:
data = [('user',)]
cursor.execute("INSERT INTO ? (id, email, password) VALUES (1, test, test);", data)
syntax error because you cannot add placeholder to table name. Read here
I used format with the {0}:
cursor.execute("INSERT INTO {0} (id, email, password) VALUES (1, test, test);".format('user'))
The query was successful. I believe that is your problem here.
found a solution:
intro.destroy()
con= sqlite3.connect("login.db")
c= con.cursor()
c.execute("SELECT accountname FROM credentials WHERE accountname = ?", (user,))
results=c.fetchone()
global tablename
tablename=" ".join(map(str, (results)))
con.commit()
con.close()
global m
m="mod"
global q
q="ques"
global s
s="score"
fieldtype="INTEGER"
con=sqlite3.connect("store.db")
c=con.cursor()
c.execute('CREATE TABLE IF NOT EXISTS {} ({fc} {ft}, {sc} {ft2}, {tc} {ft3})'\
.format(tablename, fc=m, ft=fieldtype, sc=q, ft2=fieldtype, tc=s,
ft3=fieldtype))
con.commit()
con.close()
I am coding with python and using SQLite. I need to update a table using the UPDATE and WHERE statements. The challenge is that both values for the WHERE and UPDATE statements must be variables. I have done some research and found this link Sqlite3 Updating Row Defined by a Variable and this https://www.tutorialspoint.com/sqlite/sqlite_update_query.htm
def studentlist():
'''Checks if a student is checked in any class, inserts the status into the
student list table Displays a list of all students and their class status'''
c.execute("SELECT StudentID FROM StudentTable")
all_students = c.fetchall()
c.execute("SELECT StudentID FROM CheckedInTable")
selected_student_id = c.fetchall()
print("The student id in the studentlist is:", selected_student_id,)
for i in all_students:
if i in selected_student_id:
student_attendance = 'Attending a class'
c.execute("UPDATE StudentlistTable set ClassAttend = ?", (student_attendance), "WHERE StudentID = ?", (i))
conn.commit()
else:
student_attendance = "Not in class"
c.execute("UPDATE StudentlistTable set ClassAttend = ?", (student_attendance))
conn.commit()
studentlist()
Upon running the code, I receive the following error
c.execute("UPDATE StudentlistTable set ClassAttend = ?", (student_attendance), "WHERE StudentID = ?", (i))
TypeError: function takes at most 2 arguments (4 given)
Any help would be highly appreciated.
Based on the error message you are receiving, the execute() function is expecting 2 arguments, the first for the query and the second a single tuple containing the parameters to be used in the query. Try this:
c.execute("UPDATE StudentlistTable SET ClassAttend = ? WHERE StudentID = ?",
(student_attendance, i))
Here is a good reference question which discusses your problem in greater detail:
How to use variables in SQL statement in Python?