Oracle 11g za Windows

October 24, 2007 – Dejan

“Dugo” očekivana verzija 11g za Windows je postala dostupna.

- Službena ovavijest i link za download -

Sad ću da skinem i ovu verziju, pa da se malo poigram. :D Nadam se da će mi kućni “server” podnijeti ovu novu verziju…


Backup Oracle baze pomoću RMAN-a

October 23, 2007 – Dejan

Jedan od obaveznih zadataka svakog administratora Oracle baze je pravljenje sigurnosne kopije, odnosno backup Oracle baze. Ja ću vam u primjeru “korak po korak” objasniti kako se RMAN podešava i koristi za backup Oracle baze, a za detaljnije definicije šta je šta, pročitajte službenu Oracle dokumentaciju(Oracle® Database Backup and Recovery Advanced User’s Guide).

Za ovaj recept nam nisu potrebni ni limun, niti peršun, tako da možemo slobodno da ih bačimo.

Za backup Oracle baze pomoću RMAN-a trebaju nam ovi sastojci:
- 2 Oracle baze
- 1 RMAN
- 1 administrator Oracle baza
- 2 piva
- 1 film ili epizoda omiljene serije za ubijanje dosade dok traje backup

Pročitaj kompletan tekst »


DUAL vs. FAST DUAL (_fast_dual_enabled)

October 17, 2007 – Dejan

Ukoliko u izvornom kôdu često koristite DUAL tabelu, npr.  “SELECT sysdate FROM dual”, interne funkcije USER, USERENV, SYS_CONTEXT ili pseudokolone (ROWID, LEVEL i td.), onda pogledajte, da li je podešen parametar “_fast_dual_enabled” i da li je postavljen na “true”, jer u verziji 10g Oracle koristi poboljšani “access path” za operacije, koje uključuju DUAL tabelu i za svaku tu operaciju štedi 3 logička I/O upita.

Dokaz:

SQL> select sysdate from dual;

Execution Plan
--------------------------------------------------------- 

0    SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1)
1  0  FAST DUAL (Cost=2 Card=1) 

Statistics 

---------------------------------------------------------
0 consistent gets 

SQL> alter session set "_fast_dual_enabled"=false; 

SQL> select sysdate from dual; 

Execution Plan 

---------------------------------------------------------

0    SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1)

1  0  TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1) 

Statistics 

----------------------------------------------------------

3 consistent gets

Postavite taj parametar na TRUE i uživajte.


Spajanje podataka po zajednickom atributu

October 16, 2007 – Srdjan

Miša, jedan moj kolega s posla, je juče naišao na problem prilikom pravljenja nekog izveštaja. Za potrebe tog izveštaja mora da prikupi podatke iz četiri različita izvora, a onda da ih objedini u jedinstven izveštaj.

Miša je napravio strukturu od četiri tabele, i u svaku od tabela je importovao podatke iz po jednog izvora. Svi prikupljeni podaci se odnose na odnose sa poslovnim partnerima (bilo da se radi o kupcima ili dobavljačima). Ono što je zajedničko svim podacima je da svi izvori koriste zajednički način ‘šifriranja’ partnera.

Pošto nemaju svi izvori odnose sa svim partnerima, ni jedan izvor nema kompletnu listu partnera. Problem je nastao kako se od četiri nepotpune liste partnera može napraviti jedna jedinstvena lista. Po dobijanju jedinstvene liste partnera ostaje rutinski posao spajanja tabela.

Miša mi se obratio za pomoć baš za kreiranje ove jedinstvene liste partnera, jer je problem dodatno komplikovala činjenica da su različiti izvori davali različita imena partnerima.

Da bih ilustrovao problem, daću sledeću strukturu tabela:

CREATE TABLE podaci_prodaje (
  sifra_partnera INTEGER NOT NULL PRIMARY KEY,
  ime_partnera VARCHAR(50) NOT NULL,
  broj_faktura INTEGER NOT NULL,
  prodajna_vrednost NUMERIC(12, 2) NOT NULL);         

CREATE TABLE podaci_nabavke (
  sifra_partnera INTEGER NOT NULL PRIMARY KEY,
  ime_partnera VARCHAR(50) NOT NULL,
  datum_poslednje_nabavke DATE NOT NULL,
  nabavna_vrednost NUMERIC(12, 2) NOT NULL);              

CREATE TABLE podaci_marketinga (
  sifra_partnera INTEGER NOT NULL PRIMARY KEY,
  ime_partnera VARCHAR(50) NOT NULL,
  broj_promocija INTEGER NOT NULL);

Ovu strukturu ću popuniti test podacima:

INSERT INTO podaci_prodaje (sifra_partnera, ime_partnera, broj_faktura, prodajna_vrednost)
  VALUES (1, 'Mika str', 2, 15000.00);
INSERT INTO podaci_prodaje (sifra_partnera, ime_partnera, broj_faktura, prodajna_vrednost)
  VALUES (2, 'Pera doo', 5, 46500.00);
INSERT INTO podaci_prodaje (sifra_partnera, ime_partnera, broj_faktura, prodajna_vrednost)
  VALUES (4, 'Joca doo', 4, 75000.00);         

INSERT INTO podaci_nabavke (sifra_partnera, ime_partnera, datum_poslednje_nabavke, nabavna_vrednost)
  VALUES (4, 'D.O.O. JOCA', '2007-03-01', 22000.00);
INSERT INTO podaci_nabavke (sifra_partnera, ime_partnera, datum_poslednje_nabavke, nabavna_vrednost)
  VALUES (5, 'Doo ZIKA i SONS', '2007-05-15', 15000.00);          

INSERT INTO podaci_marketinga (sifra_partnera, ime_partnera, broj_promocija)
  VALUES (1, 'MIKA', 1);
INSERT INTO podaci_marketinga (sifra_partnera, ime_partnera, broj_promocija)
  VALUES (3, 'MELANIJA', 2);
INSERT INTO podaci_marketinga (sifra_partnera, ime_partnera, broj_promocija)
  VALUES (4, 'JOCA', 5);

Napomena: Spomenuo sam da je Miša napravio četiri tabele, a ja ovde radim sa tri tabele jer to ne utiče na princip rešavanja problema.

Zahtev je da se od datih podataka napravi izveštaj sa sledećim kolonama: ime partnera, broj faktura, prodajna vrednost, datum poslednje nabavke, nabavna vrednost i kolona sa brojem promocija. Takođe, svi podaci o jednom partneru se moraju pojaviti u jednom redu.

U testnim podacima treba uočiti da ni jedna od službi (prodaje, nabavke, marketinga) nema u svojim podacima sve partnere. Druga stvar koju treba uočiti je neznatna razlika u imenovanju partnera u pojedinim službama. Tako služba prodaje partnera sa šifrom 1 imenuje ‘Mika str’, dok tog istog partnera marketing imenuje ’MIKA’.

Ova činjenica o imenovanju partnera komplikuje stvari jer se objedinjena lista partnera nemože dobiti prostim spajanjem (UNION) podataka raznih službi.

SELECT sifra_partnera, ime_partnera FROM podaci_prodaje
 UNION ALL
SELECT sifra_partnera, ime_partnera FROM podaci_nabavke
 UNION ALL
SELECT sifra_partnera, ime_partnera FROM podaci_marketinga;

Prikazan upit ne spaja podatke o partnerima na ispravan način jer duplira partnere koji su različito imenovani od strane različitih službi. Ovde nebi pomogla ni upotreba čistog UNION umesto UNION ALL.

Treba nam suptilniji način za spajanje podataka o partnerima i to se postiže pomoću sledećeg pogleda:

CREATE VIEW partneri (sifra_partnera, ime_partnera)
AS
SELECT s.sifra_partnera,
       CASE WHEN p.ime_partnera IS NOT NULL THEN p.ime_partnera
            WHEN n.ime_partnera IS NOT NULL THEN n.ime_partnera
            WHEN m.ime_partnera IS NOT NULL THEN m.ime_partnera
       END
  FROM (SELECT sifra_partnera FROM podaci_prodaje
         UNION
        SELECT sifra_partnera FROM podaci_nabavke
         UNION
        SELECT sifra_partnera FROM podaci_marketinga
       ) AS s
       LEFT OUTER JOIN
       podaci_prodaje AS p
         ON s.sifra_partnera = p.sifra_partnera
       LEFT OUTER JOIN
       podaci_nabavke AS n
         ON s.sifra_partnera = n.sifra_partnera
       LEFT OUTER JOIN
       podaci_marketinga AS m
         ON s.sifra_partnera = m.sifra_partnera;

U gornjem pogledu je prvo upotrebljen čist UNION za dobijanje svih (unikatnih) šifara, a onda su te šifre spojene sa odgovarajućim imenima partnera. Prost SELECT nad ovim pogledom vraća kompletnu listu jedinstvenih partnera:

sifra_partnera  ime_partnera
--------------  ---------------
             1  Mika str
             2  Pera doo
             3  MELANIJA
             4  Joca doo
             5  Doo ZIKA i SONS

Sada kada imamo jedinstvenu listu partnera uopšte nije teško doći do sledećeg upita:

SELECT s.ime_partnera,
       p.broj_faktura, p.prodajna_vrednost,
       n.datum_poslednje_nabavke, n.nabavna_vrednost,
       m.broj_promocija
  FROM partneri AS s
       LEFT OUTER JOIN
       podaci_prodaje AS p
         ON s.sifra_partnera = p.sifra_partnera
       LEFT OUTER JOIN
       podaci_nabavke AS n
         ON s.sifra_partnera = n.sifra_partnera
       LEFT OUTER JOIN
       podaci_marketinga AS m
         ON s.sifra_partnera = m.sifra_partnera;

Ovaj upit nam daje traženi rezultat:

ime_partnera     broj_faktura  prodajna_vrednost  datum_poslednje_nabavke  nabavna_vrednost  broj_promocija
---------------  ------------  -----------------  -----------------------  ----------------  --------------
Mika str                    2           15000.00                                                          1
Pera doo                    5           46500.00
MELANIJA                                                                                                  2
Joca doo                    4           75000.00               2007-03-01          22000.00               5
Doo ZIKA i SONS                                                2007-05-15          15000.00

Njemački znakovi u nazivima kolona + impdp u UTF8 bazu = problem

September 27, 2007 – Dejan

Džabe ja govorim ljudima da izbjegavaju njemačke ili bilo koje druge “specijalne” znakove u nazivima kolona, jer nema efekta sve dok ne iskrsne neki problem.

A kad iskrsne neki “ozbiljniji” problem, onda se i ja ko fol naljutim, pa im ozbiljnijim tonom dam do znanja da moraju ispraviti svoje greške.

Slična situacija se desila i juče. Exportujem bazu sa expdp, pokrenem import sa DataPump-om (impdp) u novu UTF8 bazu, kadli nakon nekoliko sati iskrsnu slijedeća greška:

Wed Sep 26 12:01:07 2007 Errors in file c:\oracle\product\10.2.0\admin\espaLive\bdump\espaLive_dw01_5360.trc:
ORA-07445: exception encountered: core dump [ACCESS_VIOLATION] [kpodpals+8916]
[PC:0×298CBA4] [ADDR:0×0] [UNABLE_TO_READ] []
 

a u trace datoteci pronađem ovo:

ksedmp: internal or fatal error
ORA-07445: exception encountered: core dump [ACCESS_VIOLATION] [kpodpals+8916]
 [PC:0×298CBA4] [ADDR:0×0] [UNABLE_TO_READ] []
—– PL/SQL Call Stack —–
  object      line  object
  handle    number  name
000007FF89AB6488        54  package body SYS.KUPD$DATA_INT
000007FF89AF62F8      1324  package body SYS.KUPD$DATA
000007FF89AFC3C8     10716  package body SYS.KUPW$WORKER
000007FF89AFC3C8      3687  package body SYS.KUPW$WORKER
000007FF89AFC3C8      6896  package body SYS.KUPW$WORKER
000007FF89AFC3C8      1259  package body SYS.KUPW$WORKER
000007FF89AD9440         2  anonymous block
—– Call Stack Trace —–

Nakon pretrage na MetaLinku nađoh da je riječ o bug-u (Bug: 5576865), koji se pojavljuje, kada se u pojedinim tabelama nalaze kolone sa njemačkim znakovima (’Ö’,'Ä’,'Ü’,'ß’), a koji je ispravljen u verziji 11g. Super.

Dakle, pošto od upgrade-a na 11g još dugo neće biti ništa, ne preostaje nam ništa drugo, nego prepraviti nazive kolona.


Oracle u Hrvatskoj obučava studente da dođu lakše do posla

September 20, 2007 – Dejan

U zadnjem newsletteru od Oraclea sam vidio jednu veoma zanimljivu vijest pod naslovom “Oracle helps young people to find employment opportunities“, a u tekstu sam pronašao veoma optimističan potez zastupništva Oraclea u Hrvatskoj.

Naime, zbog nedostatka dovoljno stručnih administratora Oracle baza podataka na hrvatskom tržištu, Oracle Hrvatska je odlučio da u saradnji sa Fakultetom elektrotehnike i računarstva održi besplatan kurs  “Oracle Database Administrator 10g“, sa ciljem da se popuni spomenuta rupa u manjku kvalifikovanih Oracle DBA.

Prenijeću citat gospodina Marina Tadića, predstavnika Oracle Hrvatska:
Everyone benefits from this initiative. Students receive free, vocational training that can help them to find a job more easily when they graduate, and they can also connect with potential employers who may also be interested in investing in their further education. Employers have an opportunity to find new employees with the combination of skills they are looking for.

Palac gore!


Isplativost sertifikata

September 11, 2007 – Dejan

Tu i tamo me znaju pitati, da li se isplati polagati ispite za pojedine sertifikate. Moj odgovor je - samo ukoliko te papire mozete potvrditi stvarnim znanjem.

Sertifikat bez znanja je u vecini slucajeva bezvrijedan. Ukoliko imate iole prakticnog znanja i iskustva, sertifikat vam moze pomoci pri zaposljavanju ili pri dobijanju povisice, a meni je sertifikat pomogao u oba slucaja - i pri dobijanju prvog PRAVOG posla, i sad nedavno pri dobijanju povisice (nekoliko stotina EUR vise). Znaci, meni se isplatio.

U svakom slucaju ne mozete biti na gubitku. :)



Agregatno spajanje stringova za PostgreSQL

August 26, 2007 – Srdjan

SQL standard propisuje 5 agregatnih funkcija: AVG, COUNT, MAX, MIN i SUM. Uz izuzetak COUNT funkcije, ostale agregatne funkcije rade nad numeričkim vrednostima.

Šta da radimo ako nam je potrebno prosto spajanje (konkatenacija) stringova? Iskoristićemo PostgreSQL-ovu mogućnost CREATE AGGREGATE za kreiranje nove agregatne funkcije.

Uopšte nije teško na internetu naći ovakvu funkciju. Prikazaću jednu koja je napisana upotrebom SQL jezika:

CREATE FUNCTION agg_concat (text, text)
RETURNS text AS
$body$
SELECT
  CASE WHEN $1 IS NULL
       THEN $2
       ELSE $1 || ', ' || $2
  END
$body$
LANGUAGE 'sql';    

CREATE AGGREGATE agg_concat (
  BASETYPE = TEXT,
  SFUNC = agg_concat,
  STYPE = TEXT
);

Kako se koristi ova nova agregatna funkcija?

Recimo da imamo jednu tabelu i njene podatke:

CREATE TABLE informacije (
  datum_informacije DATE NOT NULL,
  informacija VARCHAR(10) NOT NULL,
  CONSTRAINT pk_inf
    PRIMARY KEY (datum_informacije, informacija)
);    

INSERT INTO informacije
       (datum_informacije, informacija)
VALUES ('2007-08-23', 'posao');
INSERT INTO informacije
       (datum_informacije, informacija)
VALUES ('2007-08-23', 'odmor');
INSERT INTO informacije
       (datum_informacije, informacija)
VALUES ('2007-08-24', 'posao');
INSERT INTO informacije
       (datum_informacije, informacija)
VALUES ('2007-08-24', 'kafic');
INSERT INTO informacije
       (datum_informacije, informacija)
VALUES ('2007-08-24', 'bioskop');
COMMIT;

Ako hoćemo da izvršimo grupisanje informacija po danu, izvršimo sledeći upit:

SELECT datum_informacije,
       agg_concat(informacija) AS informacije
  FROM informacije
 GROUP BY datum_informacije
 ORDER BY datum_informacije;

Dobijamo sledeći rezultat:

datum_informacije   informacije
=================   ===========
2007-08-23          posao, odmor
2007-08-24          posao, kafic, bioskop

Download Oracle 11g (trenutno samo za Linux)

August 21, 2007 – Dejan

Evo, vratio sam se sa odmora, pa da nastavimo u revijalnom tonu…

Nakon najave nove verzije 11g, Oracle je sluzbeno objavio i dostupnost nove verzije (za pocetak samo na Linux platformi): Oracle Announces General Availability of Oracle Database 11g

Neke od novih opcija ce se posebno naplacivati, tako da je potrebno dobro razmisliti o stvarnoj potrebi za tim opcijama i da li se isplati preci na 11g. Mi u firmi ne planiramo prelaz na 11g prije nego sto izadje 11g Release 2.

U svakom slucaju, potvrdjuje se stara izreka - “Koliko para, toliko muzike”. 



Struktura evidencije partnera

August 16, 2007 – Srdjan

S vremena na vreme mi je posao da izvršim transfer podataka iz jednog sistema za čuvanje podataka u drugi sistem. Obično se izvorni sistemi sastoje od DBF datoteka. Česti problemi koji nastaju prilikom ovakvih transfera podataka su:
- različite strukture izvornih i ciljnih podataka i
- “prljavi” izvorni podaci (duplirani podaci (a usput različiti), podaci koji nedostaju, podaci koji se nalaze tamo gde im nije mesto,…).

Pre neki dan sam opet imao “čast” da vršim transfer takvih podataka. Od svega što sam zatekao u izvorni DBF datotekama, ovom prilikom ću prodiskutovati evidenciju o poslovnim partnerima.

Evidencija o partnerima se nalazila u jednoj DBF datoteci, sledeće strukture:

Field   Type Size
------- ---- ----
PRED     C    2
SIFRA    C    6
NAZIV1   C   30
NAZIV2   C   30
ADRESA   C   30
POSTBR   C    5
MESTO    C   24
GRAD     C   30
ZRACUN   C   25
ZRACUN2  C   25
ZRACUN3  C   25
ZRACUN4  C   25
ZRACUN5  C   25
ZRACUN6  C   25
OPISD    C   40
TELEFD   C   12
TEFAXD   C   12
OPISK    C   40
TELEFK   C   12
TEFAXK   C   12
OPIS     C   40
TELEF    C   12
TEFAX    C   12
GRUP1    C    2
GRUP2    C    2
MATBR    C    8
REGBR    C   11
SIFDEL   C    6
TREBA    L    1
PIB      C    9
OBVPDV   L    1

Sama struktura mi je otkrila nekoliko stvari:
- naziv partnera je podeljen na dve kolone,
- predviđeno je da se može zapisati do 6 tekućih računa (pojam žiro račun se ne upotrebljava već 2 i po godine) za jednog partnera,
- predviđeno je da se može zapisati do 6 brojeva telefona za jednog partnera.

Pogled na sadržaj tabele je otkrio mnogo više:
- Za neke partnere je bilo upisano i više od 6 brojeva telefona! Za upis dodatnih brojeva su korišćene kolone ‘opisd’, ‘opisk’ ili ‘opis’.
- Gore spomenute kolone su služile i za upisivanje e-mail adresa (ipak smo u 21-vom veku :) ) ili adrese istovarnog mesta.
- Vrednosti u koloni grad su izvedene od vrednosti kolone ‘postbr’ i ‘mesto’.
Prilično sam se namučio dok nisam podatke prebacio u ciljnu bazu. Posebno su problematične bile kolone opisa, koje su kako sam već rekao korišćene u razne svrhe. Iz ovoga i proizilazi zaključak da korišćena struktura podataka nije odgovarala potrebama za vođenje podataka o partnerima i kontaktima.

Hteo sam malo da se poigram sa postojećom strukturom i postavio sam pitanje: Kakva bi to struktura bila kvalitetnija od postojeće?

Kvalitetnija struktura mora da obezbedi:
1. unos više od 6 tekućih računa (koliko god to ludo zvučalo),
2. unos više od 6 brojeva telefona,
3. unos adresa poslovnica
4. unos e-mail adresa.

Pored gornje liste poboljšanja (koja bi se i još mogla proširiti), kvalitetnija struktura mora obezbediti kvalitetnija imena kolonama (da niko ne mora da razmišlja šta znači ‘grup1′, a šta ‘grup2′).

Ostvarenje prvog cilja

Izdvojio sam sve što se tiče tekućeg računa u novu tabelu kao što je prikazano na donjem dijagramu.

Slika 1

Ostvarenje drugog cilja

Izdvojio sam podatke o kontaktima (osobama, odeljenjima, službama) u posebnu tabelu kao što je prikazano na donjem dijagramu.

Slika 2
Svaki kontakt može imati više brojeva telefona (mobilni, kućni, direktan u firmi, lokal preko centrale). Takođe broj faks nije ništa drugo do još jedne vrste broja telefona. Izdvojio sam brojeve telefona iz tabele kontakata i oformio sam novu tabelu, kao na donjem dijagramu.

Slika 3

Ostvarenje trećeg cilja

Izdvojio sam podatke o adresi (ulica, broj, pošta i mesto) u posebnu tabelu i dodao sam svakoj adresi opis, kao što je prikazano u donjem dijagramu.

Slika 4

Ostvarenje četvrtog cilja

Za ovu potrebu sam jednostavno dodao novu tabelu u koju se zapisuju e-mailovi kontakata. Slično telefonu i adresi, i e-mail ima svoj (jedinstveni) opis.

Slika 5
Evo me na kraju zacrtanih ciljeva. Ova struktura je daleko fleksibilnija od polazne strukture.

Ova struktura ne odgovara samo programerima GUI-a, jer ju je daleko teže prikazati od prvobitne strukture, koja je i bila napravljena sa idejom što lakšeg pisanja programa. Programeri često zaborave da podaci jedne firme često nadžive njihove programe.

Mentalna napomena: Ako se u nekoj koloni očekuje unos imena (osobe, službe) koje se sastoji isključivo od slova, treba zabraniti unos cifara, pluseva, crtica i ostalih ne slovnih znakova. Ako se to ne uradi, naći će se neki korisnik koji će u tu kolonu uneti cifre ili nešto neočekivano.