MySQL constraint bei Delete Anweisung

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Hi

hab ne Frage:
und zwar versuche ich ein Delete auf einer Tabelle in meiner MySQL Datenbank zu machen.
Klappt auch super in der jeweiligen Tabelle.

Mein Problem ist aber, dass ich Constraints angelegt habe die eigenlich bei Update und Delete auch entsprechende andere Zeilen in anderen Tabellen löschen sollten. Klappt aber leider nicht

wenn ich den selben Befehl im MySQL Workbench ausführe löscht er alle Zeilen, die auf den Constraint anschlagen.

Code: Alles auswählen

DELETE FROM table_name WHERE id='1234'
benutze MySQLdb

Danke im Vorraus
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was heißt denn "klappt nicht"? Kommt eine Fehlermeldung oder wird nichts gelöscht?

Evtl. fehlt einfach ein `commit`?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Hyperion hat geschrieben:Was heißt denn "klappt nicht"? Kommt eine Fehlermeldung oder wird nichts gelöscht?

Evtl. fehlt einfach ein `commit`?
Also

tabelle A und B
beide über einen Constrainst " Verbunden "

wenn ich im Workbench

Code: Alles auswählen

DELETE FROM A WHERE id='1234'

ausführe löscht er mir die entsprechende Zeile in Tabelle A und wie im Constraint angegeben die Zeile in Tabelle B

Wenn ich das ganze mit Python ausführe löscht er mir nur die Zeile in Tabelle A und nicht noch die in B
Commit wurde danach ausgeführt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zeig uns doch mal bitte die Definition der Tabellen in SQL. Greifst Du auch wirklich auf dieselbe Tabelle zu?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Code: Alles auswählen

-- -----------------------------------------------------
-- Table `xml_daten`.`nvd_basic`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `xml_daten`.`nvd_basic` (
  `CVE_NR` INT(8) NOT NULL DEFAULT '0' ,
  `publisheddatetime` DATETIME NULL DEFAULT NULL ,
  `lastmodifieddatetime` DATETIME NULL DEFAULT NULL ,
  PRIMARY KEY (`CVE_NR`) ,
  UNIQUE INDEX `CVE_NR_UNIQUE` (`CVE_NR` ASC) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_german1_ci;


-- -----------------------------------------------------
-- Table `xml_daten`.`auxiliaries`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `xml_daten`.`auxiliaries` (
  `aux_id` INT(11) NOT NULL AUTO_INCREMENT ,
  `CVE_NR` INT(8) NULL DEFAULT '0' ,
  `assessment_name` VARCHAR(150) CHARACTER SET 'latin1' COLLATE 'latin1_german1_ci' NULL DEFAULT NULL ,
  `assessment_href` VARCHAR(400) CHARACTER SET 'latin1' COLLATE 'latin1_german1_ci' NULL DEFAULT NULL ,
  `assessment_system` VARCHAR(400) CHARACTER SET 'latin1' COLLATE 'latin1_german1_ci' NULL DEFAULT NULL ,
  `cwe` VARCHAR(8) CHARACTER SET 'latin1' COLLATE 'latin1_german1_ci' NULL DEFAULT NULL ,
  `summary` TEXT CHARACTER SET 'latin1' COLLATE 'latin1_german1_ci' NULL DEFAULT NULL ,
  PRIMARY KEY (`aux_id`) ,
  INDEX `neu` (`CVE_NR` ASC) ,
  CONSTRAINT `neu`
    FOREIGN KEY (`CVE_NR` )
    REFERENCES `xml_daten`.`nvd_basic` (`CVE_NR` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 3416
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_german1_ci;
Python Script

Code: Alles auswählen

import MySQLdb
connection = MySQLdb.connect("x.x.x.x", "root", "1234", "xml_daten") 
cursor = connection.cursor()

def sqlSelect(id): 
    sqlstart = "select * from xml_daten.nvd_basic where CVE_NR = '"
    sqlende = "'"
    str = sqlstart + id + sqlende
    cursor.execute(str)
    return (cursor.rowcount)

def sqlDelete(table, id):
    sqlstart = "DELETE FROM " 
    sqlmitte = " WHERE CVE_NR='"
    sqlende = "'"
    str = sqlstart + table + sqlmitte + id + sqlende
    test = sqlSelect(id)
    if test == 1: 
        cursor.execute(str)
        connection.commit()
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

zimbo hat geschrieben:
Hyperion hat geschrieben:tabelle A und B
beide über einen Constrainst " Verbunden "
Ein Constraint kann viel bedeuten. Entscheidend ist in deinem Fall, dass "ON DELETE CASCADE" gesetzt ist.

Die Storage-Engine wird wohl InnoDB sein, aber welche Version von MySQL setzt du ein und wie sehen die Tabellendefinitionen genau aus?

Edit: OK, die Frage nach den Tabellendefinitionen hat sich mit deinem kurz vorher abgesendeten Posting erledigt.
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Benutze MySql Server 5.5 MySql Workbench 5.2CE
den Rest s.o. :wink:
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Der gezeigte Code lässt zwar an Schönheit einiges zu wünschen übrig, aber hier funktioniert das kaskadierende Löschen ohne Probleme.

Hängst du eventuell aus Versehen auf einer anderen Datenbank?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also `on delet cascade` ist ja gesetzt - zudem sollte das ja auch von der DB alleine erledigt werden; da hat Python ja nichts mit zu tun! Ich denke tatsächlich nach wie vor, dass das Problem DB seitig zu suchen ist - sofern die SQL-Statements wirklich exakt 1:1 übereinstimmen.

Zu Deinem Code lässt sich aber viel sagen!

- Benutze niemals gängige String-Methoden zum Zusammenbau. Damit ist Dein SQL anfällig für SQL-Injections. Benutze stattdessen die Methodik der DB-API2:

Code: Alles auswählen

cursor.execute("select foo from bar where attr=?", (value,))
Anstelle des "?" kann das beim MySQLdb-Modul ggf. leicht anders aussehen. Das musst Du in der Doku mal nachlesen.

- Deine Namensgebung entspricht nicht PEP8. Funktionsnamen sollten aus Kleinbuchstaben und "_" bestehen.

- Integer haben einen Wahrheitswert. Man kann sich also den Test auf " == 1" sparen.

- mir erschließt sich Deine Logik nicht; das Löschen wird nur durchgeführt, wenn ein Eintrag in der einen Tabelle existiert? Der Code zeigt uns ja nun nicht, wie Du feststellst, dass das nicht klappt... evtl. ist auch das Query-Statement falsch; numerische Werte müssen ja nicht in '' eingeschlossen werden - evtl. dürfen sie das auch nicht? Ich würde da insgesamt wohl eine Lösung per Exception vorziehen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

/me hat geschrieben:Der gezeigte Code lässt zwar an Schönheit einiges zu wünschen übrig, aber hier funktioniert das kaskadierende Löschen ohne Probleme.

Hängst du eventuell aus Versehen auf einer anderen Datenbank?
Das mit der Schöhnheit ist mir durchaus bewusst ich hab vor 6 Wochen mit Python angefangen und muss in 2 fertig sein.
Mit XML auslesen, DB schreiben, SSH Zugriff, Softwarelisten auslesen, GUI bauen, Logik zum Vergleichen der Software.

Bin definitiv in der richtigen Datenbank alle anderen Anweißungen funktionieren ja auch.
Was mich aber wundert ist, dass der Constraint beim Insert funktioniert also er meckert wenn in nvd_basic kein Datensatz mit der entsprechenden ID vorhanden ist.

@ Hyperion

Danke für die Tips
werde die Namensgebung ändern
Hyperion hat geschrieben:

Code: Alles auswählen

cursor.execute("select foo from bar where attr=?", (value,))
ich glaub das geht hier mit

Code: Alles auswählen

cursor.execute("select foo from bar where attr= %s", (string,))
ich muss eine XML datei mit updates einlesen um unnötigen Aufwand mit Update kommandos zu sparen wollte ich da ich ja meine Constraints hab die entsprechenden Einträge löschen und komplett neu reinschreiben lassen.
Aber jetzt muss ich wohl Update Kommandos schreiben.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wie überprüfst Du denn, dass der Python-Code nicht das tut, was er soll? Aus dem Code oben geht das ja nicht hervor!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Hyperion hat geschrieben:Wie überprüfst Du denn, dass der Python-Code nicht das tut, was er soll? Aus dem Code oben geht das ja nicht hervor!
Im SQL Workbench kann ich mit die Tabelleninhalte anzeigen lassen und bearbeiten einmal per drag an drop und einmal per SQL Befehl.
So teste ich die Befehle bzw lass mir die Befehle im Python Script per print Anweisung einfach ausgeben.
zimbo
User
Beiträge: 16
Registriert: Dienstag 6. Dezember 2011, 17:38

Hi :D

das ganze hat sich glücklicherweise erledigt habe heute die kompletten tables gelöscht und nun gehen auch die Constraints aus dem Python Script.
Danke für die Hilfe
Antworten