Svi postovi sa bloga: Baze podataka

U prethodnom tekstu sam pisao kako obaviti backup Oracle baze pomoću RMAN-a, u kojem sam pored ostalog naveo i da ću pokazati kako se vrši povratak (recovery) Oracle baze pomoću RMAN-a. Pošto je taj tekst ionako bio dug, odlučio sam ovaj dio objaviti kao nastavak.

Prvi slučaj: Povratak izgubljenog SYSTEM tablespacea
(recovering from the loss of the SYSTEM tablespace)

Da bih pokazao kako obaviti povratak izgubljenog SYSTEM tablespacea, simuliraću gubitak datoteke SYSTEM01.DBF, koja pripada SYSTEM tablespaceu. Ukoliko vi zaista imate izgubljenu datoteku za SYSTEM tablespace, kao što je npr. prikazano u koraku 4, onda preskočite odmah na korak 5.

1. Ugasiti bazu:
SQL> shutdown immediate;

2. Pronaći SYSTEM01.DBF na sistemu i preimenovati ju u SYSTEM01_bkp.DBF.

3. Bazu ponovo pokrenuti:
SQL> startup;

4. Trebali biste dobiti ovakvu poruku:
ORA-01157: cannot identify/lock data file 1 - see DBWR trace file
ORA-01110: data file 1: 'E:\oracle\SYSTEM01.DBF'

ili ako koristite njemački jezik:
ORA-01157: Datendatei 1 kann nicht identifiziert/gesperrt werden - siehe DBWR-Trace-Datei
ORA-01110: Datendatei 1: 'E:\oracle\SYSTEM01.DBF'

To znači da je SYSTEM tablespace nedostupan i samim tim baza ne može funkcionisati.
Sada nam u pomoć dolazi RMAN, pomoću kojeg ćemo vratiti bazu u normalno stanje.

5. Spojimo se RMAN-om na bazu i recovery katalog, pa potom ugasimo bazu i pokrenemo ju u MOUNT stanje. Biće učitan controlfile, ali u ovoj fazi se neće vršiti provjera ispravnosti i dostupnosti datoteka od kojih se sastoji svaki tablespace. MOUNT stanje na omogućava da popravimo oštećene ili nedostupne datoteke, nakon čega možemo ponovo pokrenuti bazu u normalnom stanju:
C:\> rman target sys/sysPass@productionDB catalog rman_cat/rmanPass@katalogDB
RMAN> startup force mount;

6. Iz backup lokacije prebacimo pripadajuću datoteku za SYSTEM tablespace:
RMAN> restore tablespace SYSTEM;

7. Povratimo SYSTEM tablespace u normalno stanje:
RMAN> recover tablespace SYSTEM;

8. I konačno otvorimo bazu za normalan rad:
RMAN> alter database open;

Kako to sve izgleda u praksi?
C:\> rman target sys/sysPass@productionDB catalog rman_cat/rmanPass@katalogDB
Recovery Manager: Release 10.2.0.3.0 - Production on Tue Oct 30 11:30:02 2007
Copyright (c) 1982, 2005, Oracle.  All rights reserved. 

connected to target database: PRODUCTIONDB (DBID=1243025471, not open) 

connected to recovery catalog database 

RMAN> startup force mount; 

Oracle instance started 

database mounted 

Total System Global Area   10737418240 bytes 

Fixed Size                     2072800 bytes 

Variable Size              10636758816 bytes 

Database Buffers              83886080 bytes 

Redo Buffers                  14700544 bytes 

RMAN> restore tablespace system; 

Starting restore at 30-OCT-07 

allocated channel: ORA_DISK_1 

channel ORA_DISK_1: sid=652 devtype=DISK 

allocated channel: ORA_DISK_2 

channel ORA_DISK_2: sid=651 devtype=DISK 

channel ORA_DISK_1: restoring datafile 00001 

input datafile copy recid=443 stamp=617116129
filename=H:\BACKUP\RMAN\DATA_D-PRODUCTIONDB_I-1243025471_TS-SYSTEM_FNO-1_AKICEQDQ 

destination for restore of datafile 00001: E:\oracle\SYSTEM01.DBF 

channel ORA_DISK_1: copied datafile copy of datafile 00001 

output filename=E:\oracle\SYSTEM01.DBF recid=513 stamp=617196354 

Finished restore at 30-OCT-07 

RMAN> recover tablespace system; 

Starting recover at 30-OCT-07 

using channel ORA_DISK_1 

using channel ORA_DISK_2 

starting media recovery 

media recovery complete, elapsed time: 00:00:09 

Finished recover at 30-OCT-07 

RMAN> alter database open; 

database opened
Drugi slučaj: Povratak obične datoteke ili običnog tablespacea
(recovering online from the loss of the datafile or tablespace)

Ovu situaciju ću prikazati praktičnim primjerom bez puno objašnjavanja, jer smatram da se vide sve potrebne informacije.

RMAN> shutdown immediate
database closed 

database dismounted 

Oracle instance shut down 

RMAN> startup; 

connected to target database (not started) 

Oracle instance started 

database mounted 

RMAN-00571: =========================================================== 

RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS =============== 

RMAN-00571: =========================================================== 

RMAN-03002: failure of startup command at 10/30/2007 14:26:56 

ORA-01157: cannot identify/lock data file 3 - see DBWR trace file 

ORA-01110: data file 3: 'H:\oracle\INDX01.DBF' 

RMAN> 

RMAN> sql "alter database datafile 3 offline"; 

sql statement: alter database datafile 3 offline 

RMAN> alter database open; 

database opened 

RMAN> restore datafile 3; 

Starting restore at 30-OCT-07 

allocated channel: ORA_DISK_1 

channel ORA_DISK_1: sid=647 devtype=DISK 

allocated channel: ORA_DISK_2 

channel ORA_DISK_2: sid=643 devtype=DISK 

channel ORA_DISK_1: restoring datafile 00003 

input datafile copy recid=435 stamp=617116127 filename=H:\BACKUP\RMAN\INDX01.DBF 

destination for restore of datafile 00003: H:\ESIFMP\INDX01.DBF 

channel ORA_DISK_1: copied datafile copy of datafile 00003 

output filename=H:\oracle\INDX01.DBF recid=514 stamp=617206971 

Finished restore at 30-OCT-07 

RMAN> recover datafile 3; 

Starting recover at 30-OCT-07 

using channel ORA_DISK_1 

using channel ORA_DISK_2 

starting media recovery 

media recovery complete, elapsed time: 00:00:04 

Finished recover at 30-OCT-07
Vi biste još?

E, pa nema. D
Mislim, ima toliko mnogo mogućih situacija u kojima može doći do problema u radu baze (media failure, instance failure, datafile loss/corupption i td.), tako da nema šanse objasniti ih i prikazati u jednom blog tekstu. Više primjera imate u već spomenutoj knjizi iz prvog dijela teksta (Oracle database 10g: RMAN Backup & Recovery), kao i na internetu. Google je moj najbolji prijatelj - neka bude i vaš! D

Većina upita može da se napiše na različite načine.  CJ Date u online članku “Fifty Ways to Quote Your Query” prikazao listu od 52 načina da se iskaže jedan upit! Nije mi namera da se u ovome takmičim sa Date-om, već želim da prikažem nekoliko praktičnih i pravolinijskih metoda pomoću kojih se izvesna forma upita može zameniti adekvatnom (a efikasnijom) formom.

Prikazaću dve slične metode za transformaciju upita.

1. Prvom metodom se upit oblika … IN (SELECT …) pretvara u upit oblika … EXISTS (SELECT …), a naknadno se EXISTS zamenjuje sa INNER JOIN.

2. Drugom metodom se upit oblika … NOT IN (SELECT …) pretvara u upit oblika … NOT EXISTS (SELECT …), a naknadno se EXISTS zamenjuje sa LEFT OUTER JOIN

Cilj ovih transformacija je da se pronađe oblik upita koji najbolje odgovara SQL optimizatoru konkretnog SUBP-a (sistema za upravljanje bazama podataka), to jest da se koristi oblik upita koji se najbrže izvršava.

Struktura testnih tabela i testni podaci

Prvo ću dati strukturu i podatke, koji će mi pomoći u demonstraciji metoda transformacije upita. (Strukturu sam pozajmio iz jednog od mojih predhodnih postova.)

CREATE TABLE partneri (
  sifra_partnera INTEGER NOT NULL,
  ime_partnera VARCHAR(50) NOT NULL,
  CONSTRAINT pk_par
    PRIMARY KEY (sifra_partnera)
);                 

CREATE TABLE adrese (
  sifra_partnera INTEGER NOT NULL,
  opis_adrese VARCHAR(20) NOT NULL,
  CONSTRAINT pk_tra
    PRIMARY KEY (sifra_partnera, opis_adrese),
  CONSTRAINT fk_tra_par
    FOREIGN KEY (sifra_partnera) REFERENCES partneri
    ON DELETE CASCADE ON UPDATE CASCADE
);             

INSERT INTO partneri (sifra_partnera, ime_partnera)
  VALUES (1, 'Mika str');
INSERT INTO partneri (sifra_partnera, ime_partnera)
  VALUES (2, 'Pera doo');
INSERT INTO partneri (sifra_partnera, ime_partnera)
  VALUES (3, 'MELANIJA');
INSERT INTO partneri (sifra_partnera, ime_partnera)
  VALUES (4, 'Joca doo');
INSERT INTO partneri (sifra_partnera, ime_partnera)
  VALUES (5, 'Doo ZIKA i SONS');                 

INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (1, 'prodavnica');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (2, 'prodavnica br 1');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (2, 'prodavnica br 2');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (2, 'Kafana kod Pere');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (4, 'uprava');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (4, 'skladiste');
INSERT INTO adrese (sifra_partnera, opis_adrese)
  VALUES (4, 'prodavnica');
INSERT INTO adrese (sifra_partnera, ime_partnera)
  VALUES (5, 'Kafana Sinovi');
Prva metoda - zamena upita oblika … IN (SELECT …)

Ovu metodu ću demonstrirati na upitu koji daje odgovor na pitanje: Treba prikazati partnere koji imaju barem dve adrese.

Jedan od upita koji daje odgovor na ovo pitanje je upit koji koristi IN izraz:

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE p.sifra_partnera IN
       (SELECT a.sifra_partnera
          FROM adrese AS a
         GROUP BY a.sifra_partnera
        HAVING COUNT(a.sifra_partnera) > 1
       )
 ORDER BY p.sifra_partnera

Kako od ovog upita napraviti ekvivalentan upit upotrebom izraza EXISTS? Ponoviću ponovo predhodan upit, ali ću bojom istaći ključne elemente upita koji učestvuju u transformaciji.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE p.sifra_partnera IN
       (SELECT a.sifra_partnera
          FROM adrese AS a
         GROUP BY a.sifra_partnera
        HAVING COUNT(a.sifra_partnera) > 1
       )
 ORDER BY p.sifra_partnera

Ekvivalentan upit je sledeći upit u kojem sam istakao šta se desilo sa ključnim elementima iz predhodnog upita. Treba primetiti da je p.sifra_partnera iz spoljašnjeg upita ušla u unutrašnji upit u sastavu WHERE klauzule.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE EXISTS
       (SELECT a.sifra_partnera
          FROM adrese AS a
         WHERE p.sifra_partnera = a.sifra_partnera
         GROUP BY a.sifra_partnera
        HAVING COUNT(a.sifra_partnera) > 1
       )
 ORDER BY p.sifra_partnera

Kako od ovog upita doći do upita koji koristi INNER JOIN? Isti ključni elementi i dalje učestvuju u transformaciji i dobija se donji upit. Treba primetiti da konstrukcija p.sifra_partnera = a.sifra_partnera izlazi iz unutrašnjeg upita i pojavljuje se kao uslov spajanja u spoljašnjem upitu.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
       INNER JOIN
       (SELECT a.sifra_partnera
          FROM adrese AS a
         GROUP BY a.sifra_partnera
        HAVING COUNT(a.sifra_partnera) > 1
       ) AS pa
         ON p.sifra_partnera = pa.sifra_partnera
 ORDER BY p.sifra_partnera

Ceo postupak, korak po korak, sam bolje demonstrirao pomoću Power Point prezentacije Isti upit 1.

Rezultat izvršavanja sva tri gornja upita je isti:

sifra_partnera   ime_partnera
--------------   ------------
             2   Pera doo
             4   Joca doo
Druga metoda - zamena upita oblika … NOT IN (SELECT …)

Ovu metodu ću demonstrirati na upitu koji daje odgovor na pitanje: Treba prikazati partnere koji nemaju adresu.

Jedan od upita koji daje odgovor na ovo pitanje je upit koji koristi IN izraz:

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE p.sifra_partnera NOT IN
       (SELECT a.sifra_partnera
          FROM adrese AS a
       )
 ORDER BY p.sifra_partnera

Kako od ovog upita napraviti ekvivalentan upit upotrebom izraza NOT EXISTS? Ponoviću ponovo predhodan upit, ali ću bojom istaći ključne elemente upita koji učestvuju u transformaciji.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE p.sifra_partnera NOT IN
       (SELECT a.sifra_partnera
          FROM adrese AS a
       )
 ORDER BY p.sifra_partnera

Ekvivalentan upit je sledeći upit u kojem sam istakao šta se desilo sa ključnim elementima iz predhodnog upita. Treba primetiti da je p.sifra_partnera iz spoljašnjeg upita ušla u unutrašnji upit u sastavu WHERE klauzule.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
 WHERE NOT EXISTS
       (SELECT a.sifra_partnera
          FROM adrese AS a
         WHERE p.sifra_partnera = a.sifra_partnera
       )
 ORDER BY p.sifra_partnera

Kako od ovog upita doći do upita koji koristi LEFT OUTER JOIN? Isti ključni elementi i dalje učestvuju u transformaciji i dobija se donji upit. Treba primetiti da konstrukcija p.sifra_partnera = a.sifra_partnera izlazi iz unutrašnjeg upita i pojavljuje se kao uslov spajanja u spoljašnjem upitu. Takođe je bitno napomenuti kako je potrebno dodati WHERE klauzulu pa.sifra_partnera IS NULL.

SELECT p.sifra_partnera, p.ime_partnera
  FROM partneri AS p
       LEFT OUTER JOIN
       (SELECT a.sifra_partnera
          FROM adrese AS a
       ) AS pa
         ON p.sifra_partnera = pa.sifra_partnera
 WHERE pa.sifra_partnera IS NULL
 ORDER BY p.sifra_partnera

Slično kao i kod prethodne metode, i ovde ceo postupak demonstrirao pomoću Power Point prezentacije Isti upit 2.

Rezultat izvršavanja sva tri gornja upita je isti:

sifra_partnera   ime_partnera
--------------   ------------
             3   MELANIJA
Zaključak

Koji od prikazanih upita daje rezultat najbrže? To se mora proveriti u zavisnosti od konkretnog SUBP-a, količine podataka, postojanja indeksa. Može se desiti da pojedini (stariji?) sistemi ni ne podržavaju sve prikazane verzije upita.

Moja iskustva sa PostgreSQL 8.1 i 8.2 sistemima pokazuju, da se najbolje ponašaju verzije upita koje koriste INNER JOIN i LEFT OUTER JOIN.

“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…

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

(more…)

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.

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

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.

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!

blogodak blog

Blogodak?

Blogodak je vaš pogled na domaću blogosferu. Prijavite se i napravite sopstvenu listu blogova koje pratite.

O projektu

Podrška

MyCity.co.yu

DevProTalk