[ nikitaGradov @ 04.12.2012. 08:27 ] @
Treba mi pomoc za sledeci problem: htio bih da, iz uskladistene procedure, upisem dvostruko ulancanu listu u tabelu.

Tabela ima sledeca polja:
ID (primary key, bigint)
ID_Sledeci (pokazuje na rekord koji je po, nekoj logici rada aplikacije, sledeci)
ID_Prethodni (pokazuje na rekord koji je po, nekoj logici rada aplikacije, prethodni)
Kolona_Podatak_1
Kolona_Podatak_2
...

Postoji UI u kome korisnik definise, da ih tako krstim, 'clanove' liste i njihove veze (jasno: prvi clan liste nema prethodnog clana, a poslednji clan liste nema sledeceg clana).

Ja bih htio da podatke, definisane na UI formi, upisem u bazu, pomocu jedne uskladistene procedure.

Problem mi je taj da ne znam, jasno, vrijednost ID_Sledeci, jer taj rekord jos nije insertovan.
Takodje, treba da pamtim ID prethodno 'insert'-ovanog rekorda, da bih mogao da setujem polje ID_Prethodni od tekuceg 'insert'-ovanog rekorda.
I treba da, prilikom insert-a tekuceg rekorda, update-jem polje ID_Sledeci od prethodno 'insert'-ovanog rekorda (da je jednako polju ID upravo 'insert'-ovanog rekorda).

Ne poznajem dovoljno SQL sintaksu (i sintaksu za uskladistene procedure) i zato problem iznosim na forum.

Da li neko zna kako ovo uraditi iz jedne uskladistene procedure?

Razmatram varijantu da napisem dvije uskladistene procedure:
- prva bi izvrsila insert svih clanova liste,
- druga procedura bi se trebala pozvati odmah po zavrsetku izvrsavanja prve procedure (u okviru iste transakacije) i ona bi uspsotavila veze izmedju clanova liste.

Zahvalan za svaku ideju, predlog itd
[ Dusan Kondic @ 04.12.2012. 09:26 ] @
Jedno od rešenja može da bude dodavanje polja PrazanRed tipa BIT pomoću kojeg možeš da imaš naredni red. Taj red se inicijalno popunjava praznim podacima i prilikom unosa novih podataka updateuje, pa se kreira nov prazan red.
Primer
Code:

--Ulazni parametri procedure
DECLARE @Kolona_Podatak_1 VARCHAR(50) = 'Podatak 1'
DECLARE @Kolona_Podatak_2 VARCHAR(50) = 'Podatak 2'
--AS

DECLARE @T TABLE (ID BIGINT IDENTITY(1, 1) PRIMARY KEY, ID_Sledeci BIGINT, ID_Prethodni BIGINT, 
Kolona_Podatak_1 VARCHAR(50), Kolona_Podatak_2 VARCHAR(50), PrazanRed BIT)

DECLARE @TekuciRedId BIGINT

/*
--Ovi iskazi sluze za testiranje ELSE dela koda
INSERT INTO @T (ID_Sledeci, ID_Prethodni, Kolona_Podatak_1, Kolona_Podatak_2, PrazanRed)
VALUES(2, 1, 'Stari podatak 1', 'Stari podatak 1', 0)

INSERT INTO @T (ID_Sledeci, ID_Prethodni, Kolona_Podatak_1, Kolona_Podatak_2, PrazanRed)
VALUES(NULL, 1, NULL, NULL, 1)
*/
    
--Prilikom prvog unosa INSERT-ujemo, a svaki naredni put UPDATE-ujemo
IF NOT EXISTS (SELECT Id FROM @T)
BEGIN
    INSERT INTO @T (ID_Sledeci, ID_Prethodni, Kolona_Podatak_1, Kolona_Podatak_2, PrazanRed)
    VALUES(NULL, NULL, @Kolona_Podatak_1, @Kolona_Podatak_2, 0)
    
    SET @TekuciRedId = SCOPE_IDENTITY()
END
ELSE
BEGIN
    SET @TekuciRedId = (SELECT Id FROM @T WHERE PrazanRed = 1)
    
    UPDATE @T SET Kolona_Podatak_1 = @Kolona_Podatak_1, Kolona_Podatak_2 = @Kolona_Podatak_2, PrazanRed = 0
    WHERE Id = @TekuciRedId
END

INSERT INTO @T (ID_Sledeci, ID_Prethodni, Kolona_Podatak_1, Kolona_Podatak_2, PrazanRed)
VALUES(NULL, @TekuciRedId, NULL, NULL, 1)

DECLARE @PrazanRedId BIGINT
SET @PrazanRedId = SCOPE_IDENTITY()

UPDATE @T SET ID_Sledeci = @PrazanRedId WHERE Id = @TekuciRedId

SELECT * FROM @T
[ djoka_l @ 04.12.2012. 10:38 ] @
Dusan ti je dao neke smernice, a ja bih hteo da kritikujem tvoju postavku problema.
S obzirom da si rekao da ne poznaješ dovoljno SQL sintaksu i Transact SQL, smatram da koristiš bazu podataka na neprimeren način.
Skoro svaka baza podataka ima implementiran mehanizam dvostruko ulančane liste - i zove se index. Indeksi su u većini baza podataka implementirani u vidu B* stabla, dok su listovi stabla dvostruko povezana lista. Ukoliko je upit dobro napisan, podacima se efikasno pristupa upravo preko indeksa.

Zato je pravo pitanje za tebe zašto želiš na svoj način da implementiraš nešto što sama baza radi bolje nego ti?

Primedbe na dizajn: ti si predvideo da struktura tabele liči na listu u tvom programu. Po onom što si napisao, ispada da će tabela u jednom momentu imati samo jednu listu kao sadržaj. Ako misliš da čuvaš više lista, kako ćeš ih razlikovati? Ako imaš više listi, kako ćeš obezbediti da se ne ukrste (na primer šesti član jedne liste pokaže da je sledeći član treći član iz neke druge liste)? U programu verovatno imaš neku strukturu u kojoj držiš pokazivač na početak (i možda kraj) liste. Gde ti je taj podatak u tvojoj strukturi podataka? Ovo znači da ti, u stvari, treba tabela koja predstavlja listu listi, ili ti fali podatak koji u svakom članu liste mora da identifikuje kojoj listi pripada (na primer Lista_ID).

Sledeće pitanje je da li je bitna uređenost liste? Ako je nebitna, onda nije potrebno u bazi čuvati strukturu liste, već listu rekreirati prilikom učitavanja u program i to onim redosledom kojim baza vrati slogove. AKo je bitna uređenost liste, pitanje je da li onaj podatak koji stoji u listi određuje poredak. Ako je to tako, opet nije potrebna pokazivačka struktura, nego listu treba pročitati sortiranu po skupu podataka koji određuju poredak. I, na kraju, ako je poredak bitan i nije moguće izračunati ga, onda procedura za upis u bazu, može da čita redom podatke iz liste i da generiše REDNI_BROJ, koji bi uz Lista_ID mogao da bude UNIQUE index.

Razmisli još malo šta ti u stvari treba...
[ nikitaGradov @ 04.12.2012. 11:27 ] @
Zahvaljujem se na odgovorima - evo da pokusam da preciznije objasnim sto meni treba (a bez zalazenja u detalje same aplikacije).

Imam korisnika koji hoce da ima mehanizam kreiranja (bilo za sebe, bilo za saradnike) vise 'zadataka' odjednom, pri cemu su ti zadaci povezani, za sada, vezom 'Finish-to-Start' (u prevodu: zavrsetak jednog zadatak oznacava pocetak rada na drugom zadatku).

Ti 'zadaci' imaju neka svoja polja (u bazi): razni datumi (zavrsetak,dodela,promjena itd), kome je dodeljen, itd.
Da zaokruzim pricu: grupe zadataka se dodjeljuju necemu, sto cemo nazvati, recimo, 'Projekat'. Znaci, moze da se desi da jednom projektu dodijelimo vise grupa zadataka (i u pravu je djoka_I: trenutno ne bih mogao da razlikujem zadatke iz vise grupa zadataka - trebaju mi dodatna polja u tabeli ...).

Meni je palo na pamet da ih (u bazi) organizujem kao 'dvostruko ulancanu listu': jedan zadatak ima 'pokazivac' na zadatak (iz, jasno, iste tabele) koji mu prethodi ('predcessor'), kao i 'pokazivac' na zadatak, koji se izvrsava posle njega ('successor').
Jasno, prvi zadatak (u nekoj grupi zadataka) nema 'predcessor'-a, a poslednji nema 'successor' -a.

'Predcessor' mi treba da korisniku prikazem zadatak koji, da tako kazem, 'koci' tekuci zadatak.
'Successor' mi treba da bih iz nekog UI-a, kad tekuci zadatak (iz grupe) proglasim da je 'finished', mogao da sledeci zadatak (iz grupe) proglasim za 'current' ...

Na ovaj nacin, ja mogu da korisniku predstavim, da tako kazem, dinamiku napredovanja pojedinacnih zadataka (cekanje na zavrsetak drugih zadataka, veze izmedju zadataka itd).

Do sada sam odradio povezivanje izmedju dva 'zadatka': kreiram jedan zadatak, a kasnije i drugi i uspostavim relaciju izmedju njih (i to, da se tako izrazim, 'radi').

Sada bih htio da, iz jedne uskladistene procedure:
- insertujem sve zadatke (iz grupe zadataka, koju korisnik kreira na nekom UI-u), i
- da uspostavim relacije izmedju njih (relacije koje postoje kod dvostruko ulancane liste).

Prvi problem mi je kako da popunim polja 'pokazivac na sledeci', jer kad insertujem tekuci zadatak, sledeci jos nije insertovan.
Tu sam imao neku ideju da kreiram uskladistenu proceduru, koju bih pozivao iz trigera, koji bih definisao 'after insert'. Ta procedura bi trebala da ispita da li zadatak iz neke grupe, da li je prvi/poslednji i da izvrsi 'update' polja 'pokazivac na sledeci clan' prethodno insertovanog zadatka ...

Citajuci odgovor od djoka_I shvatio sam da moram dopuniti tabelu informacijom o tome kojoj listi zadatak pripada (o cemu sam prethodno napisao).

Nadam se da sam malo detaljnije opisao problem ... meni je 'dvostruko ulancana lista' ovdje potrebna u kontekstu koji sam opisao.

Jos jednom se zahvaljujem na odgovorima ...



[ Zidar @ 04.12.2012. 15:43 ] @
@Nikit:
Zasto ne pojednostavis tabelu? Nije potrebno da pamtis i 'Prethodni' i 'Naredni'. Ako za svaki zadatak znas koji su njegovi prethodni zadaci, onda sledi da je taj zadatak naredni zadatak za sve one koji su njemu prethodni. Ovo znai da je moguce napisati kveri koji za svaki zadatak moze da pokaze listu prethodnika i listu sledecih zadataka. Znaci, izbaci iz tabele kolonu 'Sledeci' i izracunaj je kad ti zatreba.

U svakom slucaju nece ti biti lako. Pokusavas da cuvas u relacionoj bazi strukturu mreze zadataka na projektu. Za takve stvari postoji MS Project....

[ nikitaGradov @ 04.12.2012. 16:18 ] @
> Ako za svaki zadatak znas koji su njegovi prethodni zadaci, onda sledi da je taj zadatak naredni zadatak za sve one koji su njemu prethodni.

Zahvaljujem - ovo je tacno i usvojicu tvoj prijedlog.

> Pokusavas da cuvas u relacionoj bazi strukturu mreze zadataka na projektu. Za takve stvari postoji MS Project....

Da li ovo znaci da je relaciona baza neprimjeren alat za ovu svrhu ? Pretpostavljam da i MS Project koristi neki mehanizam za cuvanje podataka ?

Znam za MS Project - kolega mi je prosle nedjelje ukazao isto sto i ti, odnosno da je MS Project alat za ovakve namjene ... s druge strane, zahtjev korisnika je da, koliko god je moguce, izbjegavamo upotrebu MS proizvoda ...
[ Zidar @ 05.12.2012. 16:48 ] @
Citat:
Da li ovo znaci da je relaciona baza neprimjeren alat za ovu svrhu ? Pretpostavljam da i MS Project koristi neki mehanizam za cuvanje podataka ?
Relaciona baza moze da se koristi za cuvanje podataka o mreznim strukturama. Ono sto ti moedliras inace se zove 'mrezni plan projekta', znaci - moze, a shvatio si i kako moze. Problemi nastaju kad se trazi neka informacija iz sacuvanih podataka o mrezi. Kveriji su rekurzivni i komplikovanin za pisanje, ali to moes da resis u kodu. Kad budes uneo mrezu u tabelu, trazice ti da izracunas "kritican put", a to je iterativan postupak, za koji relacione baze nemaju bas najbolja resenja. Zatim, sistem za upravljanje projektima je mnogo vise od pukog cuvajna podataka. Trazi se pracenje promena na aktivnostima, cesto se zahteva re-kalkulacija kriticnog puta, sistem mora da spreci nelogicne unose podataka (a veoma se lako gresi), moras omoguciti raspodelu resursa, upravljanje kalendarima, graficko prikazivanje mreze aktivnosti i Gantt planova i jos sijaset izvestaja od koji ce te zaboleti glava. Ako pravite sistem za upravljanje projektima, good luck, ima mnogo da se radi.

Citat:
Znam za MS Project - kolega mi je prosle nedjelje ukazao isto sto i ti, odnosno da je MS Project alat za ovakve namjene ... s druge strane, zahtjev korisnika je da, koliko god je moguce, izbjegavamo upotrebu MS proizvoda ...
MS project nije jedini alat za ovakve namene. Ima i drugih, ali su svi manje vise isti, sa istim mogucnostima i manama, i svi kostaju mnoooogo para. MS proizvodi su medju najjeftinijim, i u ex-YU uslovim su cestoi besplatni.

SVi alati za upravljanje projektima razvijeni su u osamdesetim godinama proslog veka. Sama metoda mreznog planiranja nije mnogo starija - prvi put je to primenila NASA na primenjena na projektu POlaris - slanje coveka na mesec. U pocetku se to radilo rucno (PC nije postojao, ) dok se neko nije setio da isprogramira celu metodu (u FORTRANu na busenim karticama), u zgodnom momentu kad je PC dosao na scenu. Prve programe su pisali ljudi koji su metodu i izmislilil - matematicari i strucnjaci za 'operational research'. Kad su programe poceli da koriste inzenjeri, ispostavilo se da mnogo toga nedostaje, uglavnom u oblasti interfejsa i izvestaja. I neke vazne stvari su nedostajale - na primer pracenje progresa na aktivnostima ili dodavanje komentara na aktivnosti. Na nesrecu, pojavio se Windows, Microsoft je kupio firmu koja je razvila Project, malo su ga nasminkali, dodali bespotrebne stvari, bez da su resili ijedan znacajan problem. Svi ostali su naravno morali da slede Microsoft.

Tu pocinje tvoj problem. Programi za upravljanje projektima su kao jaje jajetu slicni i svi pate od istih bolesti. Onda ti moras da ih popravljas ili da pises novi program odpocetka, i da podatke smestis u relacionu bazu. Pristup je zdarv i solidan, ali je veoma tesko i mukotrpno razviti jedan takav sistem. Moras da budes istovremeno i inzenjer i programer i database modeler. To nazalost nema. Prve verzije su pisali matematicari i naucnici, koji su sad ili u penziji ili u vecnim lovistima.

Sad nesto korisno:
U knjigama koje pise Itzik-Ben Gan, "Inside MIcrosoft SQL Server 2005/8 Programming" imas deo koji se bavi grafovima, ima primer mreze vazduznog saobracaja u USA, a na isti nacin se moze tretirati i mreza projektnih aktivnosti. Tek da dobijes sliku o cemu se radi.

Srecan rad, projekat je lep, ali je sav 'krv, znoj i suze'