Probleme beim Löschen eines Datensatzes in Sqlite3

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Spleen
User
Beiträge: 16
Registriert: Donnerstag 2. Juli 2009, 09:41

Hey Leute,

habe da ein Fehler bei dem ich nicht weiterkomme und hoffe, dass mir jemand weiter helfen könnte.

In einer ListCtrl werden alle meine Datensätze angezeigt. Zum Löschen wird ein Datensatz angeklickt und der Löschen-Button gedrückt. Das funktioniert auch alles ohne Probleme - bis ich einen Datensatz mit einer zweistelligen ID löschen will.

Hier mal mein Code (es sind drei Module/Dateien - für die Applikation, für das Frame, für die Funktionen)

#App:

Code: Alles auswählen

class BoaApp(wx.App):
    def OnInit(self):
        self.main = FilmarchivFrame1.create(None)
        self.main.Show()
        self.SetTopWindow(self.main)
        return True

def main():
    application = BoaApp(0)
    application.MainLoop()

if __name__ == '__main__':
    main()
#Frame:

Code: Alles auswählen

class Frame1(wx.Frame):

    def _init_coll_menuFilm_Items(self, parent):
        parent.Append(help='Einen neuen Film hinzuf\xfcgen',
              id=wxID_FRAME1MENUFILMITEMS_HINZUFUEGEN, kind=wx.ITEM_NORMAL,
              text='Hinzuf\xfcgen')
        parent.Append(help='Den aktuellen Film l\xf6schen',
              id=wxID_FRAME1MENUFILMITEMS_LOESCHEN, kind=wx.ITEM_NORMAL,
              text='L\xf6schen')


    def _init_coll_menuBar1_Menus(self, parent):
        parent.Append(menu=self.menuFilm, title='Film')


    def _init_coll_listCtrl_Film_Tabelle_Columns(self, parent):
        parent.InsertColumn(col=0, format=wx.LIST_FORMAT_RIGHT, heading='ID',
              width=-1)
        parent.InsertColumn(col=1, format=wx.LIST_FORMAT_LEFT, heading='Kunde',
              width=-1)
        parent.InsertColumn(col=2, format=wx.LIST_FORMAT_LEFT, heading='Titel',
              width=-1)
        parent.InsertColumn(col=3, format=wx.LIST_FORMAT_LEFT,
              heading='Redakteur', width=-1)
        parent.InsertColumn(col=4, format=wx.LIST_FORMAT_LEFT,
              heading='Kategorie', width=-1)
        parent.InsertColumn(col=5, format=wx.LIST_FORMAT_LEFT, heading='Status',
              width=-1)
        parent.InsertColumn(col=6, format=wx.LIST_FORMAT_LEFT, heading='Medium',
              width=-1)
        parent.InsertColumn(col=7, format=wx.LIST_FORMAT_LEFT,
              heading='Sprache', width=-1)

        liste = FilmarchivFunktionen1.tabelle_anzeigen()
        for i in liste:
            parent.InsertStringItem(0, str(i[0]))
            parent.SetStringItem(0,1, i[1])
            parent.SetStringItem(0,2, i[2])
            parent.SetStringItem(0,3, i[3])
            parent.SetStringItem(0,4, i[4])
            parent.SetStringItem(0,5, i[5])
            parent.SetStringItem(0,6, i[6])
            parent.SetStringItem(0,7, i[7])


    def _init_utils(self):
        self.menuFilm = wx.Menu(title='')
        self.menuBar1 = wx.MenuBar()
        self._init_coll_menuFilm_Items(self.menuFilm)
        self._init_coll_menuBar1_Menus(self.menuBar1)


    def _init_ctrls(self, prnt):
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(156, 34), size=wx.Size(1288, 1058),
              style=wx.DEFAULT_FRAME_STYLE, title='Filmarchiv')
        self._init_utils()
        self.SetClientSize(wx.Size(1280, 1024))
        self.SetMenuBar(self.menuBar1)

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(1280, 981),
              style=wx.TAB_TRAVERSAL)

        self.listCtrl_Film_Tabelle = wx.ListCtrl(id=wxID_FRAME1LISTCTRL_FILM_TABELLE,
              name='listCtrl_Film_Tabelle', parent=self.panel1, pos=wx.Point(5,
              30), size=wx.Size(1270, 698),
              style=wx.LC_SINGLE_SEL | wx.LC_REPORT)
        self.listCtrl_Film_Tabelle.SetLabel('')
        self.listCtrl_Film_Tabelle.Center(wx.HORIZONTAL)
        self.listCtrl_Film_Tabelle.SetHelpText('')
        self._init_coll_listCtrl_Film_Tabelle_Columns(self.listCtrl_Film_Tabelle)
        self.listCtrl_Film_Tabelle.Bind(wx.EVT_LIST_ITEM_SELECTED,
              self.OnListCtrl_Film_TabelleListItemSelected,
              id=wxID_FRAME1LISTCTRL_FILM_TABELLE)


    def __init__(self, parent):
        self._init_ctrls(parent)


    def OnMenuFilmItems1_loeschenMenu(self, event):
        zeile = self.listCtrl_Film_Tabelle.GetFocusedItem()
        id = self.listCtrl_Film_Tabelle.GetItemText(zeile)
        id = str(id)
        FilmarchivFunktionen1.loeschen(id)
#Funktionen:

Code: Alles auswählen

def tabelle_erstellen():
    connection = sqlite3.connect("T:/tmp/Max_Hanauer/Filmarchiv/EasyEclipse for Python/Filmarchiv/src/Datenbank/Filmarchiv_Datenbank.db")
    cursor = connection.cursor()
    cursor.execute("""CREATE TABLE Film (id TEXT, kunde TEXT, titel TEXT, redakteur TEXT, kategorie TEXT, status TEXT, medium TEXT, sprache TEXT )""")


def loeschen(id):
    connection = sqlite3.connect("T:/tmp/Max_Hanauer/Filmarchiv/EasyEclipse for Python/Filmarchiv/src/Datenbank/Filmarchiv_Datenbank.db")
    cursor = connection.cursor()
    sql = "DELETE FROM Film WHERE id = (?)"
    cursor.execute(sql, id)
    connection.commit()
Als Exception bekomme ich immer ein:
cursor.execute(sql, werte)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 2 supplied.

Obwohl die übergebene id ein string oder integer ist (beider ausprobiert).
Wie gasagt, ist die Zahl einstellig gibt es keine Probleme.

Danke schon mal im Voraus

Gruß,
Spleen
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Der zweite Parameter von execute muss ein Tupel sein:

Code: Alles auswählen

cursor.execute(sql, (id,))
Den Code hättest du ruhig noch etwas kürzen können. Der letzte Block und

Code: Alles auswählen

id = str(id)
FilmarchivFunktionen1.loeschen(id)
hätten locker gereicht.

Der zweite Google-Treffer mit "sqlite3.ProgrammingError: Incorrect number of bindings supplied." hätte dir schon geholfen ;-)
Das Leben ist wie ein Tennisball.
Spleen
User
Beiträge: 16
Registriert: Donnerstag 2. Juli 2009, 09:41

Hey,

Habe es einfach so geschrieben:

Code: Alles auswählen

cursor.execute("DELETE FROM Film WHERE id = (%s)" %(id))
Jetzt funktionierts.

Danke
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das willst du so aber nicht machen, da dir das unter Umständen sicherheitskritische Lücken bereitet (SQL-Injection). Besonders bei von Benutzern erzeugten Daten ist das sehr Problematisch. Vergesse daher deinen Ansatz sofort wieder und versuche immer execute zu benutzen. Das solltest du immer dann machen, wenn du mit Werten arbeitest, welche in die Anfrage eingetragen werden.
Das Leben ist wie ein Tennisball.
Spleen
User
Beiträge: 16
Registriert: Donnerstag 2. Juli 2009, 09:41

Alles klar. Wurde jetzt in...

Code: Alles auswählen

def loeschen(id):
    connection = sqlite3.connect("T:/tmp/Max_Hanauer/Filmarchiv/EasyEclipse for Python/Filmarchiv/src/Datenbank/Filmarchiv_Datenbank.db")
    cursor = connection.cursor()
    sql = "DELETE FROM Film WHERE id = (?)"
    cursor.execute(sql, (id,))
    connection.commit()
...geändert.

Danke nochmals

Gruß,
Spleen
Antworten