-1
#Delete suspense window
class dWindow(QtGui.QMainWindow, Ui_dWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
        self.setupUi(self)

        for row in cursor.execute("SELECT FIRSTNAME FROM Staff"):
            self.comboUser.addItems(row)
        con.close()

        self.btnDeleteSuspense.clicked.connect(self.btnDeleteSuspense_Clicked)

    def btnDeleteSuspense_Clicked(self):
        user = self.comboUser.currentText() #finds selected user
        date = self.dateEdit.date().toString("M/d/yyyy")
        numrecord = cursor.execute() ??

Here is a sample DB and program file to further help me explain

programsample

dbsample

I have created variables to hold the selection of the combobox and the dateEdit box.

The next step (the one I'm struggling with) is to then use those variables in an SQL query that will first find the count of rows with the selected user name and having a date <= than the selected date. That will populate the numrecord variable so that I can display a "This will delete 'x' rows, are you sure?"

If the user selects yes then I will then use the variable in a delete query to delete the selected rows.

I believe if I can figure out how to use the variables I have in a SQL query then the DELETE query should be rather simple.

An example of a possible DELETE query to show what I'm trying to do

cursor.execute("DELETE TO, count(*) FROM Suspense where TO = [user] and DATE = [date]")

I know that is wrong but maybe it will help clarify.

I hope I have explained my question fully and I appreciate any help provided.

Edit: Thanks so much!!

Just before I saw that you had posted this I figured it out.

What I came up with was the following:

qdate = self.dateTimeEdit.dateTime().toPyDateTime() #grabs the raw datetime from the QDateTimeEdit object and converts to python datetime

query = "SELECT DATE FROM Suspense WHERE DATE >= ?"  #creates the query using ? as a placeholder for variable

cursor.execute(query, (qdate,)) #executes the query and passes qdate as a tuple to the placeholder

With this knowledge I can recreate my queries to include both variables.

ricketyCode
  • 11
  • 1
  • 4
  • What is the schema of the *suspense* table? Is `TO` a string column, or a foreign key column? – Brendan Abel Sep 27 '16 at 05:44
  • String column. The dbsample image is a section of the suspense table showing the columns that I will be targeting with my queries to find the # of rows matching the variables and then delete those rows – ricketyCode Sep 27 '16 at 06:04

3 Answers3

1

As mentioned in a comment to another answer, you should be using a proper parameterized query, for example:

# assumes that autocommit=False (the default)
crsr = conn.cursor()
sql = "DELETE FROM [Suspense] WHERE [TO]=? AND [DATE]<=?"
user = self.comboUser.currentText()  # as before
date = self.dateEdit.date()  # Note: no .toString(...) required
params = (user, date)
crsr.execute(sql, params)
msg = "About to delete {} row(s). Proceed?".format(crsr.rowcount)
if my_confirmation_dialog(msg):
    conn.commit()
else:
    conn.rollback()
Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
  • Thanks so much! I posted an edit explaining what I found out to fix it just before you posted. BTW how do I tag someone with a space in their name? – ricketyCode Sep 28 '16 at 20:29
  • @ricketyCode re: *"how do I tag someone with a space in their name?"* - You can just use the first few characters (e.g., @Gord) provided that it uniquely identifies a participant in the comment thread. If you are posting from a web browser then after typing "@" and the first letter you should also get a pop-up with valid selections (e.g., @GordThompson). – Gord Thompson Sep 29 '16 at 23:30
1

What I came up with was the following:

qdate = self.dateTimeEdit.dateTime().toPyDateTime() #grabs the raw datetime from the QDateTimeEdit object and converts to python datetime

query = "SELECT DATE FROM Suspense WHERE DATE >= ?"  #creates the query using ? as a placeholder for variable

cursor.execute(query, (qdate,)) #executes the query and passes qdate as a tuple to the plac

With this knowledge I can now add both variables to the query as needed.

Thanks everyone for their help, especially Gord Thompson!

ricketyCode
  • 11
  • 1
  • 4
0

You use the DELETE sql command.

This assumes your DATE field is actually a date field and not a string field.

user = self.comboUser.currentText()
date = self.dateEdit.date().toString("yyyy-MM-dd")
cmd = "DELETE FROM Suspense WHERE TO = '{}' AND DATE >= '{}'".format(user, date)
cursor.execute(cmd)

Also, you may want to look into using an ORM framework (sqlalchemy is probably the most popular, but there are others). It's best to avoid manually constructing sql queries if possible.

Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • I think I should have clarified better. The "Staff" table isn't relevant to the DELETE query (the table being targeted with the DELETE is 'Suspense'), it's merely to clarify which user is being targeted in the TO column. I'm targeting a selection of rows with TO and DATE where DATE is equal to or older than the selected date. The primary key of the Suspense table is COUNTER, but I don't think it's useful in this case since I don't care if the rows are duplicate or not I'm merely deleting all rows for a specific user equal to or older than the date specified. – ricketyCode Sep 27 '16 at 04:53
  • So you'd like to delete rows in the SUSPENSE table based off of a selection from the STAFF table? Sorry if I'm reading this wrong, but I'm not fully awake. If so, however, you need to look into `joins`. – amitchone Sep 27 '16 at 07:01
  • No I only use the Staff table to populate the combobox. After a name and date is clicked on in the window the actual delete will be targeting the TO and DATE fields of the Suspense table. – ricketyCode Sep 27 '16 at 12:38
  • 1
    @BrendanAbel. The [execute](http://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.execute) method supports parameterization, so there's no need to use `format`. It will ensure quotes are escaped correctly as well. – ekhumoro Sep 27 '16 at 16:09
  • Hello, I tried it exactly like that and here is the traceback I get: File "C:\Dev\Workspace\Suspense Utilities\main.py", line 61, in btnDeleteSuspense_Clicked cursor.execute(cmd) pypyodbc.DataError: ('22018', '[22018] [Microsoft][ODBC Microsoft Access Driver] Data type mismatch in criteria expression.') The "TO" column is Short Text data type and the "DATE" column is Date/Time data type if that helps – ricketyCode Sep 27 '16 at 16:46
  • I think I may have found it. Even though the DATE column only shows dates I queried the column and it returns in datetime format (2016, 8, 26, 0, 0) I will do some tests and report back – ricketyCode Sep 27 '16 at 16:53
  • I'm not sure what type of datetime functions MS Access supports (I'm guessing none). You could just provide the hour minute and seconds - `yyyy-MM-dd 00:00:00` – Brendan Abel Sep 27 '16 at 17:07