Problemet: Hej!! Hej. Denna länk kanske kan var till ett hjälp. Visar hur man kan överstiga 32 nivåer i en hirarki: Begränsningen på 32 nivåers rekursion finns där av en anledning: man bör inte använda rekursivitet i SQL. För att bygga en effektiv hierarki i SQL Server föreslår jag istället att du tittar på t ex Joe Celkos modell Nested Sets (finns info på nätet, samt i hans böcker), eller Itzik Ben-Gans Enumerated Paths (vet dock inte riktigt var man ska hitta info om den på nätet). Har att tacka herr "Trash" för detta:Delete problem...
Det projekt jag håller på att skapa är ett filhanteringsystem emot webben. Projektet skrivs i C# samt ASP.NET, dbhsen som används är en MS-SQL 2K. Verifieringen, dvs ingloggningen sköts av en Win2k Active Directory.
Alla användare har en egen katalog, där de kan skapa underkataloger samt skicka upp filer. Dvs varje användare har sin egen lilla herarki av kataloger...
En sökväg, eller namn på varje katalog lagras i databasen, samt dess förälder (parent directory).
Tabellen ser ut som följande:
<code>
tblDirectories
----------
dirIdent (int, identity(1,1))
dirLocation char(50)
...
dirOwner int ( relation till dirIdent)
</code>
en select ifrån tblDirectories kan se ut som följande:
</code>
Mina Dokument
|-Mina Bilder
|- Databas diagram
| |- SQL S
| |- Access
|- UML
|- Web
|- JPG
|- GIF
</code>
Problemet uppkommer nu när användaren beslutar sig att ta bort tex. 'Mina Bilder' katalogen. När detta sker måste alla underkataloger samt de underkataloger som till hög underkatalogerna till 'Mina Bilder' tagas bort.
Detta skulle kunna lösas relativt enkelt med en rekursiv funktion, problemet är att SQL Server enbart stödjer rekursivitet till 32 nivåer, dvs en funktion kan max kalla på sig själv 32 ggr.
En lösning som jag kom upp med var att skapa en trigger som bindades till tblDirectories, så när något togs bort ifrån tabellen tblDirectories så tog triggern bort alla kataloger där förälder (dirIdent) inte fanns i databasen. Men även denna är begränsad av 32 nivåers rekursivitet....
En sista lösning skulle vara att detta sköts av sidan i sig, som själv har en rekursiv funktion som tar bort katalog för katalog. Detta skulle dock vara alldelse för långsamt och dra för mycket kraft av servern.
Förslag?Sv: Delete problem...
Du kanske skulle kunna skapa en temptabell som innehåller alla id'n som skall bort. Sedan gör man bara en DELETE med en subselect eller join mot den tabellen.
Kodexemplet nedan är inte testat utan mer till för att ge dig en bild över hur jag tänkt. @DeleteThis skall innehålla id på foldern som skall bort. Som sagt, jag har inte testat denna kod, så posta gärna in lösningen här så vi får se hur du löste det!!!!!
/Tommie
<code>
CREATE TABLE #RemoveIds(
dirIdent Int,
dirOwner Int
)
' Sätt in det första värdet
Insert #RemoveIds(dirIdent Int) Values (@DeleteThis)
' Default för att loopen skall köras minst en gång
SELECT @iCount = 1
WHILE @iCount <> 0
INSERT #RemoveIds
SELECT dirIdent FROM tblDirectories
WHERE dirOwner IN (SELECT dirIdent FROM #RemoveIds)
AND dirIdent NOT IN (SELECT dirIdent FROM #RemoveIds)
SELECT @iCount = @@ROWCOUNT
END
DELETE FROM tblDirectories WHERE dirIdent IN (SELECT dirIdent FROM #RemoveIds)
DROP TABLE #RemoveIds
</code>Sv: Delete problem...
Nu kan jag inte ett jota mer än "Oracle-världen" vad det gäller databaser.
Så här hade jag gjort i Oracle, men jag vet inte om detta fungerar i SQL-Server:
delete from tblDir
where dirIdent in (
select dirIdent
from tblDir
start with dirLocation = 'Databas diagram'
connect by prior dirIdent = dirOwner);
/UffeSv: Delete problem...
http://www.gladh.nu/asphelp/svar18.htmlSv: Delete problem...
Sv: Delete problem...
<code>
if exists(select name from sysobjects where name='GetThreads_The_AH_Way')
drop proc GetThreads_The_AH_Way
go
CREATE PROC GetThreads_The_AH_Way
(
@dirIdent int
)
AS
CREATE TABLE #Threads
(
dirParent int,
dirIdent int,
dirLocation char(50),
thr_depth int
)
DECLARE @thr_depth int
SET @thr_depth = 0
INSERT INTO #Threads (dirParent, dirIdent, thr_depth,dirLocation)
SELECT dirParent, dirIdent, @thr_depth,dirLocation
FROM tblDirectories
WHERE dirParent = @dirIdent
WHILE EXISTS (SELECT Null FROM #Threads WHERE thr_depth = @thr_depth)
BEGIN
INSERT INTO #Threads (dirParent, dirIdent, thr_depth,dirLocation)
SELECT dirParent, dirIdent, @thr_depth + 1,dirLocation
FROM tblDirectories
WHERE dirParent IN (SELECT dirIdent FROM #Threads WHERE thr_depth = @thr_depth)
SET @thr_depth = @thr_depth + 1
END
SELECT * FROM #Threads
DROP TABLE #Threads
</code>
fÿnka perfa.