I want to delete the whole row when user enters the id. If it matches, I completely delete whole row from table.
#staticmethod
def close_account(value):
check()
rows = cur.fetchall()
for row in rows:
if rows is None:
print("Sorry It's an Empty.............. ")
return True
elif rows[0] == value:
del_row = "Delete From customer where id = value"
cur.execute(del_row)
return True
It shows error in del_row that:
value is unable to resolve column value
Even if I enter the id = 1 it also does not delete the row.
Considering your id attribute is a string, change this line:
del_row = "Delete From customer where id = value"
to:
del_row = "Delete From customer where id = %s" % value
The way you have it, the database is trying to delete DELETE FROM customer WHERE id="value", whereas your goal is to replace value with the function parameter (e.g. DELETE FROM customer WHERE id="123"
Disclaimer: This solution makes your code susceptible to SQL injection
There are a couple of problems here. Primarily you're not passing a value in for the id = X condition in your query, so you'll need to do that - preferably using a parameterized query, that looks like this:
del_row = "DELETE FROM customer WHERE id = %s"
cur.execute(del_row, (1))
Your second problem is the assumption that the row ID is 1, when this may not be the case. If your ID field is auto incrementing, then it may be far greater than that. If your original query is returning the ID as a column, you should be able to retrieve the row ID using something like:
row[0]
Which, when passed into the first code block, means you end up with something like this:
#staticmethod
def close_account(value):
check()
rows = cur.fetchall()
for row in rows:
if rows is None:
print("Sorry It's an Empty.............. ")
return True
elif rows[0] == value:
del_row = "DELETE FROM customer WHERE id = %s"
cur.execute(del_row, row[0])
return True
"Delete From customer where id = %s" % value
will possibly get you what you want. On the other hand, it's a bad idea to programatically walk through all rows of the database to find a single one to delete, but I guess there are even bigger fish to fry first...
Related
I'm trying to create a script which will check if entry is in connected database, if found it will return entry and if not it will ask if user wants to add it. Script is connecting db without problems, and retrun correct information when entry is found. But when entry is not in db nothing is returned back. I tried two different ways
Tuple doesn't exist:
# get vrn
def vrn_exist():
vrn = input('Registration Number: ')
vrn = vrn.upper()
# check if vrn is in database
for row in cursor.execute("SELECT * FROM vw_vehicles WHERE regnum= ?", [vrn]):
cursor.fetchone()
if not row:
print("NO")
continue
else:
print("YES")
len of tuple:
for row in cursor.execute("SELECT * FROM vw_vehicles WHERE regnum= ?", [vrn]):
data = cursor.fetchone()
# print(row)
# return True
# if entry is in database show details
if len(row) != 0:
car_details(row)
# if entry not in database insert new line
elif len(data) == 0:
print('Car not in db. Would you like to add it?')
Since you're using fetchone it will return None if no data is match in your query.
for row in cursor.execute("SELECT * FROM vw_vehicles WHERE regnum= ?", [vrn]):
data=cursor.fetchone()
#if entry is in database show details
if data != None:
car_details(row)
#if entry not in database insert new line
elif data == None:
print('Car not in db. Would you like to add it?')
Rather than using a loop to process one result, ask the database for the first row using fetchone(). If there's no record, it'll return None, so you can react accordingly:
data = cursor.execute("SELECT * FROM vw_vehicles WHERE regnum=?;", [vrn]).fetchone()
if data is None:
print("Car not in db. Would you like to add it?")
else:
car_details(data)
I am working on a project and in that, I've to work on sql. In the code, I've to work on a single row to match the values of a person.
def userid():
os.system('cls')
ii = input("enter your User ID: ")
curs.execute("SELECT ID FROM users") #shows ID row of users table
rows = curs.fetchall() #fetch all data of ID row
if (ii,) in rows: #if value of ii is in the row, condition evaluates
password()
else:
exit()
def password():
ps = getpass.getpass("enter your pin: ")
curs.execute("SELECT pin FROM users") #shows PIN row of users table
row = curs.fetchall() #fetch all data of pin row
if (ps,) in row: #if data in row matches with data in ps, condition evaluates
main()
else:
exit()
this is the code and you can see, in the first function, I am successful in fetching user ID but when it comes to passwords, I want to match the password in the row containing the UserId entered by the user. But instead, all passwords it contains is getting matched and error is occurring.
recently I discovered a keyword fetchone() but am not sure how to use it or it would work or not.
Please help me, how can I work on only one row in sql using python.
You need to use WHERE clauses to filter the query results before the database returns them. For example
SELECT ID, PIN FROM users WHERE ID = 42
will return only the id and pin for the user with id 42, or nothing if there is no row with this id.
Using WHERE clauses, we can change your code like this:
def userid():
os.system('cls')
ii = input("enter your User ID: ")
# I'm guessing ID is an integer value in the database?
id_ = int(ii)
# fetch matching id
curs.execute("SELECT ID FROM users WHERE ID = %s", (id_,))
row = curs.fetchone() #fetch all data of ID row
if row: # if the query returned a row, the id exists
password(id_)
else:
exit()
def password(id_):
ps = getpass.getpass("enter your pin: ")
# Fetch the PIN only for our user's ID
curs.execute("SELECT pin FROM users WHERE ID = %s", (id_,))
row = curs.fetchone() #fetch all data of pin row
# if data in row matches with data in ps, condition evaluates
if (ps,) in row:
main()
else:
exit()
Note that when checking credentials like this, it's common to get the id and password and check them both in a single query:
id_ = int(input('What is your id number?'))
password = getpass.getpass('What is your PIN?')
cur.execute("""SELECT id, password FROM users WHERE id = %s AND password = %s""",
(id_, password))
This is more efficient, because only one query is sent to the database, and potentially more secure, because if it fails the users does not know whether the id or password is wrong.
I am currently producing a stock management system. All of the code so far works, however i have a variable which asks a user to input an ingredient name. If the ingredient name if found within the "inventory" table of the database i have created, then the record will be displayed to the user. Within each record, there are the fields: Ingredient, stock_level, Price, and Retailer. I'm not sure how to output the whole record to the user.
I have tried using the print(fetchone()), however if an ingredient is held in the database, "None" is outputted instead of the actual record
def searchIngredient():
found=0
while found == 0:
ingredient = input("Enter an ingredient name: ")
if len(ingredient) < 3:
print("Ingredient name must be three or more characters long")
continue
with sqlite3.connect("Inventory.db") as db:
cursor = db.cursor()
findIngredient = ("SELECT * FROM Inventory WHERE Ingredient=?")
cursor.execute(findIngredient, [(ingredient)])
if cursor.fetchall():
print(fetchone())
else:
found = 0
print("Ingredient does not exist in Inventory")
tryAgain = input("Do you want to enter another Retailer? Y or N ")
if tryAgain.lower() == "n":
mainMenu()
time.sleep(2)
mainMenu()
When run with the rest of the code, the user is asked to input an ingredient name (the format check works if string is less than three characters). With the fetchone() function, "None" is outputted when an ingredient name what exists in the db is entered. If the ingredient does not exist, the code works also. It is just the case of outputting the record to the user.
You are not fetching the record, instead:
# returns a list
for rec in cursor.fetchall():
# do something
# or
while True:
rec = cursor.fetchone()
if not rec:
break
# do something
Since fetch all the records can cause a very large list, it is recommended to loop over the records until you met None - no more to read. Look into the doc for more information.
Also Python has a standard lib logging. You don't have to print.
Example:
logger = logging.getLogger("SQL query")
logger.setLevel(logging.DEBUG)
logger.info("QUERY: %s" % query)
You can save it to a file:
hdlr = logging.FileHandler('query.log')
logger.addHandler(hdlr)
See the cookbook for more examples.
I am trying to place a condition after the for loop. It will print the word available if the retrieved rows is not equal to zero, however if I would be entering a value which is not stored in my database, it will return a message. My problem here is that, if I'd be inputting value that isn't stored on my database, it would not go to the else statement. I'm new to this. What would be my mistake in this function?
def search(title):
query = "SELECT * FROM books WHERE title = %s"
entry = (title,)
try:
conn = mysql.connector.connect(user='root', password='', database='python_mysql') # connect to the database server
cursor = conn.cursor()
cursor.execute(query, entry)
rows = cursor.fetchall()
for row in rows:
if row != 0:
print('Available')
else:
print('No available copies of the said book in the library')
except Error as e:
print(e)
finally:
cursor.close()
conn.close()
def main():
title = input("Enter book title: ")
search(title)
if __name__ == '__main__':
main()
Quite apart from the 0/NULL confusion, your logic is wrong. If there are no matching rows, you won't get a 0 as the value of a row; in fact you won't get any rows at all, and you will never even get into the for loop.
A much better way to do this would be simply run a COUNT query, get the single result with fetchone(), and check that directly.
query = "SELECT COUNT(*) FROM books WHERE title = %s"
entry = (title,)
try:
conn = mysql.connector.connect(user='root', password='', database='python_mysql') # connect to the database server
cursor = conn.cursor()
cursor.execute(query, entry)
result = cursor.fetchone()
if result != 0:
print('Available')
else:
print('No available copies of the said book in the library')
First of all NULL in python is called None.
Next:
according to documentation:
"The method fetches all (or all remaining) rows of a query result set and returns a list of tuples. If no more rows are available, it returns an empty list.
"
enpty list is not None
>>> row = []
>>> row is None
False
So you need to redesign your if statment in the way like this:
for i in rows:
if i:
blah-blah
else:
blah-blah-blah
In python you should check for None not NULL. In your code you can just check for object, if it is not None then control should go inside if otherwise else will be executed
for row in rows:
if row:
print('Available')
else:
print('No available copies of the said book in the library')
UPDATE after auther edited the question:
Now in for loop you should check for column value not the whole row. If your column name is suppose quantity then if statement should be like this
if row["quantity"] != 0:
What I am trying to is work out whether there are teachers with duplicate initials. I tried to do this by returning one value from the database file with the searched for initials. Then returning all the values with the searched initials. Then I wanted to check the first value against the second, and if they were not equal there must be a duplicate.
Is there a way of doing this and is there an easier way of doing this?
Thanks
def FindTeacherID(TeacherInitials):
with sqlite3.connect("TeacherInfo.db") as db:
cursor = db.cursor()
cursor.execute("select TeacherID from TeacherInfo where TeacherInitials = ?",(TeacherInitials,))
Value = cursor.fetchone()
cursor.execute("select TeacherID from TeacherInfo where TeacherInitials =?",(TeacherInitials,))
ValueTest = cursor.fetchall()
if Value == None:
print("There are no teachers in the list")
else:
Value = str('.'.join(str(x) for x in Value))
ValueTest = str('.'.join(str(x) for x in Value))
if ValueTest == Value:
DeleteTeacher(Value)
else:
print("There is a duplicate in teacher initials")
Just use only 1 query where you get the count:
cursor.execute("select Count(TeacherID) from TeacherInfo where TeacherInitials = ?",(TeacherInitials,))