[Tutor] Looking for help in sqlite3 UPDATE and DELETE selection in treeview (ttk tkinter)

Alan Gauld alan.gauld at yahoo.co.uk
Wed May 12 19:19:17 EDT 2021


On 12/05/2021 13:46, Piotr Mazek wrote:

> I'm writing application to manage sqlite3 database in window made in tkinter
> with treeview.
> 
> Successfully wrote two functions: to show database, and to add new row.

Well done, the rest should be straightforward.

> But stuck on Update and delete selection. I think there are some stupid
> mistakes, but can't see them.

There are a few odd things in your code. See comments below...

>     def updateRecord():
> 
>         def updateR():
>             conn = sqlite3.connect('db_member.db')
>             c = conn.cursor()
>             # INSERT into table
> # I wish to get values from selection and place them in corresponding Entry
> fields, then change some value and save new state
> 
>             c.execute("UPDATE `member` SET (:mem_id, :firstname, :lastname,
> :address)"))

First point:
This will UPDATE every row in the table. If you only want to
modify a single row you need a WHERE clause to specify
the row(or rows) affected.

Second:
I've never seen the :mem_id syntax before. I assume it substitutes the
local variable name somehow? But I can't find any documentation of that
style?

Normally I'd expect an update statement to look like:

update = """
UPDATE or ROLLBACK member
SET
mem_id=?
firstname=?
lastname=?
address=?
WHERE mem_id = ?
"""

cur.execute(update,(mem_id, firstname, lastname, address, mem_id))

>             conn.commit()
>             conn.close()
> 
>             updateRoot.destroy()

>         updateRoot = Toplevel()
>         updateRoot.title("Update record")
>         updateRoot.iconbitmap('printer.ico')
>         lbl_fname = Label(updateRoot, text="First Name")
>         lbl_fname.grid(row=0, column=0, pady=10)
>         lbl_lname = Label(updateRoot, text="Last Name")
>         lbl_lname.grid(row=1, column=0, pady=10)
>         lbl_addr = Label(updateRoot, text="Address")
>         lbl_addr.grid(row=2, column=0, pady=10)
>         en_fname = Entry(updateRoot)
>         en_fname.grid(row=0, column=1, padx=10)
>         en_lname = Entry(updateRoot)
>         en_lname.grid(row=1, column=1, padx=10)
>         en_addr = Entry(updateRoot)
>         en_addr.grid(row=2, column=1, padx=10)
>         btn = Button(updateRoot, text="Update", command=updateR)
>         btn.grid(row=3, column=1, columnspan=2, sticky='we', padx=20)
> 
>         updateRoot.mainloop()

I may be wrong but I don't think you need to call mainloop()
here, the parent mainloop() will see the events for your
TopLevel too. I think...

>     def deleteRecord():
>         conn = sqlite3.connect('db_member.db')
>         c = conn.cursor()
> 
>         # DELETE from table
>         userid = tree.selection()[0]
>         tree.delete(userid)
> 
> # here I have no idea how to delete selected row from database
> 
>         c.execute("DELETE FROM `member` WHERE mem_id = ?", (userid))

You need to pass the arguments as a tuple, simply putting parens around
is not enough, you need a comma after the userid, its the comma that
makes it a tuple.

Also, I notice that you are putting the table name in quotes. That
should not be necessary (and may be an error?) since the entire SQL
statement is already in quotes. I certainly never quote table names
in my SQL. That may be part of the source of  the problem?


>         conn.commit()
>         conn.close()
Finally, I notice you are not detecting errors. You should really
use a try/except to catch database error exceptions and take
action (eg Rollback). You can re-raise them during debugging
if you want to see the stack-trace.

Of course you may have simplified the code for clarity in which
case just ignore me! :-)

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list