I have a form which 4 input fields, when clicking the submit button, I'm fetching results from the database based on those 4 inputs. I'm not forcing the user to enter any input, so I could get all blank inputs or part of them empty. The more inputs the user fills, the results from the database will be more precise.
My problem is how to build the where part of the query dynamically using only the place holders which are populated. here is my query. This way if one of the inputs are blank, the query will not fetch anything while my intention is the opposite: if the input is blank, do not take into account while querying the database.
cursor.execute('''
SELECT name, id, gender, age, address, phones, mails, gender, age, hair_color
FROM persons
WHERE
name = ? AND
id = ? AND
gender = ? AND
age = ?
''', (name_input, id_input, gender_input, age_input))
You could create the WHERE clause dynamically:
sql = "SELECT ... WHERE 1"
parameters = []
if name_input != "":
sql += " AND name = ?"
parameters += [name_input]
if id_input != "":
sql += " AND id = ?"
parameters += [id_input]
...
Alternatively, rewrite the WHERE clause so that empty values are ignored:
SELECT ... WHERE (name = ?1 OR ?1 = '') AND (id = ?2 OR ?2 = '') AND ...
(?n specifies the n-th parameter.)
Related
I am trying to verify user by ensuring only registered users with a department can have access to the department template in the application. I want a situation whereby once a user enters his login details, his department would be checked by the system and through his login detail, the template for his department would be open. So it is the work of the application to identify the department he is through his login details and open the right template for him.
I want the system to loop through the other departments if he's not found in the first department, to see if he is registered in one of the others. Here's my code:
def verifyUser(self):
self.db_connection()
try:
username = self.user.text()
password = self.pwtx.text()
result = self.conn.execute(
"""SELECT *
FROM newUser_general
WHERE userID = ? AND dept = 'Comp Dept' """,
(username, password)
) # include dept
print("SQL Statement executed")
if (len(result.fetchall()) > 0):
print("user found")
self.compDept()
else:
print("user not found")
except Exception as err:
print(err)
I've finally gotten it right.
I used an if and else conditional statement.
First I instantiated the departments like dept1 = "Comp sci", dept2 = "Statistics"
Then I did
```if dept1:
result = self.cursor.connect(result = self.conn.execute(
"""SELECT *
FROM newUser_general
WHERE userID = ? AND dept = 'Comp Dept' """,
(username, password))
else if dept2:
result = self.cursor.connect(result = self.conn.execute(
"""SELECT *
FROM newUser_general
WHERE userID = ? AND dept = 'Statistics' """,
(username, password))```
Suppose you have a department table in your database, you can select all the department names or better their unique identifier first and store them in an array. Then you loop through the array and execute a request every time.
Another solution is to store the department of each user in the user table. Then when in the login process you can select his dept id.
I am trying to add a feature to my program where a teacher sets homework to users from a class they've made. There is a table for users where each user has a unique UserID, classname, firstname and surname. I am trying to take the userIDs of students who are in a certain class, and insert them into a HomeworkSet table. I am able to retrieve the userIDs successfully, but when I insert them into the HomeworkSet table, the values appear as (for example) ('2a1910e919a84230bfc2a7111160cade',), and I am not sure how I am meant to remove the brackets and apostraphes.
def Class_sethw():
homeworktoset = Homework_To_Set.get()
#print (homeworktoset)
conn = sqlite3.connect('MyComputerScience.db')
c = conn.cursor()
homeworkID = c.execute("SELECT HWID FROM HomeworkInfo WHERE HomeworkName = ?", (homeworktoset, )).fetchone()
print (homeworkID)
c.execute("SELECT UserID FROM users WHERE ClassName = ?", (ClassName_SetHWR, ))
homeworksetlist = c.fetchall()
print (homeworksetlist)
for i in (homeworksetlist):
#x = i
#firstname, lastname = x.split(" ")
c.execute('insert INTO HomeworkSet (HWID, StudentID)VALUES(?,?);', ((homeworkID[0]), str(i)))
conn.commit()
Label(sethw, text = "Homework Set!", fg = "GREEN").place(relx=0.205, rely=0.445, height=34, width=97)
This is the code I have used.
You should change this line:
for i in (homeworksetlist):
to:
for i in homeworksetlist:
I am trying to update my user detail with Python and SQLite.
The aim is to upgrade all the columns of my user in one go.
My code is:
def update():
new_username = input("Input your NEW username:\n")
new_firstname = input("Input your NEW firstname:\n")
new_lastname = input("Input your NEW lastname:\n")
new_email = input("Input your NEW email:\n")
new_password = input("Input your NEW password:\n")
update_customer =("""UPDATE customer SET username = ? AND firstname = ? AND lastname = ? AND email = ? AND password = ?""")
cursor.execute(update_customer, [(new_username), (new_firstname), (new_lastname), (new_email), (new_password)])
I inspected the database before and after running my python function. However, the changes are not saved into the database. Nothing changes but the username that disappears.
You don't use AND for additional columns to be SET. Instead you separate the columns to be SET with a comma.
So you want
update_customer =("""UPDATE customer SET username = ?, firstname = ?, lastname = ?, email = ?, password = ?""")
and then a WHERE clause if not setting all rows to the same values.
As per :-
SQL As Understood By SQLite - UPDATE
You need to save changes after you completed the transaction.
cursor = conn.cursor() # Get cursor
cursor.execute(...) # Execute some SQL queries
# This is the line you've missed.
# You need to call this function every time you update the data in database.
cursor.commit()
Also, your SQL syntax for the "UPDATE" command is not correct. Use commas instead of "AND" when specifying multiple columns to be changed. Like this:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
I have been working on this function in python. I intend for it to iterate over a list of phone numbers, checking with a database to see whether the number has been used yet or not. If it has been used, it should remove the phone number from the list and choose another and check the new one until an unused one has been found and return the unused one. If it has not been used, it should simply just return the number. However, after one run, it picks a number, checks it, runs, and then enters it into the database. The next run deletes the previously used number, and picks another that hasn't been used. It continues to run and enters this number into the database. The third run does not delete the previously used number from the list, but it still picks a new one regardless. Although this still works, when the numbers run out, since there are no others to pick, it continues using the last number in the list for every following run of the script. Sorry if the code is a bit sloppy right now, I am in a bit of a rush and this is only a script I have been messing around with. I hope this is clear, and not too confusing. If I need to clear any confusion, I will be glad too.
Edit: Sorry, I forgot to mention that these phone numbers are constantly grabbed from a website by another script. These set of numbers listed below is just a dummy set for testing. So in the end, I am needing to see if these recently grabbed numbers have been used by checking with the database tables.
import random
import names
##############################Information Variables##################################
emailAddress = "Fakeemail#mail.com"
titleValues = [0,1] #0 is 'Mr.', 1 is 'Mrs.'
country = 'Schwifty'
title = random.choice(titleValues)
#Generate a random name based on gender
if title == 1:
firstName = names.get_first_name(gender= 'female')
else:
firstName = names.get_first_name(gender= 'male')
lastName = names.get_last_name()
fullName = firstName + ' ' + lastName
print(fullName)
phoneNumber = '111-222-3333'
#########################################################
import sqlite3
import time
import datetime
conn = sqlite3.connect('accounts.db')
c = conn.cursor()
def createTable():
c.execute('CREATE TABLE IF NOT EXISTS accounts(Email TEXT, Name TEXT, Title TEXT, PhoneNumber TEXT, Country TEXT, DateStamp TEXT)')
def dynamic_data_entry(email, name, title, phone, country):
unix = time.time()
date = str(datetime.datetime.fromtimestamp (unix).strftime('%Y-%m-%d %H:%M:%S'))
c.execute('INSERT INTO accounts (Email, Name, Title, PhoneNumber, Country, DateStamp) VALUES (?, ?, ?, ?, ?, ?)', (email, name, title, phone, country, date))
conn.commit()
createTable()
#################################TEST NUMBER CHECK###########################
phoneNumbers = ['111-222-3333', '444-555-6666', '777-888-9999', '123-456-7890', '321-321-321']
def checkNumber(a):
c.execute("SELECT * FROM accounts WHERE PhoneNumber = ?", (a,))
row = c.fetchall()
if row:
print("Phone number has already been used, choosing another and deleting current from list.")
phoneNumbers.remove(a)
a = random.choice(phoneNumbers)
checkNumber(a)
elif row == False:
print("Number is fresh and new, using " + a)
return a
elif row == None:
print('No new phone numbers to use, exiting... ')
exit()
# for num in phoneNumbers:
# checkNumber(num)
# print(num)
checkNumber(phoneNumber)
print(phoneNumbers)
print('working')
##########################################
# INSERT DATA TO DB #
##########################################
#Insert information to database in this order: email, name, title, phone, country
dynamic_data_entry(emailAddress, fullName, title, phoneNumber, country)
conn.commit()
c.close()
conn.close()
Don’t do this. Populate a table with your phone numbers and update each phone number record with a field like ‘used’ once used.
Always keep state and data modeling in the database where possible. It is made for it.
Update in response to OP:
Create a separate table for phone numbers and replace your number field in the accounts table with a foreign key id to the primary key of the phone number table. This is called maintaining an object model or data model, so that if you want to query accounts, you have the data you need via foreign key, and if you just want phone numbers you can query the phone numbers table directly.
This way your phone number ‘objects’ can have their own attributes like ‘already called’ or ‘on do not call list’ without muddying up your accounts ‘object’.
If you want to insert a new account, you should first insert your new phone number 'object' into the phone number table and return the id, and then use that in your account insert.
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]})