Python/MySQL SELECT, Update and Fetch in same query - python

I want to SELECT and UPDATE in one query.
In my database, I have category_ids that needs to be checked. I want to select the last updated query by DESC and update it with runs = runs+1, so it counts up that and also automatically update the last_update field.
But for some reason, I can't fetch it
cursor.execute(
"UPDATE categorys as t1,
(SELECT category_id
FROM categorys
ORDER BY last_update
LIMIT 1) as t2
SET t1.runs = t1.runs+1
WHERE t2.category_id = t1.category_id")
row = cursor.fetchone()
print(row)
print(row) gives me None but I need the category_id here
The update works and counts up the runs+1 of the last_update DESC

mysql update doesn't return value of data changed. It only returns the Query ran ok.
you would need to execute the select statement to return the category_id.

Related

Creating a Search Record Function Python SQLite3

I am currently working on a coursework project for school and it is a database system with a user interface using Tkinter, Python and SQLite3. I have made a form to add, delete, update and search for customers. I am able to display the result from a single field, however, I am struggling to get the message box to display all the fields, which is what I would like it to do. I have attached photos of the form along with the code. Thank you in advance.
def SearchCustomer(self):
customerid = self.CustomerEntry.get();
with sqlite3.connect("LeeOpt.db") as db:
cursor = db.cursor()
search_customer = ('''SELECT * FROM Customer WHERE CustomerID = ?''')
cursor.execute(search_customer, [(customerid)])
results = cursor.fetchall()
if results:
for i in results:
tkinter.messagebox.showinfo("Notification",i[0])
It is because you showed only the first column (i[0]) from result.
Since there should be only one record for a specific customer ID, you should use fetchone() instead of fetchall(), then you can show the whole record as below:
def SearchCustomer(self):
customerid = self.CustomerEntry.get()
with sqlite3.connect("LeeOpt.db") as db:
cursor = db.cursor()
search_customer = "SELECT * FROM Customer WHERE CustomerID = ?"
cursor.execute(search_customer, [customerid])
result = cursor.fetchone() # there should be only one record for specific customer ID
if result:
tkinter.messagebox.showinfo("Notification", "\n".join(str(x) for x in result))

How can I select and delete the first row of my database?

This is my code:
db = MySQLdb.connect("localhost", "root", "raspberry", "cribdb")
curs=db.cursor()
curs.execute ("""INSERT INTO tbstatus values(NOT NULL, 'status')""")
db.commit()
number_of_rows= curs.execute("SELECT * FROM tbstatus")
if (number_of_rows <= 5):
print(number_of_rows)
else:
curs.execute("""SELECT * from tbstatus""")
row1=curs.fetchone()
db.commit()
curs.execute("""Delete from tbstatus where id = 'row1'""")
db.commit()
print("\n Record Deleted successfully ")
It has no error but the delete function is not working. I just want to delete the first row of my database after it reach its maximum limit which is 5. What should I do? THANK YOU!
Try to use limit instead of ID
curs.execute("""DELETE FROM tbstatus order by id LIMIT 1""")
First you need to define the order of the records with order by. Then you can delete just one record with limit 1
Delete from tbstatus
order by id
limit 1

Performing an SQL query for each item in a tuple

I am new to Python and am hoping someone can help me figure out how to perform an SQL query on each item in a tuple using Python.
I have a SQL Express server that contains a number of databases for a badge reader system. What I am trying to do is pull the user id's that have scanned into a particular reader, then use those id's to get the actual user names.
Currently, I am able run the query that pulls the user id's and run a query on the other table using just one id. What want to be able to do, and seem to be having an issue figuring out, is running that second query on every user id in the tuple that is created from the first query. Below is the code for the two functions I am currently using.
def get_id():
global cardholder
global cur
cur.execute("SELECT user_id FROM db.table WHERE badgereaderid = 'badgereader1'")
cardholder = []
rows = cur.fetchall()
for row in rows:
if row == None:
break
cardholder.append(row[0])
print(cardholder)
def get_name():
global cardholder
global user
global cur
cur.execute("SELECT FirstName, LastName FROM db.table WHERE user_id= '%s'" % cardholder)
while 1:
row = cur.fetchone()
if row == None:
break
user = row[0] + row[1]
Two possible options
Repeated queries in Python
for user_id in cardholder:
cur.execute("SELECT FirstName, LastName FROM db.table WHERE user_id= '%s'" % user_id)
But why not just pull all the data in the first query?
cur.execute("SELECT a.user_id, b.FirstName, b.LastName FROM db.table1 a left join bd.table2 b on a.user_id = b.user_id WHERE a.badgereaderid = 'badgereader1'")
or, use triple quotes to allow multi-line strings and make the SQL command easier to understand
cur.execute("""SELECT
a.user_id,
b.FirstName,
b.LastName
FROM db.table1 a
left join db.table2 b
on a.user_id = b.user_id
WHERE a.badgereaderid = 'badgereader1'""")
A good practice in Python is to define the data collections outside the function if you intend to use them later on in your code
Try this code:
cardholder_names = []
#pass the cardholder as a param to the function
def get_name(cardholder):
#cur is already defined as a global param, no need to do it twice
cur.execute("SELECT FirstName, LastName FROM db.table WHERE user_id='{0}'".format(cardholder))
return cur.fetchone()
#now use the for loop to iterate over all the cardholders
for holder in cardholders:
cardholder_name = get_name(holder)
cardholder_names.append( {"name" : cardholder_name[0], "surname" : cardholder_name[1]})

(Python) cursor.execute(sql)

def makeProductTable():
"""This creates a database with a blank table."""
with connect("products.db") as db:
cursor = db.cursor()
cursor.execute("""
CREATE TABLE Product(
ProductID integer,
GTIN integer,
Description string,
StockLevel integer,
Primary Key(ProductID));""")
db.commit()
def editStockLevel():
with connect("products.db") as db:
cursor = db.cursor()
Product_ID=input("Please enter the id of the product you would like to change: ")
Stock_Update=input("Please enter the new stock level: ")
sql = "update product set StockLevel = ('Stock_Update') where ProductID = ('Product_ID');"
cursor.execute(sql)
db.commit()
return "Stock Level Updated."
The first function is used to make the table and it shows my column titles, the second function is needed to update a specific value in the table.
But when this is ran the inputs are executed, however when all show all the products in the table the value for stock level doesn't change.
So I think the problem has something to do with the cursor.execute(sql) line.
Or something like this?
cur.execute("UPDATE Product set StockLevel = ? where ProductID = ?",(Stock_Update,Product_ID))
Yes; you're passing literal strings, instead of the values returned from your input calls. You need to use parameters in the statement and pass thme to the execute call.
sql= "update product set StockLevel = %s where ProductID = %s;"
cursor.execute(sql, (Stock_Update, Product_ID))

Python Sqlite3 - how to work very very long WHERE IN() clause

[Using Python3.x]
The basic idea is that I have to run a first query to pull a long list of IDs (text) (about a million IDs) and use those IDs in an IN() clause in a WHERE statement in another query. I'm using python string formatting to make this happen, and works well if the number of IDs is small - say 100k - but gives me an error (pyodbc.Error: ('08S01', '[08S01] [MySQL][ODBC 5.2(a) Driver][mysqld-5.5.31-MariaDB-log]MySQL server has gone away (2006) (SQLExecDirectW)')) when the set is indeed about a million IDs long.
I tried to read into it a bit and think it might have something with the default(?) limits set by SQLite. Also I am wondering if I'm approaching this in the right way anyway.
Here's my code:
Step 1: Getting the IDs
def get_device_ids(con_str, query, tb_name):
local_con = lite.connect('temp.db')
local_cur = local_con.cursor()
local_cur.execute("DROP TABLE IF EXISTS {};".format(tb_name))
local_cur.execute("CREATE TABLE {} (id TEXT PRIMARY KEY, \
lang TEXT, first_date DATETIME);".format(tb_name))
data = create_external_con(con_str, query)
device_id_set = set()
with local_con:
for row in data:
device_id_set.update([row[0]])
local_cur.execute("INSERT INTO srv(id, lang, \
first_date) VALUES (?,?,?);", (row))
lid = local_cur.lastrowid
print("Number of rows inserted into SRV: {}".format(lid))
return device_id_set
Step 2: Generating the query with 'dynamic' IN() clause
def gen_queries(ids):
ids_list = str(', '.join("'" + id_ +"'" for id_ in ids))
query = """
SELECT e.id,
e.field2,
e.field3
FROM table e
WHERE e.id IN ({})
""".format(ids_list)
return query
Step 3: Using that query in another INSERT query
This is where things go wrong
def get_data(con_str, query, tb_name):
local_con = lite.connect('temp.db')
local_cur = local_con.cursor()
local_cur.execute("DROP TABLE IF EXISTS {};".format(tb_name))
local_cur.execute("CREATE TABLE {} (id TEXT, field1 INTEGER, \
field2 TEXT, field3 TEXT, field4 INTEGER, \
PRIMARY KEY(id, field1));".format(tb_name))
data = create_external_con(con_str, query) # <== THIS IS WHERE THAT QUERY IS INSERTED
device_id_set = set()
with local_con:
for row in data:
device_id_set.update(row[1])
local_cur.execute("INSERT INTO table2(id, field1, field2, field3, \
field4) VALUES (?,?,?,?,?);", (row))
lid = local_cur.lastrowid
print("Number of rows inserted into table2: {}".format(lid))
Any help is very much appreciated!
Edit
This is probably the right solution to my problem, however when I try to use "SET SESSION max_allowed_packet=104857600" I get the error: SESSION variable 'max_allowed_packet' is read-only. Use SET GLOBAL to assign the value (1621). Then when I try to change SESSION to GLOBAL i get an access denied message.
Insert the IDs into a (temporary) table in the same database, and then use:
... WHERE e.ID IN (SELECT ID FROM TempTable)

Categories

Resources