Uskrs

Tuesday, 02.09.2008 – Zidar

Pronasao sam kod za izracunavanje Uskrsa, po pravoslavnom i po katolickom kalendaru. Izvor:

http://www.tek-tips.com/faqs.cfm?fid=5075

Pravoslavni:

CREATE FUNCTION dbo.OEaster (@Yr as int)
RETURNS datetime
AS 
-- SELECT dbo.OEaster(2007)
BEGIN
   Declare @I int, @J int, @Metonic int, @EMo int, @EDay int, @LeapAdj int
   Set @LeapAdj=@Yr/100-@Yr/400-2
   Set @Metonic=@Yr % 19
   Set @I=(19*@Metonic+15) % 30
   Set @J=(@Yr+@Yr/4+@I) % 7
   Set @EMo=3+(@I-@J+40)/44
   Set @EDay=@I-@J+28-31*(@EMo/4)
   Return DateAdd(dd,@LeapAdj,cast(str(@EMo)+'/'+str(@EDay)+'/'+str(@Yr) as datetime))
/*This algorithm is based upon work done by JM Oudin in 1940.*/
End
GO

Katolicki:

CREATE FUNCTION dbo.Easter (@Yr as int)
RETURNS datetime
AS 
BEGIN
   Declare @Cent int, @I int, @J int, @K int, @Metonic int, @EMo int, @EDay int
   Set @Cent=@Yr/100
   Set @Metonic=@Yr % 19
   Set @K=(@Cent-17)/25
   Set @I=(@Cent-@Cent/4-(@Cent-@K)/3+19*@Metonic+15) % 30
   Set @I=@I-(@I/28)*(1-(@I/28)*(29/(@I+1))*((21-@Metonic)/11))
   Set @J=(@Yr+@Yr/4+@I+2-@Cent+@Cent/4) % 7
   Set @EMo=3+(@I-@J+40)/44
   Set @EDay=@I-@J+28-31*(@EMo/4)
   Return cast(str(@EMo)+'/'+str(@EDay)+'/'+str(@Yr) as datetime)
/*This algorithm is from the work done by JM Oudin in 1940 and is accurate from year 1754 to 3400.*/
END
GO

Lep dodatak standardnom setu SQL funkcija za racunanje vremena.  🙂


MS SQL bug

Tuesday, 02.09.2008 – Zidar

Nesto sto sam nedavno otkrio i opekao se: kada navodite listu kolona u SELECT izrazu, pa zaboravite zarez, MS SQL se ne buni, nego jednostavno ignorise deo naredbe. Na primer:

SELECT Artikl, cena, Kolicina FROM Roba

treba da ispise tri kolone. Ako napisete

SELECT Artikl, cena Kolicina FROM Roba

(nema vise zareza iz kolone Cena), MS SQL se nece buniti niti ce prijaviti gresku. jednostavno ce ignorisati kolonu Kolicina. Ako je SELECT izraz slozeniji, pa imate recimo GROUP BY, onda mozete da dobijete potpuno zbunjujuci rezultat.

Mozda je ovo poznato i od ranije, mozda je Microsoft cak napravi service pack, ne znam,  za mene je novost, pa eto da podelim novost.

🙂


10 odabranih tekstova iz arhive

Tuesday, 02.09.2008 – Dejan

Evo prođoše nepune 2 godine otkako postoji ovaj blog i ovo je jubilarni 100. tekst, pa bih tim povodom po subjektivnom izboru izvadio 10 kvalitetnih tekstova iz naftalina, odnosno iz arhive. 🙂

SELECT TOP 10 tekst AS “Odabrani Tekstovi” FROM tekstovi ORDER BY datum_objavljivanja;

Kreiranje uskladistene procedure (How to create MySQL stored procedure)
Spajanje neprekidnih datumskih intervala
Struktura evidencije partnera
Spajanje podataka po zajednickom atributu
Backup Oracle baze pomoću RMAN-a
Recovery Oracle baze pomoću RMAN-a
Kloniranje/dupliciranje Oracle “ASM based” baze
MS SQL Common Table Expressions
Common Table Expressions i iterativni ciklusi
Korišćenje UDF funkcija u CHECK uslovima – rezervacija soba

Ja sam lično izbrojao 26 veoma korisnih tekstova, ali sam neke nažalost morao izostaviti iz liste.

Nadam se da ste i vi našli barem jedan koristan tekst i da ćete i dalje biti uz nas!

Nastavljamo dalje u revijalnom tonu.


Cost Based Optimizer vs. nedokumentovani parametri

Monday, 01.09.2008 – Dejan

Dok sam u više navrata čitao kako pojedini administratori Oracle baze podataka bacaju drvlje i kamenje na CBO (Cost Based Optimizer), mislio sam da oni nisu pravilno konfigurisali bazu ili da imaju neprikladan hardware (premalo RAM-a i slabi CPU resursi), jer zaboga – kako CBO, kojeg Oracle diže u nebesa i sa garancijom stoji iza svog tehnološkog čeda, može POGREŠNO da “naredi” bazi kako da pristupa podacima!? E, pa može! I nisu ti administratori bez razloga kukali na pogrešno funkcionisanje CBO-a …

Pročitaj kompletan tekst »


Patchset 10.2.0.4 overwrites sqlnet.ora

Friday, 29.08.2008 – Dejan

Upozorenje za sve, koji rade sa Oracle bazom na Windows platformi i planiraju instalirati zadnji Patchset 10.2.0.4 !

Naime, u prvoj verziji ovog Patchseta postoji Bug (MetaLink Bug: 7139820), koji “overwriteuje” (dajte neki dobar prijevod za ovu riječ!) postojeću sqlnet.ora datoteku! U novoj verziji (dostupna već od 10.07.2008.) je ta greška ispravljena, pa pazite koji Patchset ćete skinuti sa MetaLinka!

Old version Platform File name MD5 Checksum Size (bytes)
10.2.0.4 Microsoft Windows (32-bit) p6810189_10204_Win32.zip 38A59D4A3B902A399119C3AC45F81A41 1034079272
10.2.0.4 Microsoft Windows (AMD64 and EM64T) p6810189_10204_MSWIN-x86-64.zip 7D0BEC8CA58C1848B36C76DA755EF149 1122742981

 

 

 

 

 

New version Platform File name MD5 Checksum Size (bytes)
10.2.0.4 Microsoft Windows (32-bit) p6810189_10204_Win32.zip AF8818947E1903D008973B9F7CF3DF5B 1034621834
10.2.0.4 Microsoft Windows (AMD64 and EM64T) p6810189_10204_MSWIN-x86-64.zip E6992224A07FC00C210140585B0CF226 1123325074

 

 

 

 

 

Što bi se reklo – rupa u zakrpi.


ODI – Oracle Data Integrator

Monday, 25.08.2008 – Dejan

Pošto dobijamo sve kompleksnije projekte, koji se baziraju na više platformi i okruženja, postavilo se pitanje – “Kako sve te podatke iz različitih izvora skupiti i obraditi na jednom mjestu?“.

Npr. imamo problem kako izvući podatke iz SimCorp aplikacije (Oracle na IBM AIX platformi), zatim iz SAP aplikacije (Oracle na Windows platformi) i podatke iz našeg Data Warehousea (Oracle na Windows platformi), te potom sve te podatke obraditi i pohraniti na jednom mjestu…

Gledali smo nekoliko rješenja – Cognos, IBM DataStage, Server Integration Service od Microsofta, Oracle Data Integrator i još par drugih, ali smo se na kraju odlučili upravo za Oracle Data Integrator (ODI) .

Šta je ODI?
ODI
je ETL (Extract Transform Load) alat pomoću kojeg je moguće izvući podatke iz različitih izvora (Extract), transformisati ih prema zadanim kriterijima (Transform) i onda ih pohraniti (Load) na željenoj lokaciji (npr. u Oracle bazu). Doduše, ODI se predstavlja i kao E-LT (Extract – Load Transform) alat, ali u osnovi je to ipak ETL alat.

Po meni je ODI veoma kompleksan, glomazan i zahtjevan za korištenje, ali je istovremeno – zbog svih mogućnosti i opcija, koje nudi – fleksibilan i moćan. Pošto je urađen u Javi, moguće ga je koristiti na svakoj platformi, koja podržava Javu.

Sama instalacija nije zahtjevna, ali da biste napravili nešto konkretno sa ODI-om, morate dobro pročitati dokumentaciju i preći par praktičnih primjera. Mi smo imali dvodnevnu prezentaciju i radionicu, na kojoj smo isprobali tek mali dio opcija, koje ODI sadrži, ali tek nakon 10-15 dana svakodnevnog rada sa ODI-om, ulazi se u rutinu i tada ODI postaje “prijateljski” alat.

Okačiću nekoliko screenshotova, na kojima se može vidjeti funkcionalnost ODI-a, a ukoliko želite saznati više informacija, onda morate posjetiti službenu Oracle Data Integrator (ODI) stranicu.

Imam još i .ZIP datoteku (ca. 7.5 MB) sa PowerPoint prezentacijom, na kojoj su prikazani ODI arhitektura, instalacija, transformacija podataka, Metadata navigator i dodatni moduli, pa koga zanima, nek ostavi email adresu u komentaru…

Edit 05.09.2008. : Našao sam jedan opširniji opis ODI-a na engleskom jeziku – Thoughts on Oracle Data Integrator .

 

   
  
   


Novi tekstovi nakon godišnjeg odmora

Monday, 25.08.2008 – Dejan

Evo prođe i doba godišnjih odmora – ljeto je pri kraju, napunili smo baterije, odmorili se od kompjutera i baza podataka, pa smo sa svježom energijom spremni za nove radne pobjede i za pisanje novih tekstova.

Ja ću u narednim tekstovima pisati o nekoliko grešaka, koje smo dobijali u zadnje vrijeme koristeći Oracle bazu, kao i o rješenjima tih grešaka, zatim ću pisati o Oracle Data Integratoru i drugim korisnim alatima, a napisaću i par recenzija knjiga sa Oracle tematikom.

Kolege Srđan i Zidar imaju takođe u planu nekoliko tekstova, ali im fali malo motivacije za pisanje i objavljivanje tih tekstova – stoga, ukoliko želite da i dalje čitate korisne i kvalitetne tekstove, onda ostavljajte komentare, pišite nam na naše E-Mail adrese i dajte nam sugestije, prijedloge, kritike, pohvale i sl. !!!


NULLS, LEFT JOIN, EXISTS i NOT IN

Friday, 04.07.2008 – Zidar

Kada zelimo da uporedimo dve tabele A i B, i da pokazemo koji su redovi prisutni u A, a nema ih u B (Accessov ‘unmatched query’), to generalno mozemo da uradimo na nekoliko nacina. Mozemo da upotrebimo LEFT JOIN, mozemo da upotrebimo NOT IN ili NOT EXISTS. Da li su svi nacini podjednako dobri i pouzdani? Podjednako dobri znaci podjednako brzi, a pouzdani znaci da li daju tacan rezultat. Zanimljivo pitanje, da li daju tacan rezultat.

Pogledajmo primer. Kreirajmo dve jednostavne tabele i napunimo ih test podacima.

CREATE TABLE A (Broj smallint, ime VARCHAR(5))
GO
INSERT INTO A (Broj, ime) VALUES (1,‘Aca’)
INSERT INTO A (Broj, ime) VALUES (2,‘Maca’)
INSERT INTO A (Broj, ime) VALUES (3,‘Caca’)
INSERT INTO A (Broj, ime) VALUES (5,‘Aca’)
INSERT INTO A (Broj, ime) VALUES (6,‘Aca’)
GO
CREATE TABLE B (Broj smallint, ime VARCHAR(5))
GO
INSERT INTO B (Broj, ime) VALUES (1,‘Aca’)
INSERT INTO B (Broj, ime) VALUES (NULL,‘Maca’)
INSERT INTO B (Broj, ime) VALUES (5,‘Caca’)
GO   

Pokusajmo da upotrebimo NOT IN da pokazemo, koji brojevi su u tabeli A, a nisu u tabeli B:

SELECT A.* 
FROM A
WHERE Broj NOT IN (SELECT Broj FROM B) 

Sledi rezultat:

  Broj  ime
-----  ------
(0 row(s) affected)

Ocigledno je da rezultat nije tacan. Pokusajmo sa NOT EXISTS:

SELECT A.* 
FROM A 
WHERE NOT EXISTS (SELECT Broj FROM B WHERE B.Broj = A.Broj)  

Rezultat je ovaj put tacan:

 Broj  ime
----- -----    
     2  Maca      
     3  Caca      
     6  Aca 

(3 row(s) affected)

Da probamo i LEFT JOIN:

SELECT A.* FROM A
LEFT JOIN B ON A.Broj = B.Broj
WHERE B.Broj IS NULL 

Dobijamo ponovo tacan rezultat:

 Broj  ime
----- -----
     2  Maca      
     3  Caca      
     6  Aca 

(3 row(s) affected)

Zasto je ovo ovako? Primetite da u tabeli B imamo na jednom mestu NULL. E, taj jedan NULL cini da ono sto imamo u IN (SELECT…) vraca NULL. Onda <nesto> IN NULL vraca NULL.

Sta bi bilo kad bi i prva tabela A imala neki NULL u koloni Broj?


UPDATE A SET Broj =  NULL WHERE ime = ‘Caca’
 

 

SELECT * FROM A


    Broj  ime
-------  ------
      1   Aca
      2   Maca
NULL  Caca
      5   Aca
      6   Aca

(5 row(s) affected)

‘ajmo sve ponovo:

SELECT A.* FROM A
WHERE Broj NOT IN (SELECT Broj FROM B)

  Broj ime
-----  -------
(0 row(s) affected)

SELECT A.* 
FROM A
WHERE NOT EXISTS (SELECT Broj FROM B WHERE B.Broj = A.Broj)

  Broj ime
—— —–
     2 Maca
  NULL Caca
     6 Aca
(3 row(s) affected)


SELECT A.*
FROM A
LEFT JOIN B ON A.Broj = B.Broj
WHERE B.Broj IS NULL

  Broj ime
—— —–
     2 Maca
  NULL Caca
     6 Aca
(3 row(s) affected) 

Kao sto se moglo ocekivati, NOT IN gresi, dok NOT EXISTS i LEFT JOIN rade.

Na nesrecu, NOT IN se mnogo lakse pise nego NOT EXISTS ili LEFT JOIN. Da stvar bude gora, u ranijim verzijama MS SQL, NOT EXISTS je radio znatno brze nego NOT IN.
E, MS SQL 2005 je ‘ispravio gresku’, te sada NOT IN radi isto tako brzo kao NOT EXISTS ili LEFT JOIN.
I to Microsoft oglasava kao ‘major improvement’, kao lakse se pise kod, zaboravite komplikovane sintakse itd.

Da se razumemo, ako nema NULL, onda sva tri nacina daju tacan rezultat. Znaci, dobar dizajn baze sa izbegavanjem NULL koiko god moze, pomaze da vas neki suptilni bagovi ne udare po glavi.

Ovaj “Write Post” editor me ubija. Dodaje razmake kad mu se prohte, prelama red gde mu padne napamet. Mislio sam da 30 godina od kako su kopjuteri izmisljeni mogu da naprave ljudski editor za web. Izgleda da nema nista od toga. Sve sto nije plain text mozes da zaboravis… Tuga jedna i zalost.

🙂


Temp tabele

Wednesday, 02.07.2008 – Zidar

Koliko puta mi se desilo da pokusam da izvrsim nesto ovako:

SELECT * INTO #TempTAble FROM MyTable

da bih dobio poruku

Msg 2714, Level 16, State 6, Line 1 There is already an object named ‘#TempTable’ in the database.

Pokusaj da ordadim ovo:

IF  Object_id(‘#TempTable’) IS NOT NULL DROP #TempTable

daje mi ovo:

Msg 102 , Level 15, State 1,  Line 1 Incorrect syntax near ‘#TempTable’

Naravno, Object_ID radi samo sa ‘lokalnim’ tabelama. Medjutim, pametni ljudi nadju reseje za sve. Jedna pametan covek, Itzik Ben-Gan, u knjizi “Inside Microsofr SQL Server 2005: T-SQL programming” dao je ovakvo resenje:

IF Object_id(‘tempdb..#TempTable’) IS NOT NULL DROP TABLE #TempTable

Radi bez greske, pa mogu da napisem:

IF Object_id(‘tempdb..#TempTable’) IS NOT NULL DROP TABLE #TempTable
SELECT   *  INTO #TempTable FROM dbo.Board
i da me vise ne moram da mislim da li sam dropnuo ili nisam temp tabelu.

U istoj knjizi pise i da se temp tabela moze indeksirati, na primer
— Add some indexing:

CREATE  UNIQUE CLUSTERED INDEX id_tblSIF ON #tblSIF (StudentBarcode, FieldName)

Moja tabela od 500,000 slogova ce sada mnogo brze da odgovara na upite.

 


ORA-01093: ALTER DATABASE CLOSE only permitted with no sessions connected

Tuesday, 27.05.2008 – Dejan

Ako pokušavate uraditi prebacivanje primarne baze u standby bazu, može se desiti da dobijete ovu grešku:
ORA-01093: ALTER DATABASE CLOSE only permitted with no sessions connected

Prebacivanje (switchover) primarne baze u standby je moguće bez problema ukoliko u koloni v$database.SWITCHOVER_STATUS stoji vrijednost TO STANDBY. Međutim, ukoliko stoji vrijednost SESSIONS ACTIVE, onda će naredba “alter database commit to switchover to physical standby” javiti gorenavedenu grešku.

SQL> select switchover_status from v$database;
SWITCHOVER_STATUS
--------------------
SESSIONS ACTIVE

SQL> alter database commit to switchover to physical standby;
alter database commit to switchover to physical standby;
*
ERROR at line 1:
ORA-01093: ALTER DATABASE CLOSE only permitted with no sessions connected

Listu aktivnih korisnika možete dobiti pomoću ovog upita:

SQL> select sid, process, program 
from v$session 
where type = 'USER' and sid <> (select distinct sid from v$mystat);

       SID PROCESS      PROGRAM
---------- ------------ --------------------
       468 2340:3416    racgimon.exe
       469 2340:3392    racgimon.exe
       470 2340:1548    racgimon.exe
       501 2340:3392    racgimon.exe

Rješenje je dodati klauzulu “WITH SESSION SHUTDOWN“, nakon čega će postupak prebacivanja (switchover) biti uspješan:

SQL> alter database commit to switchover to physical standby with session shutdown;

Ova naredba će prvo obustaviti sve korisničke radnje, pa tek potom obaviti prebacivanje primarne baze u standby bazu.

Napomena: U ovom slučaju smo racgimon.exe mogli zaustaviti i naredbom:

racgimon stop <instanca>
ili
racgimon stopd <ime_baze>