Avatar billede biohazard_666 Nybegynder
23. september 2007 - 17:33 Der er 9 kommentarer og
2 løsninger

Systematisk udryddelse fra database

Hejsa eksperter ;)

godtnok er mit problem ikk helt så drastisk som titlen beskriver, men altså :p Jeg har tænkt et godt stykke tid på hvordan jeg skal fixe mit problem.
Jeg har i min database gemt en slags "mappestuktur" hvor hver mappe har et id, navn og en parent-id. Det kan ses nogenlunde på denne måde:

Mappe1 (id: 1)
-Mappe2 (id: 2, parent-id: 1)
-Mappe3 (id: 3, parent-id: 1)
--Mappe4 (id: 4, parent-id: 3)
---Mappe5(id: 5, parent-id: 4)
--Mappe6 (id: 6, parent-id: 3)
-Mappe7 (id: 7, parent-id: 1)

Spørgsmålet er, hvordan kan jeg lave en loop, så hvis jeg starter med at slette mappe1, så kører programmet videre og checker om mappe1 har nogle undermapper, og kører endnu længere ind og simpelthen bliver ved med at slette alle undermapper som ligger indad, og undermappernes undermapper osv :S

Er der nogen som har et eksempel på hvordan dette gøres? Jeg har prøvet at hitte ud af noget, men hver gang går jeg fast på at jeg skal kunne lave et nærmest uendeligt antal undermapper i undermapper i undermapper :P

ja det er forvirrende, sorry! Men altså! Nogen der har et svar på dette? :)
Avatar billede biohazard_666 Nybegynder
23. september 2007 - 17:33 #1
Det skal lige siges at jeg bruger en mysql database - hvor tabelnavnet er filsystem ^^
Avatar billede arne_v Ekspert
23. september 2007 - 21:00 #2
Det er fakrisk ikke helt nemt.

Du kan kode en iterativ løsning i PHP hvor du fyrer SELECT og DELETE statements af.

Hvis du bruger MySQL 5.x kan du lave en stored procedure i MySQL som kan gøre det.
Avatar billede thesurfer Nybegynder
23. september 2007 - 21:11 #3
Der skal bruges en rekursiv funktion.. Måske kan man gøre sådan her (pseudo-kode):

funktion sletundermappe(pid)

hvis pid <> "" then
  select * from filsystem where parentid = pid
  hvis antal_poster > 0 then
  for i = 0 til antal_poster
    pid = parentid_på_antal_poster(i)
    sletundermappe(pid)
  next
slut hvis

end funktion

Der skal nok arbejdes lidt på det.. :-)

Generelt er det samme pricip, som hvis man ville liste/vise samtlige mapper og undermappe på et drev..
Avatar billede biohazard_666 Nybegynder
23. september 2007 - 21:48 #4
hehe nej Arne - det er ret tricky :p

Og thesurfer, hva så hvis man har en undermappe under den undermappe der? :) Det er sygt crazy det her :p Har siddet og grublet over problemet i timer snart, men har stadig ikke fundet en løsning =/ Derfor jeg ville høre om der var nogle som havde et script som kunne klare det :) Men jeg tænker videre, og så må jeg se om der kommer andre svar her inde :) hehe
Avatar billede thesurfer Nybegynder
23. september 2007 - 22:10 #5
Det er lige meget hvor mange undermapper der er, i en undermappe.. loopen vil blive ved med at køre, så længe at der er undermapper..

Rekursive funktioner (funktioner der kalder sig selv) er lidt freaky.. :-)
Avatar billede biohazard_666 Nybegynder
24. september 2007 - 19:58 #6
ah haha ja :P lol :)

Kan lige lave en test-applikation her en af dagene og så se på hvordan det ser ud :)
Avatar billede neoman Novice
24. september 2007 - 20:17 #7
En ikke særligt effektiv løsning i kode:

Du laver et array

  parentID(ID)

hvor indexet id  er din record id,og værdien er gemt i parentID er - parent id eller 0 hvis ingen parent


Du laver et string array, myName(ID)

pseudo kode:

For each myID in ParentID

  Id = myID
  myName(myID) = ID.ToString
  myParent = ParentID(ID)
 
  While myParent<>0
    myName(myID) = myParent.ToString & "," myName(myId)
    myParent = ParentId(myParent)
  loop

Next

Når du er færdig så har du, for dit eksempel:

id myName(id)
1  1
2  1,2
3  1,3
4  1,3,4
5  1,3,4,5
6  1,3,6
7  1,7

Hvis du i funktionen ToString formaterer hvert tal  med et tilstrækkeligt antal foranstillede nuller eller blanks, så har du en string for hver mappe som entydigt placerer den i hierarkiet, og for at slette en hel gren, så skal du blot slette alle dem som matcher med navnet på den node du ønsker at slette fra venstre af.
Avatar billede neoman Novice
24. september 2007 - 20:23 #8
Noget lignende kunne opnås ved at lægge en string myName i hver record, og når en ny record tilføjes, så får myName for den record værdien af eget index prepended med  myName fra parent.
Avatar billede biohazard_666 Nybegynder
30. september 2007 - 13:35 #9
jeg lavede en rekursiv funktion igår, og den virker - til dels :) Den fejler dog nogle steder hvor den siger at der er en EOF fejl - jeg kan umiddelbart ikke hitte ud af hvorfor at den gør det, da jeg havde den i en Do while not EOF-lykke, men klokken var ret mange da jeg lavede funktionen, så tager et kik på den her senere når jeg er færdig med lektierne, så jeg kan få skidtet til at virke ;) Jeg poster funktionen her hvis jeg overhovedet ikk kan få det til, eller hvis jeg får den til at virke :D
Avatar billede biohazard_666 Nybegynder
30. september 2007 - 15:54 #10
tænk engang :) Jeg har sQ fået den til at virke :D Den kommer her:

Private Function RekursivTest(intID As String, x As Integer)
'On Error Resume Next
Dim intDelete(0 To 50) As String
Dim intBuffer() As String

strSQL = "SELECT count(*) AS Found FROM test WHERE id = '" & intID & "'"
Set objLo = objConn.execute(strSQL)

If objLo("Found") > "0" Then
    strSQL = "DELETE FROM test WHERE id = '" & intID & "'"
    objConn.execute (strSQL)
    idDelete = idDelete & "," & intID
   
    strSQL = "SELECT Count(*) AS Found FROM test WHERE parent = '" & intID & "'"
    Set objloz = objConn.execute(strSQL)
   
    If objloz("Found") > "0" Then
        strSQL = "SELECT * FROM test WHERE parent = '" & intID & "'"
        Set objRz = objConn.execute(strSQL)
       
        Do While Not objRz.EOF
            intDelete(x) = intDelete(x) & "," & objRz("id")
            objRz.movenext
        Loop
        intBuffer = Split(intDelete(x), ",")
        For i = LBound(intBuffer) To UBound(intBuffer)
            RekursivTest (intBuffer(i)), x + 1
            DoEvents
        Next i
           
    End If
End If
End Function

Den kan helt sikkert optimeres, men det der er en ret go start i hvert fald :) Håber der er andre som kan få brug for denne.

Kan du ikke smide et svar TheSurfer, så deler vi pointene, da det var din pseudo-kode der hjalp en del ;)
Avatar billede thesurfer Nybegynder
30. september 2007 - 16:45 #11
Det kan jeg da godt :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester