Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Ogranicenje u celoj tabeli

[es] :: MS SQL :: Ogranicenje u celoj tabeli

[ Pregleda: 1487 | Odgovora: 2 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

M E N E
borislav
Temerin

Član broj: 30434
Poruke: 231
*.static.isp.telekom.rs.



+1 Profil

icon Ogranicenje u celoj tabeli24.12.2009. u 13:55 - pre 173 meseci
Imam tabelu magacina
zelim da u svakom momentu postoji JEDAN i TACNO JEDAN centralni magacin
To postizem sa jednim bool (bit) not null poljem.

Zelim da u slucaju promene centralnog magacina (srazmerno retka operacija, ali moram misliti na to), postavim neko ogranicenje koje ce dozvoliti da strogo jedan magacin bude centralni, dakle, setujem magacin 1, hocu da dotadasnji centralni magacin (2) dobije FALSE; isto tako, ako sada krenem da magacinu 1 postavim na FALSE, da se to ne dozvoli, vec da constraint odrzava strogo i tacno jedno polje setovano na TRUE

Znam da mogu triggerom, ali sam pomislio da mozda postoji neka vrsta constrainta na jednoj koloni u celoj tabeli ili tako neka napredna opcija u sql 2005...

Je l neko radio nesto slicno?
Uhvatili ste me nespremnog
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: Ogranicenje u celoj tabeli24.12.2009. u 14:18 - pre 173 meseci
Pa ako hoces da se setuje samo na false onda trigger, ali ako hoces samo da osiguras integrity mozes da napravis funkciju i da je pozoves iz CHECK constrainta. Samo pazi, check constraint se ne radi na delete tako da ako obrises magacin koji je u tom treutku glavni neces to detektovati.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Zidar
Canada

Član broj: 15387
Poruke: 3085
*.100.46-69.q9.net.



+79 Profil

icon Re: Ogranicenje u celoj tabeli04.01.2010. u 17:37 - pre 173 meseci
Nadam se da nije kasno za jos jedan komentar. Pitanje je interesantno i zasluzuje diskusiju. Ovako:

Uslov A: "zelim da u svakom momentu postoji JEDAN i TACNO JEDAN centralni magacin
" je prilicno strog i nije jednostavan da se obezbedi. Ne sme da bude vise od jednog, ali ni manje od jednog glavnog magacina. Ovo 'da nema manje od jednog glavnog magacina' nije bas lako da se resi.

Mozda si mislio na uslov B: "u jednom momentu ne sme biti vise nego jedan glavni magacin" ? Ovde se trazi da ne sme da bude vise od jednog magacina koji je glavni.

Posto u oba slucaja ne sme biti vise od jednog magacina koji je glavni, to treba resiti prvo. Mmix ti je pomenuo dva nacina - 1) trigger ili 2) korisnicku funkciju koju cita neki CHECK CONSTRAINT. Postoje jos barem dva nacina: 3) kakulisana kolona i 4) promena dizajna baze.

Da malo prodiskutujemo sva cetiri pomenuta nacina:

1) Trigger: Logika za triger je jasna. Ako bilo koji rekord dobije vrednost BitPolje = 1, onda svi ostali rekordi moraju da dobiju BitPolje =0. Ovo je lepo, ali opasno. Suvise je lako promeniti glavni magacin. A i triger nije bas naivan da se napise. Probajte, pa cete videti.

2) UDF sa CHECK CONSTRAINT: Za CHECK CONSTARINT prvo ti treba udf funkcija, koju pozivas iz constrainta. Imas ovede nekoliko primera gde se koriste udf u CHECK constraints: http://www.baze-podataka.net/2...-funkcija-u-check-constraints/ ili http://www.baze-podataka.net/2...nstraint-sql-rezervacija-soba/ Ni jedan od datih primera ne resava direktno tvoj problem, ali shvatices sustinu nadam se. UDF treba da prebrojava redove u tabeli koji imaju BitPolje = 1. Ako je taj broj veci od 1, UDF vraca FALSE i CONSTRAINT ne dozvoljava promenu. Ovaj nacin garantuje 'ne vise od jednog reda gde je BitPolje=1', ali dozvoljava 'nema ni jedan red gde je Bitpolje=0'

3) Kalkulisano polje. MS SQL 2005 dozvoljava kalkulisana polja. Za tvoj problem, potrebno je da imas jednu numericku kolonu koja moze da bude kljuc (NOT NULL, UNIQUE i pozitivne su sve vrednosti) Onda definises kalkulisano polje kao

MyCalcField AS CASE WHEN BitPolje = 1 THEN -1 ELSE <unique positive numeric field> END

MyCalcField ce uvek imati vrednost jednaku odgovarjucem <unique positive numeric field> ili -1. Ako stavis da MyCalcField bude UNIQUE, onda je dozvoljen najvise jedan red koji ima MyCalcField =-1. Ovim si psotigao da imas najvise jedan red gde moze biti MyCalcField =-1, sto jest BitPolje = 1. I ovaj nacin ne resava problem 'da nema manje od jednog glavnog magacina' .

4) Promena dizajna baze .
a) Izbaci BitPolje poptpuno iz tabele Magacini.
b) Uvedi novu tabelu
CREATE TABLE GlavniMagacin
(
RecID NOT NULL DEFAULT = 1 UNIQUE CHECK (RecID = 1)
, MagacinID <isti tip kao MagacinID u tabeli Magacini> NOT NULL
, FOREIGN KEY MagacinID REFERENCES tblMagacini (MagacinID)
)

Tabela GlavniMagacin moze da ima samo jedan rekord. To obezbedjuje CHECK (RecID=1) zajedno sa RecID UNIQUE
U taj jedan rekord tabele GlavniMagacin upisujes MagacinID onog magacina koji je trenutno glavni. Da ne upises nepostojeci magacin garntuje FOREIGN KEY MagacinID REFERENCES tblMagacini (MagacinID). Ovaj FK garantuje takodje da ne mozes iz glavne tabele tblMagacini da obrises rekord za glavni magacin, namerno ili nenamerno. Ne moze se obrisati roditelj sve dok postoji dete rekord u nekoj tabeli.

Uslov MagacinId NOT NULL obezbedjuje da ne mozes tek tako da iz jednoredne tabele GlavniMagacin obrises vrednost iz kolone MagacinID. Mozes da je zamenis nekom drugom vrednoscu, kad zelis da neki drugi magacin proglasis za glavni.

Ovo do sadsje garntovalo "ne vise od jednog magacina koji je glavni". Ako hoces da imas "uvek jedan magacin koji je glavni, ni vise ni MANJE" onda treba na tabelu GlavniMagacin da dodas triger koji sprecava brisanje tog jednog jedinog rekorda. Trigger bi imao jednu jedinu komandi i bio bi FOR DELETE. Komanda bi bila 'rollback', ovako nekako:

CREATE TRIGGER nema_brisanja_GlavniMagacin
FOR DELETE AS
rollback
GO

Ovim dobijas da ne moze da se obrise rekord iz tabele GlavniMagacin. Posto kolona MagacinID ne sme da bude NULL, uvek ces morati da imas neki magacin koji je glavni.

Resenje sa promenom dizajna izgleda najkomplikovanije ali je u sustini najlakse. Triger je trivijalno jednostavan, a sve ostalo je reseno samim dizajnom tabele GlavniMagacin (tacno jedan rekord, MagacinID mora da bude popunjen uvek, ne noze da se obrise kolona MagacinID, ne moze da se obrise ceo rekord, ne moze da se obrise rekord sa glavnim magacinom u polaznoj tabeli).

I uslov 'da nema manje od jednog glavnog magacina' je zadovoljen. Ako uslov 'da nema manje od jednog glavnog magacina' nije obavezan, onda samo dozvolis NULL za MagacinID i to je sve.

:-)








 
Odgovor na temu

[es] :: MS SQL :: Ogranicenje u celoj tabeli

[ Pregleda: 1487 | Odgovora: 2 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.