Building on the database I've been using in the previous posts, I've cooked up a Python program that makes using the historical figures database easier.
import sqlite3
conn = sqlite3.connect("C:\\sqlite\\db\\history1.db")
curs = conn.cursor()
def viewtable():
curs.execute("SELECT * FROM historicalfigures ORDER BY Name;")
fulldump = curs.fetchall()
print("Name | Born | Died | Role | Nation")
print("======================|=======|=======|=======================|=========")
for line in fulldump:
namestr = line[0]
if len(namestr) >= 23:
namestr = namestr[0:22]
rolestr = line[3]
if len(rolestr) >= 23:
rolestr = rolestr[0:22]
nationstr = line[4]
if len(nationstr) >= 17:
nationstr = nationstr[0:16]
gapname = " " * (22 - len(namestr)) + "| "
gapborn = " | "
gapdied = " | "
gaprole = " " * (22 - len(rolestr)) + "| "
print(namestr + gapname + str(line[1]) + gapborn + str(line[2]) + gapdied + rolestr + gaprole + nationstr)
def searchtable():
print("Searching table - please select which column ")
print("Name ----(N)")
print("Born ----(B)")
print("Died ----(D)")
print("Role ----(R)")
print("Nation --(T)")
fieldchoice = input("? ")
fieldchoice = fieldchoice.lower()
if fieldchoice == "n":
term = input("What name? ")
searchterm = "Name = '" + term + "'"
elif fieldchoice == "b":
compare = input("Do you want results before ( < ), in exact year ( = ) or after ( > )? ")
term = input("Which Year? ")
searchterm = "YearBirth "+ compare + " " + term
elif fieldchoice == "d":
field = "YearDeath"
compare = input("Do you want results before ( < ), in exact year ( = ) or after ( > )? ")
term = input("Which Year? ")
searchterm = "YearDeath "+ compare + " " + term
elif fieldchoice == "r":
term = input("What Role? ")
searchterm = "Role LIKE '%"+ term +"%'"
elif fieldchoice == "t":
term = input("What Nation? ")
searchterm = "Nation LIKE '%" + term + "%'"
else:
print("Sorry, option not recognised. ")
return()
print (searchterm)
curs.execute("SELECT * FROM historicalfigures WHERE " + searchterm +";")
searchdump = curs.fetchall()
print("Name | Born | Died | Role | Nation")
print("=======================|=======|=======|=======================|=========")
for line in searchdump:
gapname = " " * (23 - len(line[0])) + "|"
gapborn = " " * 3 + "|"
gapdied = " " * 3 + "|"
gaprole = " " * (23 - len(line[3])) + "|"
print(line[0] + gapname + str(line[1]) + gapborn + str(line[2]) + gapdied + line[3] + gaprole + line[4])
def enternew():
print("Entering new record")
newname = input("Please enter new name: ")
newbirth = input("Please enter new year of birth: ")
newdeath = input("Please enter new year of death: ")
newrole = input("Please enter new role: ")
newnation = input("Please enter new nation: ")
keeper = input("Do you want to keep this new record (Y to keep, N to discard): ")
keeper = keeper.lower()
if keeper == "y":
curs.execute("INSERT INTO historicalfigures (Name, YearBirth, YearDeath, Role, Nation) VALUES ('" + newname + "', "+ newbirth +", "+ newdeath +", '" + newrole + "', '" +newnation +"');")
curs.execute("COMMIT;")
def deleterecord():
curs.execute("SELECT Name FROM historicalfigures ORDER BY Name;")
namedump = curs.fetchall()
print("Current list of names is:")
linecount = 0
for line in namedump:
print(linecount + " - " + line[0])
linecount += 1
whichline = input("Enter number of row to be deleted: ")
whichline = int(whichline)
delname = namedump[whichline][0]
confirm = input("Please confirm (Y) or cancel (N) deleting record for " + delname +": ")
confirm = confirm.lower()
if confirm == 'y':
curs.execute("DELETE FROM historicalfigures WHERE Name ='" + delname + "';")
curs.execute("COMMIT;")
def updaterecord():
curs.execute("SELECT Name FROM historicalfigures ORDER BY Name;")
namedump = curs.fetchall()
print("Current list of names is:")
linecount = 0
for line in namedump:
print(str(linecount) + " - " + line[0])
linecount += 1
whichline = input("Enter number of row to be changed: ")
whichline = int(whichline)
updatename = namedump[whichline][0]
curs.execute("SELECT * FROM historicalfigures WHERE Name = '"+ updatename+"';")
changedump = curs.fetchall()
coltuple = ('Name', 'YearBirth', 'YearDeath', 'Role', 'Nation')
colcount = 0
for col in changedump[0]:
print (str(colcount), coltuple[colcount], changedump[0][colcount])
colcount += 1
colchoice = input("Please enter number of column to change: ")
colchoice = int(colchoice)
newvalue = input("Please enter new value for this column: ")
if colchoice == 0 or colchoice == 3 or colchoice == 4:
newvalue = "'"+ newvalue +"'"
print("About to change "+ coltuple[colchoice] +" to " + newvalue + " for "+ updatename)
confirmchange = input("Confirm(Y) or discard (N): ")
confirmchange = confirmchange.lower()
if confirmchange == 'y':
curs.execute("UPDATE historicalfigures SET "+ coltuple[colchoice] +" = "+ newvalue +" WHERE Name = '" + updatename + "';")
curs.execute("COMMIT;")
print ("Historical Figures Table")
print ("========================")
cont = True
while cont == True:
print ("Main menu - Please select an option")
print ("View whole table ---V")
print ("Search table -------S")
print ("Enter new record ---E")
print ("Delete record ------D")
print ("Update record ------U")
print ("Quit Program -------Q")
optchoice = input("? ")
optchoice = optchoice.lower()
if optchoice == 'v':
viewtable()
elif optchoice == 's':
searchtable()
elif optchoice == 'e':
enternew()
elif optchoice == 'd':
deleterecord()
elif optchoice == 'u':
updaterecord()
elif optchoice == 'q':
conn.close()
cont = False
else:
print("Sorry, not recognised")
So this is big - bigger than any other program I've created for this blog. And what are the results like?
========= RESTART: C:\Users\pc\Documents\Programming\historical_2.py =========
Historical Figures Table
========================
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? v
Name | Born | Died | Role | Nation
======================|=======|=======|=======================|=========
Cardinal Thomas Wolsey| 1473 | 1530 | Churchman & Politician | England
Christopher Columbus | 1451 | 1509 | Explorer | Spain & Italy
Elizabeth I | 1533 | 1603 | Monarch | England
Ferdinand Magellan | 1480 | 1521 | Explorer | Portugal
Francis Drake | 1540 | 1596 | Explorer & Naval Comma | England
Henry VIII | 1491 | 1547 | Monarch | England
Leonardo da Vinci | 1452 | 1519 | Artist | Italy
Niccolo Machiavelli | 1469 | 1527 | Politician & Author | Italy (Florence)
William Caxton | 1422 | 1491 | Publisher | England
William Shakespeare | 1564 | 1616 | Author & Playwright | England
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
?
========= RESTART: C:\Users\pc\Documents\Programming\historical_2.py =========
Historical Figures Table
========================
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? v
Name | Born | Died | Role | Nation
======================|=======|=======|=======================|=========
Cardinal Thomas Wolsey| 1473 | 1530 | Churchman & Politician| England
Christopher Columbus | 1451 | 1509 | Explorer | Spain & Italy
Elizabeth I | 1533 | 1603 | Monarch | England
Ferdinand Magellan | 1480 | 1521 | Explorer | Portugal
Francis Drake | 1540 | 1596 | Explorer & Naval Comma| England
Henry VIII | 1491 | 1547 | Monarch | England
Leonardo da Vinci | 1452 | 1519 | Artist | Italy
Niccolo Machiavelli | 1469 | 1527 | Politician & Author | Italy (Florence)
William Caxton | 1422 | 1491 | Publisher | England
William Shakespeare | 1564 | 1616 | Author & Playwright | England
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? e
Entering new record
Please enter new name: Dante Alighieri
Please enter new year of birth: 1265
Please enter new year of death: 1321
Please enter new role: Author & Poet
Please enter new nation: Italy (Florence)
Do you want to keep this new record (Y to keep, N to discard): y
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? y
Sorry, not recognised
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? e
Entering new record
Please enter new name: Michelangelo di Lodovico Buonarotti Simoni
Please enter new year of birth: 1475
Please enter new year of death: 1564
Please enter new role: Artist
Please enter new nation: Italy (Florence & Rome)
Do you want to keep this new record (Y to keep, N to discard): y
Main menu - Please select an option
View whole table ---V
Search table -------S
Enter new record ---E
Delete record ------D
Update record ------U
Quit Program -------Q
? q
>>>
There are plenty of points I would like to make about this program:
- It relies on functions to split the program into manageable chunks. Each choice (except Q to quit) in the main menu calls on a user-defined function defined before the main program.
- I didn't need to reopen the connection to the database or recreate the cursor object when in the user-defined functions - they can automatically use the ones from the main program.
- The function viewtable()is about taking the list of tuples returned from SQLite by curs.fetchall() and presenting it neatly on the IDLE command line. One unforeseen problem is this blog has a narrower column width than the IDLE interface, so I've shrunk the font on the output to get the table to look neat.
- In viewtable() I have used slicing strings to make oversized text strings fit into columns, and repeating strings with * to fill with the right number of spaces. I'm hoping that all dates just have 4 digits.
- In searchtable() I have used user choices to assemble an SQL command. For searching both role and nation I have used the LIKE SQL comparator. This looks for records in a less exacting way than = , and as here will find records where the searched-for string is part of that record's data in that field. So when searching the Role column, LIKE allows me to find author in a record whose Role field is author & playwright.
- All functions that involve changing the database have a confirming part, where if the user confirms they want to make the change, the COMMIT SQLite command is used.
- Both deleterecord() and updaterecord() present a list of names (from the first column in the database) and allows the user to select the name by its index (its numerical position in the list). This name is then used as the identifier to make sure the right record in the database is updated or deleted as appropriate.