Razlike izmedju MS SQL i Oracle

Wednesday, 04.04.2007 – Dejan

Danas sam naletio na jedan zanimljiv PDF dokument u kojem su navedene razlike i slicnosti izmedju MS SQL servera i Oracle-a (“Beginning SQL, Differences between Oracle and Microsoft MS SQL server“).

Pored poredjenja tipova podataka i koristenja DML izraza, tu su jos i poredjenja outer i sub join-a, koristenje aliasa i td.

Isplati se procitati.


Sacuvajte svoj kôd (Backup your source code)

Monday, 02.04.2007 – Dejan

Zamislite ovu situaciju…

Prepravili ste jedan veliki paket ili proceduru na testnom serveru, odradili nekoliko testova i odlucili taj paket ili proceduru prebaciti na live production server. Uvjereni ste da bi i na tom serveru sve trebalo raditi bez problema.

Medjutim, nakon sto ste prebacili paket ili proceduru na live server, vec nakon par minuta javljaju se korisnici i kazu kako im program ne radi, kako dobijaju neke greske itd.

Ali, istestirano je i sve bi trebalo da radi…” – zbunjeno odgovarate.
Prije par minuta je sve radilo, a sad odjednom ne…” – nestrpljivi i ocajni korisnici s druge strane.

E sad, najelegantnije rjesenje bi bilo vratiti nazad prethodnu verziju paketa ili procedure, dok se ne ustanovi uzrok greske.

Ali avaj – vi niste osigurali sigurnosnu kopiju prethodne verzije tog paketa ili procedure, a u CVS-u ne mozete u kratkom roku izabrati, koja je prava i ispravna verzija!?

Takav scenario sam dozivljavao i u prethodnoj firmi, a i u ovoj. Dzaba govoriti kolegama da uvijek naprave backup trenutno ispravne verzije…

Zbog toga sam odlucio doskociti tom problemu i automatizovati kreiranje sigurnosne kopije (source code backup).

Evo kako sam ja to uradio…

Cilj: Prije nego sto programer ubaci novu verziju nekog paketa ili procedure, kompletan source code aktuelne verzije treba biti sacuvan u slucaju da novija verzija ne funkcionise kako treba.

Realizacija: Napravio sam jedan “ON DATABASE trigger“, koji se okida na database event “BEFORE CREATE“, sto znaci da ce source code aktuelne verzije biti sacuvan PRIJE nego sto se nova verzija ubaci u bazu. U triggeru mozemo odabrati nacin cuvanja source code-a: u datoteku ili u neku tabelu. Ja sam odabrao drugu opciju, jer je optimalnija od prve (brza je, preglednija, ne moram se bakcati sa UTL_FILE_DIR podesavanjima i td.).

Dakle, kreirao sam tabelu pod nazivom TAB_BACKUP_SOURCE i u njoj jedno CLOB polje u koje ce biti smjesten source code aktuelne verzije (download: DDL izraz za kreiranje tabele TAB_BACKUP_SOURCE).

Nakon sto je tabela kreirana, mozemo kreirati i “ON DATABASE” trigger. Za selektovanje source code-a mozemo koristiti dvije metode: DBMS_METADATA.get_ddl ili preko data dictionary “pogleda” DBA_SOURCE. Procedura GET_DDL u paketu DBMS_METADATA nam vraca kompletan DDL izraz (DDL je skracenica od Data Definition Language) potreban za rekreiranje doticnog objekta (paket, procedura, trigger i td.), ali se u njemu nalaze i suvisni podaci, koji nama nisu potrebni, tako da sam ja za “poglede” (views) odabrao metodu DBMS_METADATA.get_ddl, a za ostale objekte (paketi, procedure, funkcije, triggeri) sam odabrao DBA_SOURCE.

Za kreiranje ovog triggera je potrebna DBA privilegija (DBA role), ali niposto nemojte da koristite SYS nalog, nego ukoliko vec nemate jednog pomocnog DBA korisnika, onda kreirajte jednog i dodijelite mu DBA rolu.

Ako je taj uslov ispunjen, kreirajte “ON DATABASE” trigger (download: DDL izraz za kreiranje triggera).

Gotovi ste? Odlicno!
Napravite par testova da se uvjerite, kako je sve u redu.

Nakon ovoga se vise ne morate brinuti zbog nemarnosti ili lijenosti vasih kolega programera. 🙂


Recenzija knjige “Oracle SQL Tuning & CBO Internals”

Thursday, 22.03.2007 – Dejan

Nastavljam sa recenzijama Oracle knjiga. 🙂

Jedna od rijetkih knjiga, koja nije ispunila moja ocekivanja je knjiga “Oracle SQL Tuning & CBO Internals” autorice Kimberly Floss u izdanju Rampant TechPress.

Ocekivao sam jasan prikaz optimizacije SQL upita, sa poredjenjima kako treba i kako ne treba koristiti odredjene izraze, zatim kako Cost Based Optimizer u stvarnosti interno funkcionise i na sta treba voditi posebnu paznju pri programiranju izuzetno zahtjevnih SQL upita, ali sve sto sam u knjizi nasao je hrpa nabacanih tekstova raznih autora bez ikakvog reda i bez medjusobne povezanosti.

Autorica je prikupila kolekciju svojih tekstova i njoj pridodala tekstove slicne tematike od drugih Oracle strucnjaka (Mike Ault, Don Burlesson i td.), sto i ne bi bilo tako lose da je sve uredno rasporedjeno po cjelinama, ali ovako je stvarno naporno i smarajuce citati razbacane tekstove.

Tekstovi sami po sebi nisu nekvalitetni i ima nekoliko zaista korisnih primjera, npr. uticaj redoslijeda kolona (polja; engl. “columns”) u indexu. To znaci da cemo u zavisnosti od redoslijeda kolona u indexu imati i razlicite performanse – nije isto ako u indexu sa 3 kolone imamo na prvom mjestu NUMBER, pa DATE, pa VARCHAR2 ili drugu varijantu kad je DATE na prvom mjestu, NUMBER na drugom, a VARCHAR2 na trecem ili pak trecu varijantu kad je VARCHAR2 na prvom mjestu, DATE na drugom i NUMBER na trecem. Ovo je objasnjeno na prakticnim primjerima, ali je tako nepregledno, da sam morao 3 puta za redom citati citav tekst u vezi toga, da bih shvatio sta je autor napisao u primjeru.

Ima jos par izuzetno dobrih primjera sa koristenjem Oracle putokaza/smjernica (Oracle hints), kao i objasnjenja koje serverske parametre trebamo podesiti radi dobijanja sto boljih performansi.

Knjiga nije bas citljiva i ne preporucujem ju pocetnicima. Mogla bi jedino koristiti iskusnijim “hardcore” Oracle programerima, koji zele produbiti svoje znanje i koji imaju zivaca i vremena za korisne, ali za citanje naporne tekstove. 

Ocjena: 5/10


Recenzija knjige “Effective Oracle by Design” (Thomas Kyte)

Tuesday, 20.03.2007 – Dejan

Ovo je takodje jedna od izuzetno kvalitetnih knjiga na temu svakodnevnog rada sa Oracle bazom, u kojoj je Thomas Kyte ( http://asktom.oracle.com/) jos jednom pokazao svoje majstorske vjestine i dokazao da je istinski Oracle guru.

Ne samo da je u tehnickom pogledu odlicno prenio svoje znanje na papir, nego se i u knjizevnom pogledu nametnuo kao iznadprosjecan autor.

Knjiga je namijenjena i administratorima i programerima, jer svakodnevni rad sa Oracle bazom ukljucuje obe aktivnosti i usku povezanost oba tima, sto je Tom odlicno objasnio na samom pocetku knjige. Naveo je ceste situacije u kojima se administratori i programeri smatraju kao dva protivnicka tima, koji rade jedan protiv drugog, umjesto da kolegijalno saradjuju i medjusobno se pomazu.

Osim sto se u knjizi nalazi razno teoretsko polemisanje i savjetovanje po principu “To se ne treba tako raditi“/”To se treba ovako raditi“, knjiga sadrzi mnostvo primjera sa popratnim objasnjenjem.

Tako je npr. odlicno objasnjeno koristenje EXPLAIN PLAN izraza, kako ga ispravno koristiti i kako ga ispravno tumaciti. Pri tome je objasnio kako se koriste alati za “tracing” i analizu “tracing” podataka (StatsPack, TKProf, AUTOTRACE i td.).

Zanima vas objasnjenje kako upiti prolaze parsing, executing i fetching fazu? Ima i to.

Pitate se kako funkcionise Cost Based Optimizer i koje hintove mogu koristiti u upitu? Procitajte u poglavlju 6.

Imate dilemu kako dizajnirati odredjenu tabelu? Da li ju particionisati ili ne? Da li koristiti index na jednoj koloni ili da indexiram vise njih? Koje STORAGE opcije definisati – extent od 1M ili 10M? Da li omoguciti paralelne upite nad tabelom ili ne? Na ova i mnoga druga pitanja, Tom je prakticnim primjerima objasnio optimalno kreiranje tabela i indexa.

U poglavlju 8, “Effective SQL“, mozete procitati koje vrste joina postoje i kako tacno funkcionisu, koristenje Top-N upita, zatim fenomenalno objasnjeno koristenje analitickih funkcija (ROW_NUMBER, DENSE_RANK, RANK, NTILE i td.) i nazalost slabo koristeni pivoting (u zadnje vrijeme sam prepravio mnogo PL/SQL procedura da koriste pivoting upite za izvlacenje podataka iz tabela, a ne algoritme, koji u vise koraka uzimaju podatke i naknadno ih obradjuju; mozda cu uskoro napisati i par primjera o pivoting upitima).

Koristite li BULK processing za ETL operacije? Ne znate sta je to i kako se koristi? E, pa procitajte poglavlje 9 – “Effective PL/SQL Programming“.

I na kraju imate nekoliko savjeta za ponasanje u slucaju problema sa bazom, kao i par gotovih skripti, koje mozete prepisati i slobodno koristiti.

Ja licno nemam visegodisnje iskustvo sa Oracleom (tek sam se 2003. godine poceo baviti Oracleom), ali nakon citanja ove knjige, moje znanje je poraslo kao da se bavim 10 godina Oracle programiranjem (al’ sam skroman 😉 ).

Ocjena: 10/10


Oracle: ON DELETE CASCADE

Sunday, 18.03.2007 – Dejan

Sa mnom u firmi radi nekoliko Java programera, kojima katkad treba objasniti kako funkcionisu neke stvari u Oracle bazi. Nakon sto sam njima objasnio kako funkcionise klauzula “ON DELETE CASCADE“, odlucio sam i ovdje napisati nesto o tome.

Konkretno, pita mene kolega:”Ako ja iz jedne parent tabele obrisem jedan unos, sta ce biti sa unosima u child tabeli? Da li ja moram da vodim evidenciju o tim promjenama i onda u Javi isprogramiram da se obrisu i svi referencijalni unosi u child tabeli?

Moj odgovor je bio kratak i jasan – “ON DELETE CASCADE“.

Pa da objasnim na jednom primjeru.

Imamo parent tabelu pod nazivom “KATEGORIJE_PROIZVODA” i jednu child tabelu pod nazivom “PROIZVODI“. Ukoliko iz tabele “KATEGORIJE_PROIZVODA” obrisemo neku kategoriju, svi referencijalni unosi u tabeli “PROIZVODI” trebaju takodje biti obrisani.

Ovdje mozete skinuti DDL i DML izraze potrebne za ovaj primjer (download DDL Create statements; download DML Insert statements), a ovako izgleda rezultat nakon izvrsavanja tih izraza:

C:>sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on So März 18 16:35:58 2007

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

SQL> conn scott/scottpass

Connect durchgef³hrt.

SQL> CREATE TABLE KATEGORIJE_PROIZVODA
  2  (
  3    ID     NUMBER NOT NULL,
  4    NAZIV  VARCHAR2(32 BYTE),
  5    OPIS   VARCHAR2(64 BYTE),
  6    CONSTRAINT pk_kat_proizvod PRIMARY KEY (ID) USING INDEX
  7  );

Tabelle wurde erstellt.

SQL> CREATE SEQUENCE SCOTT.SEQ_KAT_PROIZVOD_ID
  2    START WITH 1
  3    MAXVALUE 99999999999999
  4    MINVALUE 1
  5    NOCYCLE
  6    NOCACHE
  7    ORDER;

Sequence wurde erstellt.

SQL> CREATE OR REPLACE TRIGGER TR_KAT_PROIZVOD_ID
  2  BEFORE INSERT
  3  ON SCOTT.KATEGORIJE_PROIZVODA

  4  REFERENCING NEW AS NEW OLD AS OLD
  5  FOR EACH ROW
  6  BEGIN
  7
  8     SELECT SEQ_KAT_PROIZVOD_ID.NEXTVAL INTO :NEW.ID FROM dual;
  9
 10  EXCEPTION
 11    WHEN OTHERS THEN
 12      NULL;
 13  END tr_kat_proizvod_id;
 14  /

Trigger wurde erstellt.

SQL> CREATE TABLE PROIZVODI
  2  (
  3    ID            NUMBER NOT NULL,
  4    NAZIV         VARCHAR2(32 BYTE),
  5    KAT_PROIZ_ID  NUMBER,
  6    CONSTRAINT pk_proizvod PRIMARY KEY(ID) USING INDEX,
  7    CONSTRAINT fk_kat_proizvod FOREIGN KEY (kat_proiz_id)
  8      REFERENCES KATEGORIJE_PROIZVODA(ID)
  9      ON DELETE CASCADE
 10  );

Tabelle wurde erstellt.

SQL> CREATE SEQUENCE SCOTT.SEQ_PROIZVOD_ID
  2    START WITH 1
  3    MAXVALUE 99999999999999
  4    MINVALUE 1
  5    NOCYCLE
  6    NOCACHE
  7    ORDER;
Sequence wurde erstellt.

SQL> CREATE OR REPLACE TRIGGER TR_PROIZVOD_ID
  2  BEFORE INSERT
  3  ON SCOTT.PROIZVODI
  4  REFERENCING NEW AS NEW OLD AS OLD

  5  FOR EACH ROW
  6  BEGIN
  7
  8     SELECT SEQ_PROIZVOD_ID.NEXTVAL INTO :NEW.ID FROM dual;
  9
 10  EXCEPTION
 11    WHEN OTHERS THEN
 12      NULL;
 13  END tr_proizvod_id;
 14  /

Trigger wurde erstellt.

SQL> DECLARE
  2    lnKat1 NUMBER;
  3    lnKat2 NUMBER;
  4    lnKat3 NUMBER;
  5  BEGIN
  6     INSERT INTO KATEGORIJE_PROIZVODA (naziv, opis)
  7     VALUES('Cokoladice', 'Mljac njam')
  8     RETURNING ID INTO lnKat1;
  9
 10     INSERT INTO KATEGORIJE_PROIZVODA (naziv, opis)
 11     VALUES('Alkoholna pica', 'Bolje biti pijan, nego star')
 12     RETURNING ID INTO lnKat2;
 13
 14     INSERT INTO KATEGORIJE_PROIZVODA (naziv, opis)
 15     VALUES('Cigare', 'Pusenje ubija')
 16     RETURNING ID INTO lnKat3;
 17
 18     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 19     VALUES ('Snickers', lnKat1);
 20
 21     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 22     VALUES ('Snickers Cruncher', lnKat1);
 23
 24     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 25     VALUES ('Duplo', lnKat1);
 26
 27     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 28     VALUES ('Mars', lnKat1);
 29
 30     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 31     VALUES ('Zivotinjsko carstvo', lnKat1);
 32
 33     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 34     VALUES ('Milky Way', lnKat1);
 35
 36     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 37     VALUES ('Twix', lnKat1);
 38
 39     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 40     VALUES ('Heineken pivo', lnKat2);
 41
 42     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 43     VALUES ('Tuborg pivo', lnKat2);
 44
 45     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 46     VALUES ('Bavaria pivo', lnKat2);
 47
 48     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 49     VALUES ('Budweiser pivo', lnKat2);
 50
 51     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 52     VALUES ('Marlboro', lnKat3);
 53
 54     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 55     VALUES ('Morava', lnKat3);
 56
 57     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 58     VALUES ('Ronhill', lnKat3);
 59
 60     INSERT INTO PROIZVODI (naziv, KAT_PROIZ_ID)
 61     VALUES ('Davidoff', lnKat3);
 62  END;
 63  /

PL/SQL-Prozedur erfolgreich abgeschlossen.

SQL>

Nakon sto smo kreirali tabele i unijeli podatke, pogledajmo trenutni sadrzaj tih tabela. 

SQL> SELECT * FROM KATEGORIJE_PROIZVODA;
        ID NAZIV                            OPIS
---------- -------------------------------- --------------------------------
         1 Cokoladice                       Mljac njam
         2 Alkoholna pica                   Bolje biti pijan, nego star
         3 Cigare                           Pusenje ubija
SQL> SELECT * FROM proizvodi;
        ID NAZIV                            KAT_PROIZ_ID
---------- -------------------------------- ------------
         1 Snickers                                    1
         2 Snickers Cruncher                           1
         3 Duplo                                       1
         4 Mars                                        1
         5 Zivotinjsko carstvo                         1
         6 Milky Way                                   1
         7 Twix                                        1
         8 Heineken pivo                               2
         9 Tuborg pivo                                 2
        10 Bavaria pivo                                2
        11 Budweiser pivo                              2
        12 Marlboro                                    3
        13 Morava                                      3
        14 Ronhill                                     3
        15 Davidoff                                    3
15 Zeilen ausgewõhlt.

Ukoliko su uneseni podaci ispravni, obrisacemo kategoriju “Cigare“, jer je zakonom zabranjeno pusenje na javnim mjestima i nije vise isplativo prodavati cigare. 😉

Posto imamo referencijalni integritet (Foreign key) izmedju parent i child tabele, u child tabeli “PROIZVODI” bi svi proizvodi iz kategorije “Cigare” trebali biti obrisani.

SQL> DELETE FROM KATEGORIJE_PROIZVODA
  2  WHERE ID = 3;
1 Zeile wurde gelöscht.

Provjerimo jos jednom sadrzaj obe tabele i uvjerimo se da su obrisani i kategorija i svi proizvodi iz te kategorije.

SQL> SELECT * FROM KATEGORIJE_PROIZVODA;
        ID NAZIV                  OPIS
---------- ---------------------- ---------------------------
         1 Cokoladice             Mljac njam
         2 Alkoholna pica         Bolje biti pijan, nego star
SQL> SELECT * FROM proizvodi;
        ID NAZIV                   KAT_PROIZ_ID
---------- ----------------------- ------------
         1 Snickers                           1
         2 Snickers Cruncher                  1
         3 Duplo                              1
         4 Mars                               1
         5 Zivotinjsko carstvo                1
         6 Milky Way                          1
         7 Twix                               1
         8 Heineken pivo                      2
         9 Tuborg pivo                        2
        10 Bavaria pivo                       2
        11 Budweiser pivo                     2
11 Zeilen ausgewõhlt.

Jednostavno i efikasno. Java programeri ne moraju vise da vode brigu o parent-child vezama prilikom brisanja podataka.

Ukoliko ne zelite da podaci iz child tabele budu obrisani, mozete umjesto klauzule “ON DELETE CASCADE” koristiti klauzulu “ON DELETE SET NULL“, pri cemu ce kat_proiz_id dobiti vrijednost NULL ukoliko bude obrisana pripadajuca kategorija iz parent tabele.



Recenzija knjige “Oracle database 10g: RMAN Backup & Recovery”

Tuesday, 13.03.2007 – Dejan

Nakon sto sam procitao ovu knjigu, red bi bio da napisem i kratku recenziju o njoj.

Knjiga je novije izdanje prethodne knjige “Oracle database 9i: RMAN Backup & Recovery“, s tim sto su dodane novosti i izmjene sadrzane u verziji 10g. Ko je procitao knjigu za verziju 9i, odusevice se i ovom.

U knjizi su obuhvacene mnoge stvari: od definicije i objasnjenja sta su to backup, recovery, struktura baze i sl., preko opisa trenutno najboljih backup rjesenja na trzistu, pa sve do “korak-po-korak” objasnjenja pojedinih scenarija backup i recovery strategije. Bas ova “korak-po-korak” objasnjenja su odlicno napisana i nude konkretno rjesenje za mnoge “live” slucajeve.

Navescu samo neke od njih:
– kloniranje baze pomocu RMAN-a
– podesavanje StandBy baze
– podesavanje pomocne (auxiliary) instance za “tablespace point in time recovery”
– recovery nakon gubitka baze, tablespacea ili pojedinih fajlova
– inkrementalni backup

i td.

Osim sto je tehnicki stvarno odlicno napisana, autori su se potrudili knjigu uciniti i duhovitom, kako citaoci ne bi bili smoreni suhoparnim informacijama. Evo par takvih primjera:
Well, let’s get started with this RMAN thing, shall we? I’ll just reach down, pull on the handle… I said pull on the handle… and, it doesn’t start.”
One of the other ways you can leverage your backups is to use them to make copies of the production database for testing and development purpose, in the database world, we refer to this as cloning (keep your sheep jokes to yourself).
Today is not Bill’s day. A large thunderstorm is raging outside, and Bill has forgotten that his car’s soft top is down. To make Bill’s day worse, a strike of lightning hits the data center and fries several disk drives that Bill’s database calls home.”

Tu su jos i objasnjenja kako koristiti backup u RAC okruzenjima, kako se dobro pripremiti za disaster recovery slucajeve, kako poboljsati performanse backupa (splitting, stripping, multiplexing i td.), a ima i dosta primjera sa koristenjem Enterprise Managera, tako da se mnoge stvari ne moraju raditi u RMAN command line clientu.

Meni knjiga ni na trenutak nije bila dosadna i mogu ju mirne duse preporuciti dalje. 🙂

Knjigu sam kupio preko Amazona za 59.99 dolara, ali je sad pojeftinila.

Ocjena: 10/10


Oracle: Vrijednosti :NEW i :OLD varijabli pri okidanju triggera

Wednesday, 28.02.2007 – Dejan

Evo bas sam danas jednom kolegi programeru objasnjavao statuse :NEW i :OLD varijabli pri odredjenom trigger fire-eventu (mozebitni prevod: okidacki dogadjaj?) . Za tu svrhu sam koristio jedan najobicniji primjer, koji cu pokazati i ovdje.

Najprije moramo napraviti tabelu i unijeti testne podatke:

CREATE TABLE test_table(id NUMBER, tekst VARCHAR2(32));

INSERT INTO test_table VALUES(1, 'tekst1');
INSERT INTO test_table VALUES(2, 'tekst2');
INSERT INTO test_table VALUES(3, 'tekst3');
INSERT INTO test_table VALUES(4, 'tekst4');
INSERT INTO test_table VALUES(5, 'tekst5');

SELECT * FROM test_table;

ID TEKST
-- ------
1 tekst1
2 tekst2
3 tekst3
4 tekst4
5 tekst5


Nakon toga kreiramo trigger:

CREATE OR REPLACE TRIGGER tr_old_new
BEFORE UPDATE OR INSERT OR DELETE ON test_table
FOR EACH ROW
BEGIN
  IF UPDATING THEN
    dbms_output.put_line('Updating: ');
    dbms_output.put_line('old id: '||:OLD.id);
    dbms_output.put_line('new id: '||:NEW.id);
    dbms_output.put_line('old tekst: '||:OLD.tekst);
    dbms_output.put_line('new tekst: '||:NEW.tekst);
  END IF;
  IF INSERTING THEN
    dbms_output.put_line('Inserting: ');
    dbms_output.put_line('old id: '||:OLD.id);
    dbms_output.put_line('new id: '||:NEW.id);
    dbms_output.put_line('old tekst: '||:OLD.tekst);
    dbms_output.put_line('new tekst: '||:NEW.tekst);
  END IF;
  IF DELETING THEN
    dbms_output.put_line('Deleting: ');
    dbms_output.put_line('old id: '||:OLD.id);
    dbms_output.put_line('new id: '||:NEW.id);
    dbms_output.put_line('old tekst: '||:OLD.tekst);
    dbms_output.put_line('new tekst: '||:NEW.tekst);
  END IF;
EXCEPTION
  WHEN OTHERS THEN
  dbms_output.put_line(SQLERRM);
END tr_old_new;
/


Nakon sto smo uspjesno kreirali tabelu i trigger, mozemo napraviti test za svaki fire-event: UPDATE, INSERT i DELETE. Ne zaboravite aktivirati DBMS Output (u sqlplusu akvitirajte ovako “set serveroutput on“, a za alat, koji vec koristite znate vec i sami kako da aktivirate DBMS output. 🙂 ).

INSERT INTO test_table VALUES(6, 'tekst6');
Trebalo bi se ispisati slijedece:

Inserting:
old id:
new id: 6
old tekst:
new tekst: tekst6

UPDATE test_table SET id = 7 WHERE id = 6;

Trebalo bi se ispisati slijedece:

Updating:
old id: 6
new id: 7
old tekst: tekst6
new tekst: tekst6

DELETE FROM test_table WHERE id = 7;

Trebalo bi se ispisati slijedece:

Deleting:
old id: 7
new id:
old tekst: tekst6
new tekst:

Mislim da je iz samog ispisa vidljivo koje vrijednosti sadrze :NEW i :OLD varijable prilikom okidanja triggera.



Oracle homepage redesigned

Monday, 26.02.2007 – Dejan

Nakon sto su prethodni put preuredjene web stranice od Oraclea, zapitao sam se – zasto su taj posao aljkavo uradili i zasto je sve nabacano bez imalo preglednosti. Izgleda da nisam bio jedini, koji se mucio sa preglednoscu Oracleovog web sajta, jer je nedavno Oracle homepage ponovno preuredjen – ovaj put daleko bolje, nego ranije!

 Smanjili su broj razbacanih linkova sa lijeve strane i iskoristili onaj ogromni lose iskoristeni prostor, koji je obuhvatao 70% index stranice. Na zalost, ni sada centralni prostor nije najbolje iskoristen, ali je barem pregledan. Sve podstranice nisu jos preuredjene, ali vremenom ce i one doci na red.



MySQL 5.0 sertifikat (Certified MySQL 5.0 DBA – CMDBA)

Saturday, 17.02.2007 – Dejan

MySQL sertifikatSitni pokloni od MySQL-aKonačno! Nakon skoro 5 mjeseci čekanja, danas mi je na kućnu adresu stigao MySQL sertifikat (slika lijevo). Nema plastične kartice kao kod Oraclea, ali sam zato dobio neke poklon-zezalice od MySQL-a (slika desno – lopta na duvanje i neki neobični “boomerang”).

Zašto je tako dugo trajalo? Niko nema odgovor – niti MySQL, niti LPI, koji šalje sertifikate. Navodno mi je LPI još u oktobru poslao sertifikat na kućnu adresu, ali onu u Bosni, no taj sertifikat nije nikad došao ili, bolje rečeno, nije prošao pored nečijih “nepismenih” ruku u pošti (ne bih bio pesimista, pa da kažem kako je neko od zaposlenih u pošti otvorio paket iz Kanade u nadi da će u njemu naći nešto vrijedno, pa kad je vidio da nema ništa vrijedno, onda paket bacio zajedno sa sertifikatom).

I tako ja sinoć šaljem E-Mail poruku Carstenu Pedersenu i Rolandu Boumanu sa kritikom na račun slanja sertifikata, kad ono jutros u sandučetu – MySQL sertifikat.
Odmah sam poslao izvinjenje dotičnima i potvrdio prijem sertifikata.



Novosti u verziji Oracle 11g (Oracle 11g enhancements)

Monday, 12.02.2007 – Dejan

Pisao sam već kako sam u zadnje vrijeme jako nezadovoljan Oracleom i kako forsira nove verzije, iako ni aktualne verzije (trenutno 10g) nisu 100% završene i ispravljene od bugova. Na Metalinku često za neke bugove ili opcije viđam napomenu “Fixed in version: 11g“.

Verzija 10g je donijela dosta novih stvari u odnosu na verziju 8i i 9i, pa se isto tako od verzije 11g očekuje dosta novosti u odnosu na trenutnu verziju 10g. Ja ću navesti samo neke od tih novosti, do kojih sam saznao prateći razne blogove i forume.

 +++ Novosti u verziji 11g (Enhancements in Oracle 11g) +++

DML triggeri će biti do 25% brži nego sad, što će se posebno primijetiti kod row-level triggera u kojima se vrši unos/izmjena podataka u drugim tabelama (korisno za npr. Audit-trigger).
Fine Grained Dependancy Tracking (FGDT) – ukoliko dodate kolonu u neku tabelu ili izmijenite package specification (package header), zavisni objekti (dependant objects) neće biti označeni kao invalidni (nevažeći). Jako korisno za production 24×7 baze.
Native Compilation – kompajliranje PL/SQL kôda ne zahtjeva više C kompajler, nego se interno smješta direktno u shared library. Navodno će isto važiti i za Java kôd u bazi.
Novi tip podataka – simple_integer – Deklarisan uvijek kao NOT NULL i navodno će biti brži od PLS_INTEGER.
Keširanje SQL i PL/SQL-a (SQL and PL/SQL result caching) – Biće dodan “result cache” u kojem će se nalaziti rezultati pojedinih SQL upita i PL/SQL procedura, što će višestruko ubrzati naknadna  izvršavanja dotičnih upita i procedura.
Kombinovani triggeri (compound triggers “all-in-one”) – Zamislite trigger zajednički definisan da bude “okinut” na after, before, row i statement uslove!? Da, navodno će i ta sjajna mogućnost biti dostupna u verziji 11g. A osim toga, u običnim triggerima će biti moguće odrediti redoslijed okidanja pojedinih triggera nad tabelom.
Dynamic SQLDBMS_SQL je ubrzan i poboljšan. I Native Dynamic SQL (EXECUTE IMMEDIATE) i DBMS_SQL mogu sada prihvatati CLOB tipove podataka (nema više ograničenja na veličinu od 32k). REF CURSOR se može konvertovati u DBMS_SQL cursor i obrnuto. Pored toga, DBMS_SQL će podržavati BULK operacije i “user defined” tipove.
Row-level security (RLS), tj. Fine grained access control (FGAC) – Biće npr. moguće odrediti sigurnost za portove i URL-ove koje koriste paketi UTL_TCP, UTL_HTTP i UTL_SMTP.
Read only tables – Biće moguće podesiti tabelu dozvoljenu samo za čitanje.
CONTINUE komanda – Može se koristiti za uslovni izlaz iz petlje.
Poboljšana kompresija za setove podataka – za oko 2/3 smanjiće se potrebna količina prostora za spremanje tih podataka.
Speed boost – navodno će Oracle mnogo brže čitati podatke sa “raw devices”, nego sa do sada dostupnim file systemima.
Replay Workload – Mogućnost “hvatanja” (capturing) svih aktivnosti u bazi i kopiranja tih aktivnosti na neki drugi server (npr. na testni server) bez korištenja nekog posebnog alata za tu namjenu.
Online Application Upgrades – Biće moguće instalirati neki patch bez gašenja baze (hot patching with no downtime).
Quick Fault Resolution – Automatsko hvatanje svih potencijalno povezanih uzroka neke greške.
Database Repair Advisor – Asistent (wizard), koji pomaže administratoru pri pronalaženju greške i njenom otklanjanju.
– Biće omogućeno particionisanje po logičkim objektima (partition by logical objects), kao i automatsko particionisanje radi olakšanja pri radu sa VLDB (Very Large Databases).
– Nova high-performance infrastruktura za LOB objekte.
– Re-engineered driver za PHP