Pretpostavimo da ne mozes da menjas dizajn tabela, takav je kakav je. Imamo dakle problem da za jednu kombinaciju (Artikl, BarCode) dozvolimo samo jednom Osnovni = 1 i neogranicen broj redova sa Osnovni = 0. Moze dakle triger, a moze i stored procedura. Nasao sam i treci ancin - CHECK CONSTRAINT.
Malo poznata osobina MS SQL 2005 jeste da se u CHECK CONSTRAINTS mogu koristiti skalarne funkcije. N a osnovu definicije tabele koju si dao i pretpostavke "za jednu kombinaciju (Artikl, BarCode) dozvolimo samo jednom Osnovni = 1 i neogranicen broj redova sa Osnovni = 0" uradio sam sledece:
Code:
-- kreiramo tabelu:
CREATE TABLE BarKodovi
(
[ID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[ART_ID] [int] NULL,
[barcode] [varchar](30) NULL,
[faktor] [float] NULL,
[tip] [varchar](1) NULL,
[OSNOVNI] [int] DEFAULT 1 CHECK ([OSNOVNI] IN (1,0))
)
GO
-- napisemo funkciju koja prebrojava koliko se puta Osnovni=1 javlja za datu kombinaciju (Artikl, BarCode)
CREATE FUNCTION dbo.SamoJedanOsnovni(@Artikl_ID int, @BArCode varchar(30))
RETURNS int
AS
BEGIN
DECLARE @BrojOsnovnih int
SET @BrojOsnovnih = (SELECT COUNT(*) FROM BarKodovi
WHERE BarCode = @BArCode
AND [ART_ID] = @Artikl_ID
AND Osnovni = 1
)
RETURN @BrojOsnovnih
END
GO
--- Sad dodamo constraint pre dodavanja ikakvih podataka u tabelu
--- Ako vec postoje neki podaci, ADD CONSTRAINT ce raditi samo ako su postojeci podaci u redu
ALTER TABLE BarKodovi
ADD CONSTRAINT BarKodovi_SamoJedanOsnovni CHECK (dbo.SamoJedanOsnovni([ART_ID],[barcode])=1)
GO
-- Sad cemo da testiramo resenje ---
-- Posto je tabela prazna, ovo bi trebalo da prodje:
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '12345', 1.6, 'A', 1 )
-- rezultat:
(1 row(s) affected)
-- naravno da je proslo:
SELECT * FROM BarKodovi
ID ART_ID barcode faktor tip OSNOVNI
----------- ----------- ------------------------------ ---------------------- ---- -----------
1 1 12345 1.6 A 1
-- moze li jos jednom isti barcode, osnvni = 1?
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '12345', 1.6, 'A', 1 )
-- ne moze, vec imamo jeda :-)
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "BarKodovi_SamoJedanOsnovni". The conflict occurred in database "Dejan", table "dbo.BarKodovi".
The statement has been terminated.
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '12345', 1.6, 'A', 0 )
-- (1 row(s) affected)
-- jos jedan sa 0?
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '12345', 1.6, 'A', 0 )
(1 row(s) affected)
SELECT B.* , Retval = dbo.DaLiMozeOsnovni(ART_ID,barcode)
FROM BarKodovi AS B
-- Da unesemo novu kombinaciju, isti artikl, drugaciji bar kod, ali da je Osnovni = 0, a da pre toga nije bio OSnovni = 1:
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '55555', 1.6, 'A', 0 )
---
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "BarKodovi_SamoJedanOsnovni". The conflict occurred in database "Dejan", table "dbo.BarKodovi".
The statement has been terminated.
-- Super, ne dozvoljava da se unese prva instanca a da je Osnovni = 0
-- Probajmo na 'pravi nacin', prvo Osnovni=1 pa onda dalje:
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '55555', 1.6, 'A', 1 )
(1 row(s) affected)
-- onda jos 2-3 puta ovo:
INSERT INTO BarKodovi
([ART_ID],[barcode],[faktor],[tip],[OSNOVNI])
VALUES ( 1, '55555', 1.6, 'A', 0 )
Bez trigera is tored procedura (daleko bilo !) dobili smo resenje koje za par (Artikl, BarCode):
a) dozvoljava da bude samo jedan Osnovni=1
b) dozvoljava neogranicen broj redova sa Osnovni=0
c) zahteva da prva instanca uvek bude Osnovni = 1 - nece da prihvati Osnovni = 0 ako ne postoji Osnovni = 1
I sve to radi na nivou tabele, sto obezbedjuje maksimalan stepen integritetta podataka
Jos uvek smatram da nesto nije u redu sa dizajnom tabela. Ovo mora da moze i drugacije i bilo bi bolje.
Samo sam hteo da pokazem sta se moze uraditi sa CHECK CONSTRAINTS i funkcijama. Budite an oprezu, ako vam se cini da bas nista drugo ne pomaze, nego morate da radite ovo sto sam upravo pokazao, verovatno imate problem negde u logickom dizajnu tabela.