ORACLE APEX – Brza izrada web aplikacija

Monday, 15.11.2010 – mmilosevic

    Za sve one kojima je interesantan brz razvoj web aplikacija uz korišćenje ORACLE alata evo za početak nekih osnovnih objašnjenja u kome ću vas ukratko upoznati sa ovim alatom ORACLE alatom i njegovim principima.

    Ukoliko ste se bavili razvojema MS Access baza podataka i poželeli da pređete na razvoj Web aplikacija koje u pozadini imaju ORACLE bazu, onda je ovo pravo rešenje za vas. ORACLE APEX još nazivaju ‘MS ACCESS na steroidima’ i kažu da ga koristi 45 000 ORACLE klijenata u svetu.

 apex_korisnici

Neki korisnici ORACLE APEX-a

 

Pored toga, teoretski je moguće lako preobraziti ono što ste razvijali u MS Access-u u ORACLE APEX, odnosno izvršiti migraciju Access aplikacije tako da sve to funkcioniše na web-u, mada u praksi to ne ide baš tako lako.

 

 accessmigracija1

Migracija MS Access aplikacije u ORACLE APEX

 

U svakom slučaju, ako želite da uplovite u PL/SQL, a pomalo i u JavaScript i DHTML vode, te da se pozabavite ORACLE bazom i web programiranjem, ORACLE APEX je odličan izbor.

 

Šta je ORACLE APEX (ORACLE APplication EXpress)?

 

    To je HTML DB platforma za razvoj web baziranih aplikacija koja su utemeljene na Oracle serveru baze podataka i koja svoj rad zasniva na RAD (Rapid Application Development) principima. Za korišćenje APEX okruženja u kreiranju data-centričnih web aplikacija potreban je samo web čitač (web browser), a to je, takođe i jedini alat koji je potreban i krajnjem korisniku aplikacije. To znači da krajnji korisnici mogu raditi na heterogenim operativnim sistemima i da mogu da koriste bilo koji od poznatih web čitača za pristup aplikaciji, odnosno Oracle bazi podataka posredstvom Oracle APEX sistema.

                Oracle APEX okruženje omogućuje:

  • Razvoj profesionalnih web aplikacija koje su brze i sigurne,
  • Pokretanje i rad u okviru Oracle baze podataka, pri čemu su APEX resursi i meta podaci smešteni u tabele Oracle baze,
  •  Besplatan razvoj web aplikacija jer licenca nije potrebna,
  • Jedonstavnost u distribuciji aplikacija nezavisno od okruženja i platformi,
  • Fleksibilnost u preilagođavanju izgleda i funkcionalnosti aplikacije,
  •  Skalabilnost i mogućnost pristupa velikog broja korisnika, itd.

 Evo i nekih dodatnih objašnjenja koja početnicima za sada nisu važna:

    Oracle APEX egzistira na Oracle bazi podataka, svi meta podaci, kao i PL/SQL kod i JavaScript API su smešteni u samu bazu. Zahtev upćen iz web čitača (URL) se transformiše u odgovarajući PL/SQL poziv prema Oracle HTTP serveru (Apache):

apex_arhitektura_1

 

 ili prema PL/SQL Gateway-u (Embeded PL/SQL Gateway):

apex_arhitektura_2

što zavisi od tipa APEX instalacije u okviru Oracle baze podataka. Pošto zahtev bude obrađen, rezultati se vraćaju u web čitač u HTML obliku. Ovaj ciklus se izvršava svaki put kada korisnik upućuje zahtev, a stanje aplikacijskih sesija se smešta u Oracle bazu podataka.

Mislim da je za početak dovoljno, uskoro sledi uputstvo za instalaciju ORACLE APEX-a, a do tada svi zainteresoveni mogu malo ‘prošetati’ do http://apex.oracle.com.


Kursevi u Zagrebu

Thursday, 04.11.2010 – Dejan

Naletih na dva napredna kursa, koja će se održati u Zagrebu 18. i 19.11.2010.:

Advanced Partitioning with Martin Jensen
http://www.oracle.com/go/?&Src=7026556&Act=49&pcode=WWOU10048741MPP144

Advanced Materialized Views with Martin Jensen
http://www.oracle.com/go/?&Src=7026556&Act=50&pcode=WWOU10048741MPP145

Meni firma platila oba kursa, pa sam tako od 17.11. uveče do 19.11. popodne u Zagrebu. Ako još neko ide na ova dva kursa, nek se javi, da popijemo cugu i tako to…

Edit (26.11.2010):
Evo da napišem još par dojmova u vezi seminara/kurseva u Zagrebu:
– Martin Jensen me impresionirao već samom činjenicom da radi sa Oracleom skoro 30 godina (od 1981.)
– nije smarao tokom predavanja, već je sa dozom humora i interakcijom sa prisutnima veoma efektivno objašnjavao i najkompleksnije teme
– sadržaj je bio poučan – koliko god ja mislio da znam dovoljno o particijama i “materialized views” (ko mi ovo prevede smisleno, ima pivo i ćevape od mene), našlo se stvari o kojima pojma nisam imao ili o kojima sam samo čitao, ali nisam probao u praksi, npr. PCT (Partition Change Tracking) ili ALTER MATERIALIZED VIEW dummy_mv CONSIDER FRESH;
– Goga i Dijana iz Oracle University Hrvatska su stvarno bile ljubazne i uslužne – za svaku pohvalu!!
– ne znam da li se uz svaki seminar/kurs dobija doručak i ručak, plus Nesscaffe, sokovi i grickalice, ali bi bilo super! 🙂 Hrana je bila fenomenalna!

Šta više reći, nego – vidimo se opet u Zagrebu!

Oracle seminar with Martin Jensen: Advanced Materialized Views and Partitioning


Posao za Java programera

Monday, 18.10.2010 – Dejan

Kao što napisah u zadnjem postu, tu i tamo se kod nas u firmi pojavi potreba za novim programerima. Danas je opet taj dan!

Potreban nam je solidan Java programer, za održavanje postojećih i razvoj novih aplikacija. Poželjno je napredno (ili barem srednje-napredno) poznavanje Java prog. jezika i Spring frameworka. Ostale tehnologije kao što su JSF, CSS i sl. su dodatni plus.
Potrebno je poznavanje njemačkog jezika za osnovnu komunikaciju, kao i posjedovanje radne vize za Austriju. Ako nemate radnu vizu, nemojte se javljati na ponudu, jer neće biti uzeta u obzir.

Firma: Erste Asset Management GmbH (100% u vlasništvu Erste banke)
Lokacija: Beč
Vrsta zaposlenja: Saradnja u obliku vanjskog konsultanta (DE: Selbsständiger), 35-50 EUR/h (zavisno o kvalifikacijama)

Zainteresovani kandidati mogu poslati svoj CV NA NJEMAČKOM jeziku na adresu dejan.topalovic AT sparinvest.com, sa naznakom “Posao: Java programer – <Ime i prezime>”. Ponuda važi do 31.10.2010.


Ljudi – ne dajem ja plate, ja samo čitam vijesti…

Thursday, 07.10.2010 – Dejan

Neki možda znaju šta je Top Lista Nadrealista i sjećaju se scene u kojoj Nele čita vijesti u vezi plata, pa ga onda cima masa ljudi “kad će biti plata!?“, na šta on energično odgovara:”Ama ljudi – ne dajem ja plate, ja samo ČITAM vijesti!!

E, ista situacija je kod mene u vezi tematike “posao u Beču”… Otkako sam napisao par postova, u kojima se traže Oracle i Java stručnjaci, počeo sam maltene svakodnevno dobijati E-Mail poruke sa raznoraznim sadržajem, u kojima me ljudi moljakaju da im nađem bilo kakav posao u Austriji. Počevši od raznih studenata, preko “stručnjaka sa iskustvom”, pa do sezonaca u stilu “daj bilo kakav posao – sve ću da radim!”…

Na stranu to, što je većina tih poruka napisana polupismeno sa hrpom grešaka, nego što su napisane neozbiljno i “usputno”. Ja mogu i da pređem preko tih “banalnosti”, ali vjerujte mi da se takvim pristupom posao kod drugih firmi sigurno ne može naći… A CV je mnogima špansko selo…

No, da skratimo priču – ljudi, nemojte mi slati poruke sa molbama da vam nađem bilo kakav posao!! Nisam ja biro za zapošljavanje, niti job portal.

Tu i tamo se kod nas otvori neka ponuda za Oracle ili Java stručnjacima, nakon čega mogu postaviti oglas ovdje na blogu, ali je nažalost za mnoge prepreka neposjedovanje radne vize za EU.

Za one, koji su u potrazi za poslom u Austriji, mogu posjetiti ove job portale i tamo pogledati trenutne ponude:

http://karriere.at/
http://www.jobpilot.at/
http://derstandard.at/Karriere
http://www.monster.at/

Nemojte se ljutiti, ukoliko niste dobili odgovor na vaše pitanje u vezi zaposlenja.


Nastavak price o poredjenju tabela

Wednesday, 01.09.2010 – Zidar

Moj poslednji clanak, prica o poredjenju tabela, ostao je nezavrsen. http://www.baze-podataka.net/2010/08/31/poredjenje-tabela/

 

Pokazali smo kako se mogu porediti dve tabele, pod odredjenim uslovima, ali nismo dali jedinstveni kveri. Zavrsili smo sa tri kverija i obecanjem da u sledecm nastavku krenemo nekim drugim putem. Pre nego sto krenemo drugim putem, ipak da zavrsimo nezavrsen posao. Napisacemo kveri koji se bazira na JOINu izmedju tabela koje posmatramo i sakuplja sve slucajeve u jedan.

 

Ovako smo bili definisali slucajeve kad se tabele razlikuju:

    ID postoji u Original, a nema ga u Kopija

    ID postoji u Kopija a ndma ga u Original

    ID postoji u obe tabele, ali se neke od kolone razlikuju u odgovarajucim redovima

 

Kreirajmo tabele sa test podacim, tao da su zadovoljeni sledeci uslovi:

    -. U obe tabele ID ima osobine primarnog kljuca – nema NULL i nema duplikata u koloni ID.

    – U svakoj tabeli postoji po neki ID koji ne psotoji u drugoj.

    – Postoje i redovi gde je isti ID ali se razlikuju podaci u ponkoj koloni. – – Imamo i NULL vrednosti u ponekoj koloni koja nije ID.

 

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

;

CREATE TABLE #Original (ID int , Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Original VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Original VALUES (99,‘Simo’,‘Esic’)

INSERT INTO #Original VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Original VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Original VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Original VALUES (6,‘Mesa’,‘Selimovic’)

;

IF Object_ID(‘tempdb..#Kopija’) IS NOT NULL DROP TABLE #Kopija

;

CREATE TABLE #Kopija (ID int , Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Kopija VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Kopija VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Kopija VALUES (3,‘Zzzzzzuko’,‘Dzumhur’)

INSERT INTO #Kopija VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Kopija VALUES (55,‘Branko’,‘Copic’)

INSERT INTO #Kopija VALUES (6,‘Mesa’,NULL)

;

 

SELECT ‘Original’, * FROM #Original

;

SELECT ‘Kopija’, * FROM #Kopija

;

                  ID Ime          Prezime

——– ———– ———— ————

Original           1 Dusko        Radovic

Original          99 Simo         Esic

Original           3 Zuko         Dzumhur

Original           4 Momo         Kapor

Original           5 Branko       Copic

Original           6 Mesa         Selimovic

 

(6 row(s) affected)

 

                ID Ime          Prezime

—— ———– ———— ————

Kopija           1 Dusko        Radovic

Kopija           2 Simo         Esic

Kopija           3 Zzzzzzuko    Dzumhur

Kopija           4 Momo         Kapor

Kopija          55 Branko       Copic

Kopija           6 Mesa         NULL

 

(6 row(s) affected)

 

Napisimo kveri koji pokazuje redve koji se razlikuju medju posmatranim tabelama. Razlike su definisane ovako:

    ID postoji u Original, a nema ga u Kopija

    ID postoji u Kopija a ndma ga u Original

    ID postoji u obe tabele, ali se neke od kolone razlikuju

 

Kveri:

 

SELECT

StaJeOvo = ‘ID postoji u #Original, nema ga u #Kopija’

, O.*

FROM #Original AS O

LEFT JOIN #Kopija AS K ON O.ID = K.ID

WHERE K.ID IS NULL

UNION ALL

SELECT

StaJeOvo = ‘ID postoji u #Kopija, nema ga u #Original’

, K.*

FROM #Original AS O

RIGHT JOIN #Kopija AS K ON O.ID = K.ID

WHERE O.ID IS NULL

UNION ALL

SELECT

STaJeOvo = ‘#Original’

, O.*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

UNION ALL

SELECT

STaJeOvo = ‘#Kopija’

, K.*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

 

Ovaj monstrum od kverija vraca tacan rezultat:

 

StaJeOvo                                           ID Ime          Prezime

—————————————– ———– ———— ————

ID postoji u #Original, nema ga u #Kopija          99 Simo         Esic

ID postoji u #Original, nema ga u #Kopija           5 Branko       Copic

ID postoji u #Kopija, nema ga u #Original           2 Simo         Esic

ID postoji u #Kopija, nema ga u #Original          55 Branko       Copic

#Original                                           3 Zuko         Dzumhur

#Original                                           6 Mesa         Selimovic

#Kopija                                             3 Zzzzzzuko    Dzumhur

#Kopija                                             6 Mesa         NULL

 

(8 row(s) affected)

 

Teorijski, resili smo problem pordejenja dve tabele koje imaju kolonu (ili kolone) sa osobinama primarnog kljuca po kome se mogu vezati. Nisam siguran da ce ovaj metod zaziveti u praksi, kveri izgleda kao monstrum, nije lak za razumevanje i greske su moguce sto moze dovesti do prividno tacnih rezultata.

 

Potreban nam je neki jednostavniji kveri, jednostavniji za razumevanje. Postoje bar jos dva nacina. Jedan je standardni SQL, a drugi koristi MS SQL funkcije za rad sa skupovima.

 

Drugo resenje, standardni SQL

 

Ako su tabele identicne, red po red, kolona po kolona, njihova unija imace po dva ista reda. Neka imamo identicne tabele, ovako:

 

— Sample data – identical tables:

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

CREATE TABLE #Original (ID int PRIMARY KEY, Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Original VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Original VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Original VALUES (3,‘Zuko’,‘Dzumhur’)

;

IF Object_ID(‘tempdb..#Kopija’) IS NOT NULL DROP TABLE #Kopija

CREATE TABLE #Kopija (ID int PRIMARY KEY, Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Kopija VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Kopija VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Kopija VALUES (3,‘Zuko’,‘Dzumhur’)

;

Unija ove dve table izgleda ovako:

 

SELECT * FROM #Original

UNION ALL

SELECT * FROM #Kopija

;

Unija dve tabele:

 

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          2 Simo         Esic

          3 Zuko         Dzumhur

          1 Dusko        Radovic

          2 Simo         Esic

          3 Zuko         Dzumhur

 

(6 row(s) affected)

 

Ocigledno je da u uniji svaki red je ponovljen dva puta, dve identicne kopije svakog reda postoje. Ako uradimo GROUP BY nad unijom po svim kolonama dobicemo ovako nesto:

 

SELECT ID, Ime, Prezime, COUNT(*) AS Cnt

FROM

(

SELECT * FROM #Original

UNION ALL

SELECT * FROM #Kopija

) AS X

GROUP BY ID, Ime, prezime

;

 

Rezultat poslednje operacije je:

 

         ID Ime          Prezime              Cnt

———– ———— ———— ———–

          1 Dusko        Radovic                2

          2 Simo         Esic                   2

          3 Zuko         Dzumhur                2

 

(3 row(s) affected)

 

Uocimo kako je COUNT(*) uvek 2 ako imamo uniju dve identicne tabele. Ako tabele nisu identicne, COUNT(*) nece biti jednak 2. Redovi koji nisu identicni imace COUNT(*)=1.

 

Evo ponovo test podataka kojim smo testirali kveri sa pocetka clanka.

 

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

;

CREATE TABLE #Original (ID int , Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Original VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Original VALUES (99,‘Simo’,‘Esic’)

INSERT INTO #Original VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Original VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Original VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Original VALUES (6,‘Mesa’,‘Selimovic’)

;

IF Object_ID(‘tempdb..#Kopija’) IS NOT NULL DROP TABLE #Kopija

;

CREATE TABLE #Kopija (ID int , Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Kopija VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Kopija VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Kopija VALUES (3,‘Zzzzzzuko’,‘Dzumhur’)

INSERT INTO #Kopija VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Kopija VALUES (55,‘Branko’,‘Copic’)

INSERT INTO #Kopija VALUES (6,‘Mesa’,NULL)

;

 

Test podaci:

 

                  ID Ime          Prezime

——– ———– ———— ————

Original           1 Dusko        Radovic

Original          99 Simo         Esic

Original           3 Zuko         Dzumhur

Original           4 Momo         Kapor

Original           5 Branko       Copic

Original           6 Mesa         Selimovic

 

(6 row(s) affected)

 

                ID Ime          Prezime

—— ———– ———— ————

Kopija           1 Dusko        Radovic

Kopija           2 Simo         Esic

Kopija           3 Zzzzzzuko    Dzumhur

Kopija           4 Momo         Kapor

Kopija          55 Branko       Copic

Kopija           6 Mesa         NULL

 

(6 row(s) affected)

 

Golim okom vidimo da se gotovo svi redovi razlikuju.

 

Da vidimo koliko se puta pojavljuju identicni redovi:

 

SELECT ID, Ime, Prezime, COUNT(*) AS Cnt

FROM

(

SELECT * FROM #Original

UNION ALL

SELECT * FROM #Kopija

) AS X

GROUP BY ID, Ime, prezime

;

 

         ID Ime          Prezime              Cnt

———– ———— ———— ———–

          1 Dusko        Radovic                2

          2 Simo         Esic                   1

          3 Zuko         Dzumhur                1

          3 Zzzzzzuko    Dzumhur                1

          4 Momo         Kapor                  2

          5 Branko       Copic                  1

          6 Mesa         NULL                   1

          6 Mesa         Selimovic              1

         55 Branko       Copic                  1

         99 Simo         Esic                   1

 

(10 row(s) affected)

 

Redovi za Duska radovica i Momu Kapora imajupo dve pojave – oni su dakle identicni. Svi ostali redovi nisu identicni. Proizilazi da kveri koji prikazuje redove koji narusavaju idnticnost tabela izgleda ovako:

 

SELECT ID, Ime, Prezime, COUNT(*) AS Cnt

FROM

(

SELECT * FROM #Original

UNION ALL

SELECT * FROM #Kopija

) AS X

GROUP BY ID, Ime, prezime

HAVING COUNT(*) <> 2

;

Rezultat je isti koji smo dobili kverijem sa pocetka clanka:

 

         ID Ime          Prezime              Cnt

———– ———— ———— ———–

          2 Simo         Esic                   1

          3 Zuko         Dzumhur                1

          3 Zzzzzzuko    Dzumhur                1

          5 Branko       Copic                  1

          6 Mesa         NULL                   1

          6 Mesa         Selimovic              1

         55 Branko       Copic                  1

         99 Simo         Esic                   1

 

(8 row(s) affected)

 

Rezultat smo dobili pomocu mnogo jednostavnijeg kverija.

Sta nedostaje? Nista nam ne kaze koji red u rezultatu dolazi iz koje tabele. Ako hocemo da tucemo kveri sa pocetka clanka, treba i to da dodamo nekako. Evo jedan nacin:

 

SELECT ID, Ime, Prezime, COUNT(*) AS Cnt, StaJeOvo = MIN(Source)

FROM

(

SELECT * , Source = ‘#Original’ FROM #Original

UNION ALL

SELECT * , Source = ‘#Kopija’  FROM #Kopija

) AS X

GROUP BY ID, Ime, prezime

HAVING COUNT(*) <> 2

;

 

         ID Ime          Prezime              Cnt StaJeOvo

———– ———— ———— ———– ———

          2 Simo         Esic                   1 #Kopija

          3 Zuko         Dzumhur                1 #Original

          3 Zzzzzzuko    Dzumhur                1 #Kopija

          5 Branko       Copic                  1 #Original

          6 Mesa         NULL                   1 #Kopija

          6 Mesa         Selimovic              1 #Original

         55 Branko       Copic                  1 #Kopija

         99 Simo         Esic                   1 #Original

 

(8 row(s) affected)

 

Sami mozete da dodate sortiranje i da rezultat ucinite jso citljivijim.

 

Nedostatak ovog resenja je sto se moraju kucati nazivi kolona u SELECT i GROUP BY listama. Za tabele sa desetinama i stotinama kolona to moze biti problem, ali se stim vec moze ziveti – nedostatak nije kritican.

 

Resenje sa razlikom skupova

 

Ako tabele #Original i #Kopija posmatramo kao skupove ciji su elementi redovi, na njih mozemo primeiti operacije za rad nad skupovima. MS SQL ima operaciju EXCEPT koja daje razliku skupova (A bez B, A\B). verujem da ostali sistemi imaju ekvivalentne operacije za razliku skupova. Ako nema takve operacije – ovo sto sledi ostaje resenje za MS SQL server.

 

Razlika izmedju nasa dva skupa jeste “Redovi iz jedne tabele kojih nema u drugoj”. Kako u skupovima generalno nija A\B = B\A, to nam trebaju razlike sa obe starne. Pisanje je zaista jednostavno:

 

Sta ima u originalu a nema u kopiji:

 

SELECT ID, Ime, Prezime FROM #Original

EXCEPT

SELECT ID, Ime, Prezime FROM #Kopija

;

         ID Ime          Prezime

———– ———— ————

          3 Zuko         Dzumhur

          5 Branko       Copic

          6 Mesa         Selimovic

         99 Simo         Esic

 

(4 row(s) affected)

 

Sta ima u kopiji a nema u originalu:

 

SELECT ID, Ime, Prezime FROM #Kopija

EXCEPT

SELECT ID, Ime, Prezime FROM #Original

;

         ID Ime          Prezime

———– ———— ————

          2 Simo         Esic

          3 Zzzzzzuko    Dzumhur

          6 Mesa         NULL

         55 Branko       Copic

 

(4 row(s) affected)

 

Primetite da smo naveli tacna imena kolona. Nismo morali, SELECT * FROM  radi bez problema, ako su sve kolone sa istim imenima, u istom redosledu i istog tipa.

 

Kveri  koji obejdinjuje sve razlike moze se napistai ovako:

 

 

SELECT * FROM

(

      (

      SELECT * FROM #Original

      EXCEPT

      SELECT * FROM #Kopija

      )

      UNION

      (

      SELECT * FROM #Kopija

      EXCEPT

      SELECT * FROM #Original

      )

) AS X

;

 

Rezultat ce biti tacan:

 

         ID Ime          Prezime

———– ———— ————

          2 Simo         Esic

          3 Zuko         Dzumhur

          3 Zzzzzzuko    Dzumhur

          5 Branko       Copic

          6 Mesa         NULL

          6 Mesa         Selimovic

         55 Branko       Copic

         99 Simo         Esic

 

(8 row(s) affected)

 

Lepota poslednjeg kverija je u tome sto ne morate kucati nazive kolona. Resenje sa UNION ALL i GROUP BY trazi da se navedu sve kolone, bas kao i originalno resenje sa JOINom..

 

Primetite da su #Kopija i #Original nazivi temp tabela, iza njih moze biti bilo sta, bilo koje proizvoljne dve tabele. To znaci da mozemo napisati sablon za poredjenje bilo koje dve tabele, koje

    Imaju istu strukturu (broj kolone, tip, redosled kolona, nije obavezno da imena kolona budu ista(!), iako je zgodno i pozeljno

    Imaju kolonu ili skup kolona koja se ponasju kao PK (nama NULL, name duplikata)

 

Sablon bi izgledao ovako:

 

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

;

IF Object_ID(‘tempdb..#Kopijal’) IS NOT NULL DROP TABLE #Kopija

;

SELECT INTO #Original FROM <vasa prva tabela>

;

SELECT INTO #Kopija FROM <vasa druga tabela>

;

/* Redovi koji narusavaju identicnost tabela */

SELECT * FROM

(

      (

      SELECT * FROM #Original

      EXCEPT

      SELECT * FROM #Kopija

      )

      UNION ALL

      (

      SELECT * FROM #Kopija

      EXCEPT

      SELECT * FROM #Original

      )

) AS X

;

 

Ako imate posla sa tabelama koje zadovoljavaju navedene uslove, sve sto treba da uradite jeste da zamenite vrednosti u <vasa prva tabela> i <vasa druga tabela>.

 

Za sada, nedostatak metode je sto vam ne kaze koji red rezultata dolazi iz koje tabele. Monstrum kveri sa pocetka je to lepo prikazivao. Zsto ne bi moglo i ovde? NAravno d amoze, ali se stvari komplikuju za nijansu.

 

/* Redovi koji narusavaju identicnost tabela, prosireno */

SELECT * FROM

(

      SELECT StajeOvo = ‘Orignal bez kopije’, * FROM

      (

      SELECT * FROM #Original

      EXCEPT

      SELECT * FROM #Kopija

      ) AS O

 

      UNION ALL

     

      SELECT StaJeOvo = ‘Kopija bez originala’, * FROM

      (

      SELECT * FROM #Kopija

      EXCEPT

      SELECT * FROM #Original

      ) AS K

) AS X

;

 

Rezultat:

 

StajeOvo                      ID Ime          Prezime

——————– ———– ———— ————

Orignal bez kopije             3 Zuko         Dzumhur

Orignal bez kopije             5 Branko       Copic

Orignal bez kopije             6 Mesa         Selimovic

Orignal bez kopije            99 Simo         Esic

Kopija bez originala           2 Simo         Esic

Kopija bez originala           3 Zzzzzzuko    Dzumhur

Kopija bez originala           6 Mesa         NULL

Kopija bez originala          55 Branko       Copic

 

(8 row(s) affected)

 

I posle komplikacije, ovo resenje i dalje ostaje sablon, pa mu se upotrebljivost nicim ne umanjuje. I dalje je sve sto treba da uradite da zamenite na pocetku vrednosti u <vasa prva tabela> i <vasa druga tabela>.

 

Prednost ovog nacina nad originalnim JOIN kverijam i resenjem sa UNION-GROUP BY je sto ne moramo da kucamo nazive kolona. To moze biti znacajno ako imamo desetine ili stotine kolona u tabelama. Znacajno, ali ne i presudno.

 

Ne zaboravite da sve ovo vazi ako nemate duplikata u tabelama koje poredite. Otuda zahtev da imate kolonu ili skup kolona koje imaju osobine primarnog kljuca.

 

Namera mi je da u sledecem nastavku (koji ce verovatno stici tek sredinom Septembra) pokazemo kako se tri ponudjena resenja ponasaju sa duplikatima. Zavisno od toga kako su duplikati rasporedjeni, mozete dobiti tacno, netacno ili delimicno tacno resenje. O tome, kako i o mogucem resenju kada imamo duplikate, za dve –tri nedelje.

 

J


Poredjenje Tabela

Tuesday, 31.08.2010 – Zidar

Poredjenje Tabela

 

Cesto se u praksi javlja zadatak poredjenja tabela. Date su dve tabele, istih struktura, istog broja redova. Takve dve table bice jednake ako su im svi odgovarajuci redovi jednaki. Dva reda su jednaka ako su im vrednsoti u odgovarjucim kolonama jednake.

 

Primer dve jednake tabele:

 

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

;

CREATE TABLE #Original (ID int, Ime varchar(12), Prezime varchar(12))

;

IF Object_ID(‘tempdb..#Kopija’) IS NOT NULL DROP TABLE #Kopija

;

CREATE TABLE #Kopija (ID int, Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Original VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Original VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Original VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Original VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Original VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Original VALUES (6,‘Mesa’,‘Selimovic’)

;

INSERT INTO #Kopija VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Kopija VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Kopija VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Kopija VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Kopija VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Kopija VALUES (6,‘Mesa’,‘Selimovic’)

;

Za tabele u primeru znamo da su jednake jer smo ih tako napravili. Kako dokazati da su tabele jednake? Posto smo mi SQL majstori, SQL, pokusacemo da napisemo SQL kverije koji ce dokazati jednakost datih tabela.

 

Prvo sto nam prirodno pada na pamet je nesto ovako:

 

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE O.Ime <> K.Ime

OR O.prezime <> K.prezime

 

(0 row(s) affected)

 

Sve deluje lepo. Da vidimo da li kveri radi i kad imamo razlike. Napravimo razliku u redu sa ID = 1, Dusko Radvic neka postane Dusko Popovic.

 

 

UPDATE #Kopija SET Prezime = ‘Popovic’ WHERE ID = 1

;

Kada izvrsimo kveri, dobijemo naravno tacan rezultat:

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

          1 Dusko        Radovic                1 Dusko        Popovic

 

(1 row(s) affected)

 

 

Uticaj NULL vrednsoti

Hajde sada da za ID = 2 stavimo da je Prezime = NULL

 

UPDATE #Kopija SET Prezime = NULL WHERE ID = 2

;

SELECT * FROM #Kopija

;

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Popovic

          2 Simo         NULL

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

Sada naravno ocekujemo da kveri vrati dva reda.Medjutim, dobijamo i dalje samo jedan red:

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

          1 Dusko        Radovic                1 Dusko        Popovic

 

(1 row(s) affected)

 

U cemu je problem? Zasto se ne vidi red sa ID =2 gde jeIme = NULL? Nas kveri pokusava da uporedi NULL vrednost sa necim sto nije NULL. NULL nije jednako nicemu, niti je NULL jednako nekom drugom NULL. Zato kveri ne radi dobro kad imamo NULL vrednosti u nekoj od tabela. Uradimo ovo;

 

UPDATE #Original SET Prezime = ‘Simo’, Ime = NULL WHERE ID = 2

UPDATE #Kopija SET Prezime = NULL, Ime = ‘Esic’ WHERE ID = 2

;

SELECT * FROM #Kopija

;

SELECT * FROM #Original

;

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Popovic

          2 Esic         NULL

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          2 NULL         Simo

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

Redovi za ID =1 i ID=2 se ocigledno razlikuju. Ipak, kveri vraca samo jedan red koji nije identican u dve date tabele. Da eliminisemo probleme sa NULL vrednostima, mozemo da kveri napisemo ovako:

 

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

Dobijamo tacan rezultat:

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

          1 Dusko        Radovic                1 Dusko        Popovic

          2 NULL         Simo                   2 Esic         NULL

 

(2 row(s) affected)

 

Kveri deluje jednostavno, cak is a COALESCE. Sta ce se desiti kad budemo imali veoma mnogo kolona? WHERE uslov postaje glomazan, a i izlaz nece biti bas lep, bice mnogo kolona. Bilo bi najlepse kad ne bismo morali da pisemo sve kolone….Pokazacemo resenje i za to, nesto kasnije. Sada cemo da ubacimo jos gresaka u tabele, da proverimo kako ce se ponasati kveri.

 

NULL u JOIN koloni

Napravimo tabele tako da ID nema osobine primarnog kljuca.Neka imamo NULL u koloni ID (po kojoj vrsimo JOIN)

 

IF Object_ID(‘tempdb..#Original’) IS NOT NULL DROP TABLE #Original

;

CREATE TABLE #Original (ID int , Ime varchar(12), Prezime varchar(12))

;

IF Object_ID(‘tempdb..#Kopija’) IS NOT NULL DROP TABLE #Kopija

;

CREATE TABLE #Kopija (ID int , Ime varchar(12), Prezime varchar(12))

;

INSERT INTO #Original VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Original VALUES (NULL,‘Simo’,‘Esic’)

INSERT INTO #Original VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Original VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Original VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Original VALUES (6,‘Mesa’,‘Selimovic’)

 

;

INSERT INTO #Kopija VALUES (1,‘Dusko’,‘Radovic’)

INSERT INTO #Kopija VALUES (2,‘Simo’,‘Esic’)

INSERT INTO #Kopija VALUES (3,‘Zuko’,‘Dzumhur’)

INSERT INTO #Kopija VALUES (4,‘Momo’,‘Kapor’)

INSERT INTO #Kopija VALUES (5,‘Branko’,‘Copic’)

INSERT INTO #Kopija VALUES (6,‘Mesa’,‘Selimovic’)

;

Sve je isto, osim sto imamo NULL umesto ID = 2 u tabeli #Original. Kveri kojije lepo radio za NULL vrednosti u non-join kolonama bio je ovaj

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

Ponovo dobijamo netacan rezultat:

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

 

(0 row(s) affected)

 

Neka umesto NULL imamo neku vrednost, ali razlicitu od druge tabele:

 

UPDATE #Original SET ID = 99 WHERE Ime = ‘Simo’

 

Tabele izgledaju sada ovako:

 

SELECT * FROM #Kopija

;

SELECT * FROM #Original

;

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          2 Simo         Esic

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

         99 Simo         Esic

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

Red u kome je ‘Simo’,’Esic’ ocigledno se razlikuje u dve tabele, ID nije isti. Da li ce nas kveri to pokazati? Ponovo, ako izvrsimo

 

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

ne dobijamo ni jedan red:

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

 

(0 row(s) affected)

 

Postoji jos mogucnosti da stvari krenu naopako. Neka JOIN kolona nema NULL vrednosti, neka nema razlika, ali neka imamo duplikat.

 

UPDATE #Original SET ID = 5 WHERE Ime = ‘Simo’

 

SELECT * FROM #Kopija

;

SELECT * FROM #Original

;

Sada imamo

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          2 Simo         Esic

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          5 Simo         Esic

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

U donjoj tabeli, i Zuko i Branko imaju ID = 5. Izvrsimo ponovo kveri

 

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

Ovog puta dobili smo rezulat:

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

          5 Simo         Esic                   5 Branko       Copic

 

(1 row(s) affected)

 

Nije bas odmah jasno sta u stvari rezultat pokazuje, ali bar vidimo da negde imamo problem, pa cemo vec istrazivati i verovatno nesto zakljuciti. Znaci, nas kveri ne propusta duplikate, barem tako za sada izgleda.

 

Vidimo da naivno napisan kveri moze da vrati tacan ili pogresan rezultat, ili delimicno tacan, zavisno od toga kakvi su podaci. Dobar kveri ne sme da se ponasa tako. Opisane situacije mogu se javiti lako u praksi. Ako su tabele velike i ne mogu se golim okom proveriti, mozemo biti u grdnoj nevolji ako napisemo naivan kveri.

 

Zasto je predlozeni kvari naivan i ne radi? Zato sto smo precutno i nesvsno ucinili pogresnu prtpostavku na pocetku. Ponasali smo se kao da je kolona ID primarni kljuc. Da jeste, ne bismo imali problem sa duplikatom i NULL vrednostima. Medjutim, vrednosti ne moraju da su iste za PK u obe kolone. Pogotovo ako je PK neki autonumber ili identity, neki broj koji sistem sam generise. Ako dokazemo na pocetku da ID u obe tabele ima svojstva primarnog kljuce (nema NULL i nema duplikata), mogli bi da razbijemo nas naivan kveri na tri. Prvo bismo pokazali redove koji se nalaze u jednoj tabeli a nema ih u drugoj, a onda bismo pokazali redove koji se nalaze u obe tabele, ali su razliciti.

 

Podesimo prvo podatke

 

UPDATE #Original SET ID = 5 WHERE Ime = ‘Simo’

 

UPDATE #Original SET ID = 99 WHERE Ime = ‘Simo’

;

UPDATE #Kopija SET ID = 55 WHERE Ime = ‘Branko’

;

UPDATE #Kopija SET Ime = ‘Zzzzuko’ WHERE ID = 3

;

Tabele sada izgledaju ovako:

 

SELECT * FROM #Kopija

;

SELECT * FROM #Original

;

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

          2 Simo         Esic

          3 Zzzzuko      Dzumhur

          4 Momo         Kapor

         55 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

         ID Ime          Prezime

———– ———— ————

          1 Dusko        Radovic

         99 Simo         Esic

          3 Zuko         Dzumhur

          4 Momo         Kapor

          5 Branko       Copic

          6 Mesa         Selimovic

 

(6 row(s) affected)

 

Razlike su ove:

    u #Kopija ‘Branko’,’Copic’ ima ID = 55

    u #Original ‘Simo’,’Esic’ ima ID = 99.

    U #Original umesto ‘Zuko’ pise ‘ZZZuko’ za red sa ID = 3

 

Sve ostalo je isto u obe tabele. Duplikata u ID nema, nema ni NULL vrednosti u ID.

 

Pokazimo prvo deo gde su razlike u ID:

 

— Sta ima u #Original a nema u #Kopija

SELECT

O.*

FROM #Original AS O

LEFT JOIN #Kopija AS K ON O.ID = K.ID

WHERE K.ID IS NULL

;

         ID Ime          Prezime

———– ———— ————

         99 Simo         Esic

          5 Branko       Copic

 

(2 row(s) affected)

 

— Sta ima u #Kopija a nema u #Original

SELECT

K.*

FROM #Original AS O

RIGHT JOIN #Kopija AS K ON O.ID = K.ID

WHERE O.ID IS NULL

;

 

         ID Ime          Prezime

———– ———— ————

          2 Simo         Esic

         55 Branko       Copic

 

(2 row(s) affected)

 

Nista lakse, LEFT JOIN, pa RIGHT JOIN, milina jedna 🙂

 

Razlike za one redove gde ID postoji u obe tabele:

 

SELECT

*

FROM #Original AS O

JOIN #Kopija AS K ON O.ID = K.ID

WHERE COALESCE(O.Ime,‘Ovde je NULL’) <> COALESCE(K.Ime,‘Ovde je NULL’)

OR COALESCE(O.prezime, ‘Ovde je NULL’) <> COALESCE(K.prezime, ‘Ovde je NULL’)

;

 

         ID Ime          Prezime               ID Ime          Prezime

———– ———— ———— ———– ———— ————

          3 Zuko         Dzumhur                3 Zzzzuko      Dzumhur

 

(1 row(s) affected)

 

Lepo, ali nije najzgodnije za prikazivanje. Imamo tri kverija, od kojih treci ima duplo vise kolona nego prva dva. Ko ce se tu snaci, sta ne valja i gde?

 

I to sve pod uslovom da je ID ili jedinstven i NOT NULL. U realnom zivotu to ne mozemo da garantujemo uvek. Za potrebe primera smo napravili takve tabele, ID je kao PK, ali to nece biti uvek slucaj.

 

Znaci, nasa strategija sa naivno napisanim kverijem se polako raspada. Treba nam nesto bolje. Sad znamo uslove to ‘nesto bolje’:

    da resenje nije osetljovo na NULL vrednosti u bilo kojoj

    da nije osteljivo na promene u bilo kojoj koloni (JOIN ili ne JOIN, svejedno)

    da resenje nije osetljivo na duplikate

Da resenje „nije osetljivo na neki slucaj“ treba citati „da resenje ne promasuje posmatrane slucajeve“

 

U sledecem nastavku poci cemo drugim putem, pa dokle stignemo.

 

J


Konekcija na bazu bez lozinke/šifre [How to connect to Oracle database without password]

Monday, 07.06.2010 – Dejan

A sada još jedna mala tajna iz kuhinje velikog majstora – spajanje na Oracle bazu bez zadavanja šifre iliti lozinke (u daljnjem tekstu – password 🙂 ).

Vjerujem da ste svi kad-tad imali potrebu da pokrenete neki batch job, zbog čega ste u toj batch datoteci morali koristiti password u plaintext formatu, pri čemu ste se brinuli da vam neko ne vidi password i spoji se na bazu sa lošim namjerama…

Ili vas muči što svaki programer mora znati password, da bi pristupio bazi?

Vjerovatno mislite kako je nemoguće spojiti se na bazu bez navođenja passworda pri spajanju na bazu?

Ta-daaaam! E pa moguće je!

Rješenje leži u Oracle Walletu.

Administrator Oracle baze mora za svakog korisnika kreirati Oracle Wallet i u njemu sačuvati korisničko ime i njegov password. Uz taj Wallet, na korisničkom kompjuteru se moraju još podesiti datoteke sqlnet.ora i tnsnames.ora, nakon čega taj korisnik može pristupiti bazi bez ukucavanja passworda – čak štaviše, korisnik ne mora niti znati password, da bi se spojio na bazu. Dakle, password je poznat samo administratoru Oracle baze, tako da nijedan drugi korisnik ili programer nema potrebu za passwordom.

Pogledajmo kako to izgleda na jednom primjeru…

Kreiranje Oracle Walleta

Recimo da imamo slijedeće okruženje:
– postoje 3 korisnika/programera, koji bazi pristupaju preko PL/SQL Developera, SQL*Loadera, DataPump-a ili neke druge korisničke aplikacije
– svaki korisnik ima instaliran Oracle Client na svom kompjuteru
– lokalni ORACLE_HOME za Client je C:\oracle\product\10.2.0\client

Za svakog korisnika se mora kreirati pojedinačni Oracle wallet.

cd \
mkdir wallets
cd wallets
mkdir korisnik1 korisnik2 korisnik3
REM kreiranje Walleta (unesite neki password za Wallet i potvrdite ga jos jednom)
mkstore -wrl C:\wallets\korisnik1 -create
REM korisnik1 je naziv DB Usera, a password1 je password od tog DB Usera:
mkstore -wrl C:\wallets\korisnik1 -createCredential TNSstring korisnik1 password1
mkstore -wrl C:\wallets\korisnik2 -create
mkstore -wrl C:\wallets\korisnik2 -createCredential TNSstring korisnik2 password2
mkstore -wrl C:\wallets\korisnik3 -create
mkstore -wrl C:\wallets\korisnik3 -createCredential TNSstring korisnik3 password3

– pri čemu je TNSstring zapravo connection string za bazu u datoteci tnsnames.ora, npr:

RAC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.150)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.151)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = rac)
)
)

Nakon toga je potrebno kopirati tnsnames.ora i sqlnet.ora u pripadajuće direktorije:

copy %ORACLE_HOME%\network\admin\tnsnames.ora C:\wallets\korisnik1
copy %ORACLE_HOME%\network\admin\tnsnames.ora C:\wallets\korisnik2
copy %ORACLE_HOME%\network\admin\tnsnames.ora C:\wallets\korisnik3
copy %ORACLE_HOME%\network\admin\sqlnet.ora C:\wallets\korisnik1

Otvorite datoteku C:\wallets\korisnik1\sqlnet.ora i dodajte slijedeće podatke za Oracle Wallet:

WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = C:\wallets\korisnik1)
)
)

SQLNET.WALLET_OVERRIDE = TRUE

Snimite izmjene u toj datoteci i onda ju kopirajte za preostale korisnike:

copy C:\wallets\korisnik1\sqlnet.ora C:\wallets\korisnik2
copy C:\wallets\korisnik1\sqlnet.ora C:\wallets\korisnik3

Otvorite sqlnet.ora datoteke u tim direktorijima i podesite putanju za WALLET_LOCATION:

...
(DIRECTORY = C:\wallets\korisnik2)
...

i

...
(DIRECTORY = C:\wallets\korisnik3)
...

Korištenje Oracle Walleta – spajanje na bazu bez passworda

Za svakog korisnika i za svaku aplikaciju kreirajmo npr. na Desktopu potrebne .bat datoteke sa slijedećim sadržajem:

set ORACLE_HOME=C:\oracle\product\10.2.0\client
set TNS_ADMIN=C:\wallets\korisnik1
C:\putanja\do\vase\aplikacije\aplikacija.exe userid=/@TNSstring

Tako npr. možete pokrenuti DataPump Export/Import bez unošenja plaintext passworda u neku batch datoteku ili pokrenuti SQL*Loader, TOAD, PL/SQL Developer i td., a da biste vidjeli kako to izgleda u praksi, navešću par primjera.

1. Ovako bi npr. izgledala .bat datoteka za korisnika korisnik1, ukoliko želi pokrenuti SQL*Loader bez unošenja passworda:

set ORACLE_HOME=C:\oracle\product\10.2.0\client
set TNS_ADMIN=C:\wallets\korisnik1
sqlldr userid=/@RAC keyword=value keyword=value keyword=value ...

U ovom slučaju korisnik1 ne mora uopšte znati password da bi se putem SQL*Loadera spojio na bazu i obavio import podataka. Jednostavno klikne na .bat datoteku i gotovo.

2. Ovako bi npr. izgledala .bat datoteka za korisnika2, ukoliko želi pokrenuti DataPump Export/Import:

set ORACLE_HOME=C:\oracle\product\10.2.0\client
set TNS_ADMIN=C:\wallets\korisnik2
set NLS_LANG=AMERICAN_AMERICA.AL32UTF8
expdp userid=/@RAC dumpfile=TEST:korisnik2.dmp schemas=korisnik2 logfile=TEST:korisnik2.log status=60 job_name=exp_korisnik2

Napomena: korisnik2 mora imati sistemske privilegije EXPORT FULL DATABASE i IMPORT FULL DATABASE, da bi mogao koristiti sve opcije DataPumpa!

3. Ovako bi npr. izgledala .bat datoteka, ukoliko se programer želi putem TOAD-a ili PL/SQL Developera spojiti na bazu pod korisničkim imenom korisnik3, bez da mora znati password:

set ORACLE_HOME=C:\oracle\product\10.2.0\client
set TNS_ADMIN=C:\wallets\korisnik3
cd "C:\Program Files (x86)\Quest Software\Toad for Oracle"
start /MAX toad.exe -max -c /@RAC
REM a za PLSQL Developer morate promijeniti putanju i plsqldev.exe pozvati ovako:
REM start /MAX plsqldev.exe nosplash userid=/@RAC

To bi bilo to. Jest’ da ćete imati hrpu .bat datoteka na Desktopu, ali vjerujte mi da ćete biti mirniji, sigurniji i efikasniji u radu, kada ne morate stalno ukucavati password…


Ponuda za posao: Oracle DBA

Thursday, 27.05.2010 – Dejan

Pošto ne stižem obavljati sve zadane obaveze na poslu (zbog čega ne stignem više ni pisati nešto aktivno na blogu), potrebna mi je za jedan projekt pomoć jednog iskusnog Oracle DBA na ODREĐENO vrijeme (6 do 12 mjeseci).

Firma: Erste Asset Management GmbH (u 100% vlasništvu Erste banke Austrija)
Lokacija: Beč, Austrija
Vrsta zaposlenja: vanjski saradnik na određeno vrijeme (6 do 12 mjeseci)
Projekt: Migracija Oracle RAC baze sa Windows na IBM AIX platformu & Source Code review

Traži se:
– višegodišnje iskustvo u radu sa Oracle bazama (prvenstveno Oracle 10g Release 2)
– iskustvo sa IBM AIX platformom
– poželjno napredno poznavanje SQL-a i PL/SQL-a
– poželjno poznavanje njemačkog jezika
– poželjno iskustvo u radu na sličnim projektima
– prednost imaju oni sa OCP sertifikatom i radnim iskustvom
– diploma nekog fakulteta ne igra nikakvu ulogu pri donošenju odluke o najboljem kandidatu

Nudi se:
– rad na zanimljivom i kompleksnom projektu
– fleksibilno radno vrijeme
– rad u profesionalnom timu
– 50-70 EUR po satu (zavisno od kvalifikacija i iskustva)

Zainteresovani kandidati moraju imati radnu vizu za EU.

Vaš CV pošaljite na adresu dejan.topalovic AT sparinvest.com sa naznakom “Ponuda za posao: Oracle DBA”.

Samo oni kandidati, koji uđu u uži izbor, biće obavješteni i pozvani na razgovor.

Ponuda važi do 30.06.2010., a ukoliko se do tada ne pronađe idealan kandidat, onda ćemo staviti oglas na job-portale.

Update (30.06.2010): Idealan kandidat nažalost nije pronađen, tako da ćemo kandidate morati tražiti preko job portala… Preko ovog bloga sam dobio 4 prijave, od kojih su dvije bile nepotpune (bez CV-a i napisane “neozbiljno”), a osim toga nijedan kandidat nema radnu vizu za EU… Po kvalifikacijama bi jedino jedan kandidat mogao biti primljen, ali glavni IT menadžer trenutno nema vremena da se bakće oko ganjanja radne vize za njega…

PS: Svako malo nam treba novih ljudi (Oracle PL/SQL developeri, kao i J2EE/JSF developeri), pa ukoliko neko ima interesa nek mi pošalje svoj CV, kako bih ga imao u vidu glede budućih otvorenih pozicija.


Dozvola za ubijanje (sesija)

Thursday, 11.03.2010 – Dejan

Ne prođe skoro nijedan dan, a da me barem jedan programer ne gnjavi da mu ubijem zablokiranu sesiju. Pošto nemam baš vremena da se cimam i oko toga, odlučio sam da svakom programeru dozvolim ubijanje vlastitih sesija.

Takođe ne volim otkrivati toplu vodu, pa sam za ovaj problem malo proguglao i našao sasvim zadovoljavajuće rješenje od Toma Kyte-a, a ono izgleda ovako:

1. svakom programeru dodijeliti privilegiju, da može selektovati potrebne podatke iz v_$session (sid, serial#):

grant select on v_$session to programer;

2. Ako već nemate nekog “poweruser” korisnika (“non-SYS user with a DBA role“), onda kreirajte jednog, pa s tim korisničkim nalogom kreirajte jednu proceduru, koja će ubijati željenu sesiju:

create or replace procedure poweruser.kill_session( p_sid     in number,
                                                    p_serial# in number)
  is
      ignore          pls_integer;
  BEGIN
      select count(*) into ignore
        from V$session
       where username = USER
         and sid = p_sid
         and serial# = p_serial#;

      if ( ignore = 1 )
      then
          execute immediate '
              alter system kill session ''' ||
              to_char(p_sid,'999999')||','||
              to_char(p_serial#,'999999')||'''';
      else
          raise_application_error( -20001,
                                 'You do not own session ''' ||
                                  p_sid || ',' || p_serial# ||
                                 '''' );
      end if;
  END;
  /

3. dozvolite izvršavanje te procedure svim programerima:

grant execute on kill_session to programer;

To je to – nema više svakodnevnog cimanja u vezi ubijanja sesija.


Sertifikati + praksa + redovno usavršavanje = bolji posao

Friday, 05.03.2010 – Dejan

Ko kaže da se pored prakse sertifikati i usavršavanje u kontinuitetu ne isplate?

Meni su se već u prošlosti isplatili, a sad evo opet. Naime, kao što sam već par puta napominjao, dobio sam par zanimljivih ponuda za posao, pa sam odabrao jednu, koja mi jamči odgovorniju, zanimljiviju i bolje plaćenu poziciju, tzv. “do penzije ovako – gdje da potpišem”. 🙂

Ostajem u sklopu Erste banke, ali prelazim u drugu kćerku-firmu pod nazivom “Erste Asset Management”, koja se bavi finansijskim menadžmentom, odnosno upravljanjem uloženog kapitala privatnih i pravnih lica – ukratko fondovi, akcije i sve ostalo što ide uz berzu.

Biću glavni i odgovorni za administraciju Oracle baza i za koordinaciju development tima, uključujući pisanje tehničke projektne specifikacije i obučavanje programera.

Osim dobre finansijske ponude, odobren mi je i budžet za daljnje usavršavanje i sticanje sertifikata, jer sam se pokazao dobrim i nesebičnim u prenošenju novostečenog znanja (iz prakse, sa Oracle kurseva i iz stručne literature) manje iskusnim kolegama.

Ukratko – finansijsko i vremensko ulaganje u usavršavanje svog znanja se nadasve isplati!

Nažalost, nova pozicija će mi oduzimati i mnogo vremena, tako da neću moći aktivno pisati na blogu (eh, kao da sam i do sada pisao nešto pretjerano aktivno 😉 ), ali gledaću da s vremena na vrijeme ubacim neki koristan tekst.

A sad u nove radne pobjede!