Referenzielle Integrität

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Referenzielle Integrität

    Servus zusammen!

    Ich schreibe derzeit an kleiner kleinen Webapplikation mit PHP und
    PostgreSQL. Nachdem ich meine Arbeit schon fast fertig hatte, habe ich
    gemerkt, dass ich mit meinem bisherigen Datenbank-Layout mein Problem
    offenbar nicht lösen kann und habe nun, auch als Redundanz-Gründen, auf
    n:m Beziehungen umgestellt.

    Hier ein kleiner Auszug aus meinem Layout:

    table: main
    id_number (serial primary key)
    ......

    table: sequence_help
    id_number_main (integer)
    id_number_sequence (integer)

    table: sequence
    absolute_id (serial primary key)
    id_number (integer)
    sequence (text)


    Meine gewünschten Ergebnisse erhalte ich nun mit:
    select * from main, sequence_help, sequence where main.id_number = sequence_help.id_number_main AND sequence_help.id_number_sequence = sequence.id_number;


    Nun stehe ich vor folgendem Problem:
    Ich möchte die Daten (einzelne Zeilen) auch löschen können. Prinzipiell funktioniert dies mit "references on delete cascade", jedoch stellt sich das Problem, dass Daten in der Tabelle "sequence" mehrfach referenziert werden können.

    Folgendes hatte ich mir dazu überlegt: Wird ein Datensatz in main gelöscht, werden automatisch alle dazugehörigen Referenzen in "sequence_help" mitgelöscht (references on delete cascade), die Tabelle Sequence bleibt zuerst unangetastet. Dort muss ich nun allerdings regelmäßig überprüfen, ob noch Referenzen auf einen Eintrag X existieren und wenn nicht, sollte dieser gelöscht werden. Wie lässt sich das lösen? Evtl. mit einem Trigger? Ich habe diesbzgl. ein wenig rumprobiert, es jedoch leider vom Syntax (falls es überhaupt geht) her nicht hinbekommen.

    Irgendwelche Vorschläge?
    Danke im voraus.
    Last edited by HerrSeiler; 11-01-2006, 12:26.

  • #2
    ich kann dir nicht ganz folgen

    also, wenn du einen Eintrag in main löscht, dann müssen alle Einträge in sequence_help, welche die betreffende ID aus main enthalten, gelöscht werden, und das gleiche gilt auch für Löschungen in sequence. Durch die definierte Einschränkung werden alle Aktionen automatisch vom DBMS ausgeführt. Wo liegt nun dein Problem?

    Comment


    • #3
      Das Problem ist, dass Einträge in sequence mehrfach referenziert sein können (über sequence_help mit main).

      Nehmen wir folgendes Szenario an Einträgen an:

      main:
      id_number
      1
      2
      3
      4
      5


      sequence_help:
      id_number_main, id_number_sequence
      1 1
      2 2
      3 3
      4 1
      5 1


      Jetzt habe ich 3 Referenzen auf den ersten Eintrag. Wird dieser nun über main kaskadierend gelöscht, dann hängen die anderen beiden Einträge offen.

      Comment


      • #4
        schau nochmals nach, oder mach erstmal 'ne Pause, dann schau nochmals drüber. Die 1. Spalte heisst id_number_main, ich gehe davon aus, dass sie auch (verständlicherweise) die id aus der Tabelle main enthält? wenn ja, dann liest nochmals, was du schreibst.

        Comment


        • #5
          Ich hab' extra schon ne Nacht drüber gepennt und mir nochmals Gedanken drüber gemacht :-)
          Ja die erste Spalte beinhaltet die ID aus main. Mein Problem ist damit weiterhin ungelöst.

          Nach wie vor habe ich das Problem, dass ich nicht einfach den dazugehörigen Eintrag in der Tabelle "sequence" löschen kann, da sonst ggf. Referenzen "in der Luft hängen". Lasse ich sie dagegen einfach ungelöscht (die Einträge in Sequenz), dann kann es passieren, dass ich irgendwann verwaiste Einträge habe, wenn nichts mehr auf diesen Eintrag verweist.

          Vielleicht wirds auch noch klarer, wenn ich den Ursprung kurz erläutere:
          In der Tabelle "sequence" befinden sich (jetzt wirds ein wenig biologisch) Strings, die wiederrum eine Kette von Aminosäuren darstellen/repräsentieren (1 Buchstabe = 1 Aminosäure). Proteine bestehen aus solchen Ketten - allerdings nicht selten aus mehreren. Die Natur benutzt schlauerweise etablierte Sachen immer wieder und so kann es passieren, dass verwandte Proteine in manchen Teilen gleich aufgebaut sind. So kommt es also, dass ich in Sequence genau solche Proteinfragmente speichern möchte - jeder Eintrag in main repräsentiert allerdings ein Protein in seiner Gesamtform. Gewissermaßen sind die Einträge in sequence also eine Art Baukasten, von denen ich einzelne Bausteine so lange nicht wieder löschen darf, bis kein einziges Protein mehr auf einen solchen Baustein verweist.

          Ich hoffe es wurde jetzt besser klar... man möge mir nachsehen, wenn's zu biologisch war :-)

          Comment


          • #6
            mich interessiert nicht, was in den Tabellen für Daten stehen .

            Ich denke, du schmeisst was durcheinander. Es geht hier um n:m Beziehungen, warum willst du Einträge in sequence löschen, wenn du irgendwas in main löscht? Es reicht ja, wenn du dazugehörige Einträge in der sequence_help löschst. Denn es geht nur darum keine ungültige Verknüpfungen, also Leichen, in der DB nach einer Löschung zu hinterlassen, was bereits durch den Contrains gewährleistet ist.

            Comment


            • #7
              Nehmen wir asp2php's Erklärung und HerrSeilers Beispiel:
              Wegen "Es reicht ja, wenn du dazugehörige Einträge in der sequence_help löschst." wird beim Löschen von

              sequence(1)

              auch

              sequence_help(1, 1)
              sequence_help(4, 1)
              sequence_help(5, 1)

              gelöscht. Nun existiert aber z.B. main(1) noch (4+5 auch), obwohl es in sequence keinen "Partner" mehr dazu gibt.

              Oder triggert ein ON DELETE CASADE in sequence_help das Löschen von main(1), sobald sequence_help(1, 1) gelöscht wird?

              Comment


              • #8
                Original geschrieben von onemorenerd
                Nehmen wir asp2php's Erklärung und HerrSeilers Beispiel:
                Wegen "Es reicht ja, wenn du dazugehörige Einträge in der sequence_help löschst." wird beim Löschen von

                sequence(1)

                auch

                sequence_help(1, 1)
                sequence_help(4, 1)
                sequence_help(5, 1)

                gelöscht. Nun existiert aber z.B. main(1) noch (4+5 auch), obwohl es in sequence keinen "Partner" mehr dazu gibt.

                Oder triggert ein ON DELETE CASADE in sequence_help das Löschen von main(1), sobald sequence_help(1, 1) gelöscht wird?
                Vom Ansatz richtig - stimmt allerdings noch nicht ganz: Ich lösche einen Eintrag in main und damit verschwindet gleich der passende Eintrag bzw. die passenden Einträge dazu in "sequence_help". Die oben genannten sequence_help(4, 1) und (5, 1) würden in diesem Zuge nicht gelöscht werden, da sie mit main(4) bzw. main(5) verknüpft sind [der erste Wert ist die Bindung an main].
                Ein entsprechender Trigger sollte lediglich in der Tabelle "sequence" überprüfen, ob jeder Eintrag mindestens einmal durch einen Eintrag in "sequence_help" referenziert wird. Ist dies der Fall, so passiert nichts. Einträge die allerdings nicht mehr referenziert werden, die sollen gelöscht werden.

                Comment


                • #9
                  @onemorenerd

                  Warum willst du die Einträge in main löschen? Es geht hier um n:m Beziehung!

                  Wir erweitern die Tabelle sequence_help
                  Code:
                  id_umber_main	id_number_sequence
                  	1		1
                  	2		2		
                  	3		3	
                  	4		1
                  	5		1
                  	1		4
                  	2		5
                  	3		2
                  	4		3
                  	5		4
                  du löschst jetzt in sequence die id=1, das cascading delete greift auf die relation table zu und löscht 1-1, 4-1, 5-1, dann hast du:
                  Code:
                  id_umber_main	id_number_sequence
                  	2		2		
                  	3		3	
                  	1		4
                  	2		5
                  	3		2
                  	4		3
                  	5		4
                  erkläre mir jetzt bitte einer von euch, warum sollen Einträge in main gelöscht werden, nur damit ihr Leichen in der DB haben oder was

                  Das gleiche gilt auch beim Löschen von Einträge in main!

                  Comment


                  • #10
                    Ich will Daten in main löschen, weil sich dort ebenfalls noch weitere Daten befinden, die ich gleich mitlöschen möchte. Diese besitzen allerdings jeweils immer nur ein Feld, deswegen hab ich es mir gespart sie in eine extra Tabelle zu stecken.
                    OK ich könnte natürlich die Sache auch von der anderen Seite aufrollen und Sequenzen löschen, allerdings nur dann, wenn keine Referenz mehr darauf existiert. Andersherum schien es mir allerdings einfacher, weil hier die Datenbank alles für mich macht und ich nicht mit PHP alles abfragen muss.

                    Comment


                    • #11
                      dann hast du deine Datenbankdesign nicht in n:m-Format sondern irgendwas krummes angelegt, oder du verstehst den Sachverhalt nicht

                      Comment


                      • #12
                        Ich glaube, das Problem nicht so ganz verstanden zu haben.
                        Man hat folgende Daten(*)

                        main(1)
                        main(4)
                        main(5)

                        sequence_help(1, 1)
                        sequence_help(4, 1)
                        sequence_help(5, 1)

                        sequence(1)

                        Löschen von main(1) bewirkt Löschen von sequence_help(1, 1), was wiederum Löschen von sequence(1) bewirkt.
                        Soweit korrekt? Dann sehe ich

                        sequence_help(4, 1)
                        sequence_help(5, 1)

                        als Leichen an, denn sequence(1) existiert ja nicht mehr. Die beiden würde ich nun gern ebenfalls löschen, ohne aber main(4) oder main(5) zu entfernen.
                        Gleichzeitig hätte ich aber gern folgendes:

                        Reset, alles wieder auf (*)

                        Beim Löschen von sequence(1) sollen main(1), main(4) und main(5) sowie die entsprechenden Verknüpfungen in sequence_help entfernt werden. Wobei auch hier die Einträge in main nur verschwinden dürfen, wenn es keine weiteren Referenzen darauf in sequence_help gibt.

                        (Ich mische mich hier so ein, weil ich gerade an dem selben Problem sitze. Falls HerrSeiler das nicht okay findet, mach ich einen eigenen Thread auf, aber wäre wie gesagt exakt das gleiche Thema.)

                        Comment


                        • #13
                          Original geschrieben von onemorenerd

                          Löschen von main(1) bewirkt Löschen von sequence_help(1, 1), was wiederum Löschen von sequence(1) bewirkt.
                          Soweit korrekt?
                          NEIN, falsch

                          Comment


                          • #14
                            Sondern?

                            Oder besser: Wie erreiche ich oben beschriebenes Verhalten?

                            Comment


                            • #15
                              lese bitte mein Reply um 16:43

                              Comment

                              Working...
                              X