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

Provare da li je niz podataka vec upisan

[es] :: Baze podataka :: Provare da li je niz podataka vec upisan

[ Pregleda: 2666 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

gristic
Goran Ristic
Nis

Član broj: 27204
Poruke: 121
91.150.126.*



Profil

icon Provare da li je niz podataka vec upisan17.02.2009. u 12:19 - pre 184 meseci
Pozdrav svima,

Imam tabelu gde upisujem niz elelemenata sa serijskim brojevima i to Serijski broj prvog elementa u nizu i serijski broj poslednjeg elementa u nizu. Kako najednostavnije i najbrze da kod novog unosa elementa proverim dali je taj niz serijskih brojeva vec unet?

Unapred hvala snima na pomoci.
 
Odgovor na temu

Zidar
Canada

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



+79 Profil

icon Re: Provare da li je niz podataka vec upisan17.02.2009. u 14:40 - pre 184 meseci
Problem deluje jednostavno, ali nije bas potpuno jednostavan. Daj strukturu tabele (CREATE TABLE), onda daj neke test podatke (INSERT INTO...) pa cemo ti pomoci da napravis kveri. Daj i malo vise detalja, ne vidimo sve sto treba iz pitanja.
Citat:
Serijski broj prvog elementa u nizu i serijski broj poslednjeg elementa u nizu
A sta je izmedju? Da li serijski brojevi idu sekvencijalno i kontinulano (nema rupa)?

 
Odgovor na temu

gristic
Goran Ristic
Nis

Član broj: 27204
Poruke: 121
77.46.219.*



Profil

icon Re: Provare da li je niz podataka vec upisan17.02.2009. u 18:37 - pre 184 meseci
Ovako, tabela je sledeca:

CREATE TABLE [dbo].[InterniMagacin](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[TipKarte] [nvarchar](50) NOT NULL,
[OdBroja] [nvarchar](10) NOT NULL,
[DoBroja] [nvarchar](10) NOT NULL,
[Kolicina] [int] NOT NULL,
[Status] [int] NULL,
[UserName] [nvarchar](50) NOT NULL,
[DatumVreme] [datetime] NOT NULL,
CONSTRAINT [PK_InterniMagacin] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Neki primer podataka je:

Insert into InterniMagacin VALUES (NULL,'ZZ1','00100','00199',100,0,'user',nekidatumivreme)
Insert into InterniMagacin VALUES (NULL,'ZZ1','00450','00589',140,0,'user',nekidatumivreme)
...
Insert into InterniMagacin VALUES (NULL,'ZZ1','00780','00800',21,0,'user',nekidatumivreme)


Tako ubacujem nove tipove karata sa njihovim serijskim brojevima. Ti serijski brojevi idu redom i nema preskakanja tj. OdBroja do DoBroja u jednom unosu su ukljuceni svi brojevi, ali onda moze da postoji pauza izmedju serijskih brojeva i serijskih broja za novi unos (kao sto je prikazano u primeru)

Mene zanima kako da kod sledeceg unosa proverim da nije mozda vec unet taj opseg serijskih brojeva npr: od 00150-00170.

Nadam se da sam bio malo jasniji.

Pozdrav
 
Odgovor na temu

Zidar
Canada

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



+79 Profil

icon Re: Provare da li je niz podataka vec upisan17.02.2009. u 22:12 - pre 184 meseci
Code:

TipKarte OdBroja DoBroja    Kolicina      Status
-------- ------- ------- ----------- -----------
ZZ1      00100   00199           100           0
ZZ1      00450   00589           140           0
ZZ1      00780   00800            21           0

(3 row(s) affected)


Sa ovakvom tabelom imas problem da definises sta je to 'opesg brojeva koji je vec upotrebljen'. Ako ponudis opseg 00150 do 00220 imas delimicno preklapanje sa 00100 do 00199. Znaci, nije dovoljno da ne dozvolis unos 00100-00199 vec i bilo kojih brojeva izmedju njih.

Tvoj problem nije samo kako da otkrijes da li vec imas nesto od ponudjenog opsega u tabeli, nego da to i sprecis.

Ne pomaze resenju sto su ti OdBroja do Broja nvarchar podaci. Ako ce uvek biti samo brojevi, onda neki INT ili cak BigINt moze mnogo bolje da obavi posao. Je brini za vodece nule, to je lako ispisati na izlazu. Pomoci cu ti da resis ovo, ali tek sutra, sad zurim kuci. Razmisli u medjuvremenu o sugestiji da promenis tip podataka za Odbroaj i DoBroja. Tek toliko da bi kveriji bili razumljiviji, da ih ne komplikujemo CAST fukncijom.

 
Odgovor na temu

gristic
Goran Ristic
Nis

Član broj: 27204
Poruke: 121
91.150.126.*



Profil

icon Re: Provare da li je niz podataka vec upisan18.02.2009. u 06:03 - pre 184 meseci
Uopste nije problem da se promeni tip podataka i da bude bigint. Hvala puno na trudu jer mi je pomoc oko ovoga bas potrebna.

Pozdrav
 
Odgovor na temu

Zidar
Canada

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



+79 Profil

icon Re: Provare da li je niz podataka vec upisan18.02.2009. u 15:36 - pre 184 meseci
OK, ako mozes da menjas tip podatka po volji, znaci da si jos u fazi projektovanja tabele. To znaci da su i druge izmene dozvoljene. prelozio bih jos jednu - kolona Kolicina ti ne treba. Vidim fda je kolicina izracunata vrednost, Kolicina = DoBroja - OdBroja + 1. Predlazem da za sada radimo sa ovakvim dizajnom:
Code:

--- izmenjena tabela:
IF OBject_ID('[InterniMagacin]') IS NOT NULL DROP TABLE [InterniMagacin]
GO
CREATE TABLE [dbo].[InterniMagacin](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[TipKarte] [nvarchar](3) NOT NULL,
[OdBroja] int NOT NULL,
[DoBroja] int NOT NULL,
--[Kolicina] [int] NOT NULL,
[Status] [int] NULL,
[UserName] [nvarchar](4) NOT NULL,
[DatumVreme] [datetime] NOT NULL,
CONSTRAINT [PK_InterniMagacin] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)

Insert into InterniMagacin VALUES ('ZZ1',100,199,0,'user',getdate())
Insert into InterniMagacin VALUES ('ZZ1',450,589,0,'user',getdate())
Insert into InterniMagacin VALUES ('ZZ1',780,800,0,'user',getdate())

SELECT TipKarte, OdBroja, DoBroja,  Kolicina = DoBroja - ODBroja +1 , Status
 FROM [InterniMagacin]

/* Rezultat:
TipKarte     OdBroja     DoBroja    Kolicina      Status
-------- ----------- ----------- ----------- -----------
ZZ1              100         199         100           0
ZZ1              450         589         140           0
ZZ1              780         800          21           0
*/

(3 row(s) affected)



Rezultat je isti kao sto smo imali dok je kolona Kolicina bila u tabeli. Da se razummemo, ni ovo nije verovatno najbolji dizajn, nije verovatno ni dobar, ali cemo se z atrenutak zadrzati, koliko d apokazemo kako se u ovakvom slucaju proverava da li se ponudjeni opseg brojeva preklapa sa nekim od postojecih. to si pitaona pocetku. A na kraju cemo da predlozimo kako treba da izgleda tabela, ili skup tabela za tvoj slucaj.

Elem, data je dakle tabele sa kolonama OdBroja, DoBroja koje cuvaju pocetnu i poslednju vrednost u nekom neprekidniom i kompletnom nizu brojeva, kao sto smo je upravo napravili. Kako proveriti da li neki novi opseg brojeva vec postoji u tabeli, ceo ili bar neki njegov deo? Ovde se radi o poredjenu dva intervala. Nazovimo ih (a,b) i (OdBroja, DoBroja). Ta dba intervala mogu da imaju sledece polozaje na brojnoj osi:

Code:

----- a ----- b ------ OdBroja -------- DoBroja ------->    ova dva se ne preklapaju uopste
----- a ------ OdBroja ---- b ---- DoBroja ------------>    preklapanje, bar jedan deo (a,b) se poklapa sa (OdBroja, DoBroja)
----- a ------ OdBroja ---- a ----- b ---- DoBroja ----->   (a,b) je potpuno unutar   (OdBroja, DoBroja) => preklapanje
----- a ------ OdBroja -------- DoBroja ----- b  ------->   (OdBroja, DoBroja) potpuno unutar (a,b) => preklapanje
----------- OdBroja ---- a ---- DoBroja ------ b ------>    delimicno preklapanje
----- OdBroja -------- DoBroja ----a ----- b ------ --->    ova dva se ne preklapaju uopste


Moguci su i slucajevi kada se a ili b poklapa sa tackama OdBroja do Broja, sto pretpostavljam nije dozvoljeno.

Moguce je napisati rogobatan izraz koji ce da sadrzi sve moguce slucajeve, ali nema potrebe.
Jedna dva slucaja koja dozvoljavamo su prvi i poslednji - kada je (a,b) potpuno izvan intervala (OdBroja, DOBroja).
Ovo se moze zapisati kao:

b < OdBroja OR a> DoBroja (vece ili jednako i manje ili jednako ne dolaze u obzir)

Znaci, ako ima sinterval (a,b) i zelis da vidis da li se preklapa sa nekim od postojecih intervala u tabeli, treba da proveris da li je tacno

b < OdBroja OR a> DoBroja

Ako je ovo tacno, intervali se ne preklapaju. Ako nije tacno, intervali se preklapaju i INSERT nije dozvoljen.

Primer, sa postojeciom tabelom i postojecim podacima, koje smo dali na pocetku.
Prva dva primera pokazuju preklapanje, poslednji interval nema preklapanje.
Code:

DECLARE @a int, @b int
SELECT @a = 150, @b = 250
-- Pokazi intervale koji se preklapaju sa (@a,@b)
SELECT 
TipKarte, OdBroja, DoBroja,  Status
FROM [InterniMagacin] 
WHERE NOT (@b < OdBroja OR @a>DoBroja)

TipKarte     OdBroja     DoBroja      Status
-------- ----------- ----------- -----------
ZZ1              100         199           0


DECLARE @a int, @b int
SELECT @a = 50, @b = 1200
-- Pokazi intervale koji se preklapaju sa (@a,@b)
SELECT 
TipKarte, OdBroja, DoBroja,  Status
FROM [InterniMagacin] 
WHERE NOT (@b < OdBroja OR @a>DoBroja)

TipKarte     OdBroja     DoBroja      Status
-------- ----------- ----------- -----------
ZZ1              100         199           0
ZZ1              450         589           0
ZZ1              780         800           0

DECLARE @a int, @b int
SELECT  @a = 250, @b = 400
-- Pokazi intervale koji se preklapaju sa (@a,@b)
SELECT 
TipKarte, OdBroja, DoBroja,  Status
FROM [InterniMagacin] 
WHERE NOT (@b < OdBroja OR @a>DoBroja)

TipKarte     OdBroja     DoBroja      Status
-------- ----------- ----------- -----------
(0 row(s) affected)


Znaci, ako kveri kao u primeru vrati neke redove - ti redovi se preklapaju sa zadatim intervalom.
Ako ne vrati nista, interval je dobar. Ako imas stored proceduru koja kontrolise INSERT u tabelu InterniMagacin, onda treba da proveris broj redova koje vraca kveri koji smo pokazali. Ovako nekako:
Code:

-- Izvrsi celu skriptu, do znaka ;
DECLARE @a int, @b int
DECLARE @count int
SELECT @a = 50, @b = 1200
-- Pokazi intervale koji se preklapaju sa (@a,@b)
SET @Count =  (SELECT COUNT(*)
                FROM [InterniMagacin] 
                WHERE NOT (@b < OdBroja OR @a>DoBroja)
                )
IF @Count > 0 -- ako imamo preklapanje, ispis poruku
BEGIN
    Print 'Zadati interval se preklapa sa nekim od postojecih intervala'
    RETURN    ---- prekini dalje izvrsavanje koda
END
---- ovo ce se izvrsiti ako i samo ako je @Count = 0
BEGIN
Insert into InterniMagacin VALUES ('ZZ1',@a,@b,0,'user',getdate())
END
; --- skriptu izvrsi dovde

-- proveri sta se desilo:
/*
SELECT TipKarte, OdBroja, DoBroja,  Kolicina = DoBroja - ODBroja +1 , Status
 FROM [InterniMagacin]

*/

-- Sad jedan koji prolazi:
-- pocetak skripte (ova treba da prodje)
DECLARE @a int, @b int
DECLARE @count int
SELECT @a = 250, @b = 400
-- Pokazi intervale koji se preklapaju sa (@a,@b)
SET @Count =  (SELECT COUNT(*)
                FROM [InterniMagacin] 
                WHERE NOT (@b < OdBroja OR @a>DoBroja)
                )
IF @Count > 0 -- ako imamo preklapanje, ispis poruku
BEGIN
    Print 'Zadati interval se preklapa sa nekim od postojecih intervala'
    RETURN    ---- prekini dalje izvrsavanje koda
END
---- ovo ce se izvrsiti ako i samo ako je @Count = 0
BEGIN
Insert into InterniMagacin VALUES ('ZZ1',@a,@b,0,'user',getdate())
END
;    -- karj skripte
-- Rezultat:

/*
SELECT TipKarte, OdBroja, DoBroja,  Kolicina = DoBroja - ODBroja +1 , Status
 FROM [InterniMagacin]

TipKarte     OdBroja     DoBroja    Kolicina      Status
-------- ----------- ----------- ----------- -----------
ZZ1              100         199         100           0
ZZ1              450         589         140           0
ZZ1              780         800          21           0
ZZ1              250         400         151           0

(4 row(s) affected)


*/




Tako nekako. Medjutim ,rekoh da ni ovo nije dobar dizajn. Problem je sto sav insert moar da ide kroz stored proceduru koju en razumes bas najbolje i nisi siguran da mozes da je napravis. A nema garncije da ce INSERT uvek ici kroz stored proceduru. Boje bi bilo da postoji neki CONSTRAINT. Moguce je napisati CONSTRAINT koji radi ovako kao sto smo opisali, ali to nije lako. Zahteva pisanje korisnicke funkcije koja s epoziva iz CHECK CONSTRAINT. Primer sa CHECK CONSTARINT i UDF funkcijom imas ovde http://www.baze-podataka.net/2...nstraint-sql-rezervacija-soba/ Primer je o rezervaciji soba - ne dozvoljva se da se rezervise soba u intervalu kad je soba zauzeta. Veoma slicno ovome sto ti radis, pa vidi.

Medjutim, prava stvar bi bila da se potpuno promeni dizajn tabele. Ako umesto intervala pamtis sve brojeve, tabela bi zigledala otprilike ovako:
Code:

TipKarte BrojKarte
ZZ1         100
ZZ1         101
ZZ1         102
....
ZZ1         199
ZZ1         450
ZZ1         451
ZZ1         452
.....
ZZ1         588
ZZ1         589
.....



Onda je dovoljno da kazes BRojKarte NOT NULL UNIQUE.
To ce te spreciti da uneses duplikate. I ne treba ti sva ova komplikacija. Kako da vidis koji brojevi su duplikati/ Upotrebi tabelu brojeva....., to je za neku drugu temu, a mislim da smo o tome pisali negde na ovom ili SQL forumu, a imas i ovde http://sqlserver2000.databases...n-auxiliary-numbers-table.html

Nadam se da je pomoglo.

:-)



 
Odgovor na temu

gristic
Goran Ristic
Nis

Član broj: 27204
Poruke: 121
91.150.121.*



Profil

icon Re: Provare da li je niz podataka vec upisan18.02.2009. u 18:41 - pre 184 meseci
Hvala puno na iscrpnom odgovoru i trudu. Mnogo si mi pomogao da resim problem.

Hvala jos jedanput.
 
Odgovor na temu

[es] :: Baze podataka :: Provare da li je niz podataka vec upisan

[ Pregleda: 2666 | Odgovora: 6 ] > FB > Twit

Postavi temu Odgovori

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