Zobrazují se příspěvky se štítkemOracle. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemOracle. Zobrazit všechny příspěvky

úterý 2. února 2016

Oracle DB - tablespace (de)fragmentation tutorial

This article describes how the objects are "physically" stored in Oracle DB. In tutorial is used on VM with preinstalled Oracle DB 12c.

Introduction - datafile structure

Every tablespace is one or group of multiple datafiles. Datafile has 3 levels of configuration
  • File sizing - file size on hard disk, increasing size and max size.
  • Extent management - size of extents etc. (automatic / uniform size)
  • Segment management - automatic (common) / manual (PCT_USED, FREELISTS, GROUPS ... settings is necessary)
Every extent contains blocks (usual 4KiB or 8KiB) which contain rows.
Datafile structure

Tutorial

For this tutorial, connect to db as system (sys as sysdba).

Step 1 - create tablespace with one datafile

Parameters
  • Initial size 30MiB, next 20MiB if needed, maximum of size is 100MB
  • Extent has uniform size 4MiB - it is good for tutorial. Usually use automatic extent management.
  • ASSM - automatic segment space management

define ts = TBS_TEST_DATA
--
-- Create tablespace
--
CREATE TABLESPACE "&ts."
DATAFILE '/home/oracle/test_file01.dbf' SIZE 30M AUTOEXTEND ON NEXT 20M MAXSIZE 100M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 4M
SEGMENT SPACE MANAGEMENT AUTO; --  MANUAL (PCTUSED, FREELISTS, and FREELISTS GROUPS), do not use it

Step 2 - create view TABLESPACE_MAP_VIEW

This view will be used repeately - show you content of tablespace (i.e. datafile):

create view TABLESPACE_MAP_VIEW as
SELECT   'free space' owner, '      ' OBJECT, dfs.file_id, dfs.block_id, dfs.blocks, dfs.blocks*8192/1024/1024 size_In_MB, ddf.FILE_NAME
    FROM dba_free_space dfs, DBA_DATA_FILES ddf
   WHERE dfs.tablespace_name = UPPER ('&ts.') and ddf.file_id = dfs.file_id
UNION
SELECT   SUBSTR (dext.owner, 1, 20), SUBSTR (dext.segment_name, 1, 32), dext.file_id, dext.block_id, dext.blocks, dext.blocks*8192/1024/1024 size_In_MB, ddf.FILE_NAME
    FROM dba_extents dext, DBA_DATA_FILES ddf
   WHERE dext.tablespace_name = UPPER ('&ts.') and dext.file_id = ddf.file_id
ORDER BY 3, 4;

Step 3 - create table TEST_TABLE and check the datafile

First, check tablespace map: select * from TABLESPACE_MAP_VIEW;
Result: 28MB of freespace (3584 blocks):



Now, create table with only one row but allocate initial 16MiB space:

--
-- create tmp table
--
create table TEST_TABLE tablespace TBS_TEST_DATA
storage (initial 16M NEXT 10M
        PCTINCREASE 0
        MINEXTENTS 1
        MAXEXTENTS UNLIMITED)
as
  select rownum id, ao.* from ALL_OBJECTS ao where rownum<2 ; -- 0MB dat


Check the map: select * from TABLESPACE_MAP_VIEW;


You see, there will be allocated 16MB for test table (4 extents with uniform size 4MB). But table is almost empty! Contains only one row!

Step 4 - Insert some data

First, insert cca 13MB: 

--
-- insert 13mb
--
insert into TEST_TABLE
select rownum id, ao.* from ALL_OBJECTS ao; -- 13MB dat
commit;

Check it - nothing changed because of enough space was allocated before:


 And now, insert next 7MB:

--
-- insert 7mb
--
insert into TEST_TABLE
select rownum id, ao.* from ALL_OBJECTS ao where rownum<40000 ; -- 7MB dat
commit;

Check it - rest of freespace was used and next 4MB was allocated (why only 4MB and not 10MB? - db probably rounds sizes)



Step 5 - add second table (GREAT_TABLE)

Add some another table:

--
-- great
--
create table GREAT_TABLE
tablespace TBS_TEST_DATA
storage (initial 4M NEXT 4K
          PCTINCREASE 0
          MINEXTENTS 1
          MAXEXTENTS UNLIMITED)
as
select rownum id, ao.* from ALL_OBJECTS ao; -- cca 14MB data

Check the tablespace map:
  • Datafile was extended to 48MiB (add  cca 20MiB)
  • new table needs 16MiB space


Step 6 - Create "tablespace level" fragmentation for TEST_TABLE

Insert next 7 MB into table, delete second table:

--
-- insert 7mb
--
insert into TEST_TABLE
select rownum id, ao.* from ALL_OBJECTS ao where rownum<40000 ; -- 7MB dat
commit;
-- make a hole
drop table GREAT_TABLE;

See the map:


Again insert:

insert into TEST_TABLE
select rownum id, ao.* from ALL_OBJECTS ao where rownum<40000 ; -- 7MB dat
commit;
The hole will not be filled because of "segment level fragmentation"!!!. Instead new extend will be allocated:



After delete some space...
 
-- delete "random", no space will be free
delete from TEST_TABLE where id < 60000;
commit;
...no space will be free: 


Step 7 - Defragmentation of TEST_TABLE ("tablespace level" and also "segment level" fragmentation)

Check the table block usage:

set serveroutput on;
-- fragmentation in blocks
declare
   v_unformatted_blocks number;
   v_unformatted_bytes  number;
   v_fs1_blocks         number;
   v_fs1_bytes          number;
   v_fs2_blocks         number;
   v_fs2_bytes          number;
   v_fs3_blocks         number;
   v_fs3_bytes          number;
   v_fs4_blocks         number;
   v_fs4_bytes          number;
   v_full_blocks        number;
   v_full_bytes         number;
 begin
   dbms_space.space_usage('SYS',
                          'TEST_TABLE',
                          'table',
                          v_unformatted_blocks,
                          v_unformatted_bytes,
                          v_fs1_blocks,
                          v_fs1_bytes,
                          v_fs2_blocks,
                          v_fs2_bytes,
                          v_fs3_blocks,
                          v_fs3_bytes,
                          v_fs4_blocks,
                          v_fs4_bytes,
                          v_full_blocks,
                          v_full_bytes);
   
   dbms_output.put_line('Unformatted Blocks = ' || v_unformatted_blocks);
   dbms_output.put_line('Unformatted Bytes = ' || v_unformatted_bytes);
   dbms_output.put_line('FS1 Bytes (at least 0 to 25% free space) = ' || v_fs1_bytes);
   dbms_output.put_line('FS1 Blocks(at least 0 to 25% free space) = ' || v_fs1_blocks);
   dbms_output.put_line('FS2 Bytes (at least 25 to 50% free space)= ' || v_fs2_bytes);
   dbms_output.put_line('FS2 Blocks(at least 25 to 50% free space)= ' || v_fs2_blocks);
   dbms_output.put_line('FS3 Bytes (at least 50 to 75% free space) = ' || v_fs3_bytes);
   dbms_output.put_line('FS3 Blocks(at least 50 to 75% free space) = ' || v_fs3_blocks);
   dbms_output.put_line('FS4 Bytes (at least 75 to 100% free space) = ' || v_fs4_bytes);
   dbms_output.put_line('FS4 Blocks(at least 75 to 100% free space)= ' || v_fs4_blocks);
   dbms_output.put_line('Full Blocks in segment = ' || v_full_blocks);
   dbms_output.put_line('Full Bytes in segment  = ' || v_full_bytes);
 end;
Many blocks are fragmented:


Shrinking table makes some data free:
--
-- "release free space" - shrink
--
alter table TEST_TABLE enable row movement;
alter table TEST_TABLE shrink space;
Alter table TEST_TABLE shrink space cascade;
alter table TEST_TABLE disable row movement;
 -- deallocate unused extents
ALTER TABLE TEST_TABLE DEALLOCATE UNUSED;

Table is almost defragmented (one block is 50% to 75%)

See the map:

 
Defragmentation by move storage. Init 16MiB for new extents:

-- "free space" - move to new extents
--
alter table TEST_TABLE move
storage (initial 16M NEXT 10M
          PCTINCREASE 0
          MINEXTENTS 1
          MAXEXTENTS UNLIMITED);
Result of block usages:

 Move storage contains init size (in this case 16MB), therefore 4 extents are allocated. And also first 8MB are free because there was the table stored before move:

"Move storage" benefits:
  • choose some parameters similar to table creation (init size etc...)
  • better "block level" defragmentation
  • should be fast 
"shrink" benefits:
  • less capacity (does not create new extends)
  • in some cases better "extent level" defragmentation

Step 8 - cleanup

--
-- DROP
--
drop table TEST_TABLE;
drop table GREAT_TABLE;
DROP TABLESPACE "&ts." INCLUDING CONTENTS AND DATAFILES;

pátek 15. ledna 2016

Pre-Built Oracle Database 12c in VirtualBox

Every developer sometimes needs full-featured database for testing purposes. Developer has two typical choices:
  • To use shared database installed on company servers - He does not care about installation, administration etc but during his experiments he can make this database instance unstable and cause all team-mates angry:) Developer cannot also do some administration tasks because of he has no access to system privileges. System access to database is in the competence of DBA department.
  • To use it's own database installed on his desktop locally - In this case must be developer able to install database from scratch: This is magical and boring task.
Therefore Oracle prepared various set of pre-builded VMs where the installation is easy. For application developers is suitable to use "Database App Development VM". This image has quite small footprint (2GB RAM, can be downgraded to 1.7GB) and contains only necessary tools.

This post shows you step by step how to install this image and use database from outside VM (yor desktop OS) with minimal effort:
  1. Download and install virtual box from official page

  2. Download Pre-Built Developer VM from Oracle named "Database App Development VM" from http://www.oracle.com/technetwork/community/developer-vm/index.html#dbapp

  3. Import Database App Development VM into VirtualBox
    1. Import appliance (Ctrl-I) or (menu > File > Import appliance). Select .ova file. Next button.



    2. Dialog Appliance Settings: No changes. Just press import button,

    3. Add "vboxnet" for your global VirtualBox setting: Press Ctrl+G, Choose Network, Choose Host-only Networks, Add button, set Ip addess and mask (192.168.57.1, 255.255.255.0).



    4. DO NOT CLOSE YET THE DIALOG. Switch to DHCP Server tab, enable it and configure it according to picture. Now, you can close:).



    5. Configure VM - set network adapter 1 as vboxnet : Choose Oracle DB VM, Press Settings, Choose Network, Choose Adapter no 1. Set Host-only Adapter (which was created in previous step).



  4. Start Oracle DB VM

    1. Disable oracle REST services for less memory consumption in VM. (This is java process and takes cca 300MB RAM) :

      1. Open terminal and execute "chmod -x ./ords.sh". Restart VM
      2. Check if process is not running by executing in terminal "ps aux | grep ords.war"



  5. Connect to database running inside VM from your desktop system via sqldeveloper or another client:



Summary:

Pre-built VM image is more or less a black-box which is not consuming so much resources on developer's desktop. You can quit fast re-create whole VM when something goes wrong and because of it comes from oracle, you can find another guides and advices what to do with it.



středa 11. března 2015

Práce s časem v Oracle databázi

Ve třetí části série článků o relačních databázích si ukážeme základy práce s časem.
 Databáze poskytuje mnoho funkcí pro práci s časem, v této kapitole se však budeme zabývat jen tím, jak čas a datum získat. Protože problémy způsobují časové zóny, rovněž se zmíním i o této problematice.

V Oracle databázi máme dva časové zdroje: systémový čas a databázový čas.

Sytémový čas


Máme dotaz:

select sysdate, systimestamp, SYS_EXTRACT_UTC(SYSTIMESTAMP) utc from dual;

Výše uvedený dotaz vrací čas operačního systému:

SYSDATE             SYSTIMESTAMP                        UTC                       
------------------- ----------------------------------- ----------------------------
03.03.15 13:26:41   03.03.15 13:26:41,365645000 +01:00  03.03.15 12:26:41,365645000 



Rozdíl mezi sysdate a systimestamp není jen v přesnosti. Důležité je, že sysdate neobsahuje informaci o časové zóně. V okamžiku volání sysdate se aktuální zóna "aplikuje" do hodnoty a ta se pak vrátí v dotazu. Takto zýskaný a ukládány čas může způsobit obrovské problémy:

Příklad
Představte si, že Vaše aplikace vkládá do sloupečku hodnotu SYSDATE pro zaznamání vzniku řádku a db server běží v Praze. Pokud db server přesune do Austrálie - nově vzniklé hodnoty budou ukládány s aplikovaným časovým posunem +11 ale staré hodnoty byly uloženy např. s posunem +2. Pokud tedy vznikly dva řádky v rozmezí 1 minuty ale v jiných zónách (+11 a +2), výpočty nad těmito časy (např. doba mezi vložením dvou záznamů) nebudou odpovídat realitě.

Jak tedy správně ukládat čas (a datum) v databázi? Existují 2 způsoby:
  • Záznam bude uložen včetně časové zóny a pro zjištění se užije SYSTIMESTAMP
  • Záznam bude uložen v UTC (bez časového posunu, +0h).
Právě druhý zminovaný způsob je šetrný na diskový prostor a často i na výkon. K získání času v UTC je ukázáno v třetím sloupečku předchozího příkladu, tedy SYS_EXTRACT_UTC(SYSTIMESTAMP). Nyní je jedno, ve které časové zóně se server nachází, všechny časy budou v UTC.

Pro práci s časem se může hodit časová zóna operačního systému:

select to_char(SYSTIMESTAMP,'TZR') timezone from dual;

Výslekek je pak například

 TIMEZONE                     
--------------------------------
+01:00     


Databázový čas 


S databázovým časem  se pracuje podobně jako se systémovým časem. Hlavní rozdíl je v možnosti nastavení časových zón platných v rámci databáze (tedy ne pro celý operační systém) nebo pro jedno sezení (session).

Analogický dotaz k systémovému času

select CURRENT_DATE,CURRENT_TIMESTAMP,SYS_EXTRACT_UTC(CURRENT_TIMESTAMP) utc from dual;

Výsledek je pro tentokrát zcela totožný se systémovým časem:

 CURRENT_DATE        CURRENT_TIMESTAMP                   UTC                      
------------------- ----------------------------------- ----------------------------
03.03.15 14:10:41   03.03.15 14:10:41,411721000 +01:00  03.03.15 13:10:41,411721000  


Stejne tak zjištění časové zony databáze (aktuálního sezení)

select SESSIONTIMEZONE timezone from dual;

Oproti systémovému času si můžeme nyní časovou zónu upravit podle potřeby:

ALTER SESSION SET TIME_ZONE = '+11:0'; 

Nastavíme si časový posun +11 hod a okamžitě zkusíme opět dotaz k získání času databáze. Můžeme porovnat výsledky:

CURRENT_DATE        CURRENT_TIMESTAMP                   UTC                       
------------------- ----------------------------------- ----------------------------
04.03.15 00:15:23   04.03.15 00:15:23,064275000 +11:00  03.03.15 13:15:23,064275000  


Zatímco UTC čas se nezměnil, hodnota CURRENT_DATE a CURRENT_TIMESTAMP se změnila. U hodnoty CURRENT_TIMESTAMP nám to ovšem nevadí, časová zóna je je součástí hodnoty. Zato však CURRENT_DATE nám bude vracet jiné hodnoty, které (vysvětleno výše na příkladu) nesmí být smýchány s hodnotami před změnou časové zóny.

Závěr

V databázi existuje pochopitelně nepřeberné množství funkcí pro práci s časem. Účelem tohoto článku bylo jen naťuknout tuto problematiku a poukázat na nejpalčivější problém týkající se časových zón. Nyní je již vše na samotném čtenáři, jak se tohoto tématu chopí:) 
Času zdar.



úterý 3. března 2015

Tabulka dual

Z mých zkušeností zná tuto tabulku každý databázový vývojář a v podstatě žádný Java/ORM vývojář, což není překvapující - pokud programujete přímo v databázi, některé konstrukce nejsou bez této tabulky zbytečně obtížné, ne-li nemožné. Pro programátora užívající ORM pak "ztácí" tabulka význam. Slovo "ztrácí" je v uvozovkách oprávněně: Na běžnou práci v ORM skutečně tabulka není potřeba. Pokud chceme databázi používat efektivně a nebo jsme nuceni volat některé databázové funkce přímo, tabulka se nám náramě hodí. 

Tabulka dual je tabulka vlastní všem Oracle databázím a obsahuje typicky  jeden sloupec jménem DUMMY a jeden řádek s hodnotou 'X' typu VARCHAR2(1).
select * from dual;

Proč je tedy tak důležitá? Pomocí této tabulky lze libovolnou hodnotu, literál či výstup funkce převést do relace - t.j. tabulky.

na příklad:

select 'hello world' from dual;
select 1+1 from dual;
select sysdate from dual;

Všechny tyto příklady mají jednu věc společnou - vytvářejí z "ničeho" tabulku. Velmi často se tabulka hodí pro volání databázových funkcí. 

select 1+9/4, trunc(1+9/4),DBMS_RANDOM.RANDOM from dual;

Dotaz ukazuje volání funkce "trunc", jež slouží oříznutí desetinné části z čísla a zároveň volá funkci pro generování náhodného čísla.

Výsledek dotazů je pak třísloupcová tabulka:

1+9/4 TRUNC(1+9/4) RANDOM
----- ------------ ------
 3,25            3 610212023


Z předchozích příkladů je patrný význam tabulky dual: slouží nám jako jakýsi můstek mezi konvenčním procedurálním a relačním přístupem. Článek ukázal nejzákladnější použití tabulky. V dalších dílech bude tabulka využita v mnohem větší míře a její účel bude pak jasnější. Tak zase příště.


pondělí 27. října 2014

Relace a teorie relačních databází

Vítejte v prvním díle ze série kratkých článků o relačních databázích. Seriál je určen především pro vývojáře používající ORM, kteří nemají hlubší znalosti o relačních databázích.
Je třeba ještě zmínit, že v rámci zjednodušení a zrychlení výkladu se můžou v textu vyskytnout drobné formální nedokonalosti či nepřesnosti. Berte proto, prosím, uvedené teorie s nadhledem:)

Pěkně od začátku


Mějme nějakou běžnou, obyčejnou aplikaci:

Tato aplikace se skládá z několika částí:
  • UI - (uživatelské) rozhranní (WEB, GUI, WebServices apod.)
  • BL - business logika a datový model (který musí být persistentní)
  • ORM - vrstva ORM (framework, např. Hibernate)
  • RDB - relační databáze, úložište pro aplikaci
 A tato aplikace může řešit například evidenci zaměstnanců. Její zjednodušený datový model vypadá proto takto:

Nyní nastává ta správná otázka. Jak je v obrázku zakreslena relace (z pohledu relační databáze)?

Pokud je odpověď "relace je přece ta vidlička mezi tabulkama, ten vztah 1 ku N mezi entitami ....", čtěte dále, odpověď není zcela správná.

Proč? provedli jste záměnu dvou relativně podobných (nikoli totožných) pojmů:
  • Pojem "relation", jehož význam se chápe jako přirozený "vztah mezi subjekty" a který vnukne představu "vidličky" v modelu.
  • Pojem "relation", který se běžně překládá jako relace a který se užívá v matematice v teorii množin.
a právě relační databáze vychází z druhého uvedého pojmu. Než se posuneme k relačním databázím, bude vhodné si drobné základy z teorie množin připomenout.

Teorie množin

 

Z teorie množin si velmi lehce rozeberem čtyři pojmy:
  • množina
  • uspořádaná n-tice
  • kartézský součin
  • relace

Množiny není nutné nějak hluboce rozebírat. Mějme např. tyto možiny:
  • A = {“karel”, ”franta”, “pepa”}
  • B = {”franta”, “pepa”, “karel”}
  • C = {“karel”, “pepa”, 1,2}
  • D = {“karel”, “pepa”, 1,1,2}
S množinami je možné provádět různé operace (sjednocení, průnik...), možiny jsou navzájem disjunktní, konjuktní atd. atd.

Důležité jsou však dvě vlastnosti obecných množin:
  • Nezáleží na pořadí prvků v množině (tedy platí A=B).
  • Každý prvek může být v množině max. jednou (tedy platí C=D).
A zde se dostáváme k uspořádaným n-ticím:
Uspořádaná n-tice vypadá na první pohled jako klasická množina, oproti výše popsané množině má právě tyto speciální vlastnosti:
  • Záleží na pořadí prvků v množin.
  • Každý prvek se může v n-tici opakovat.
 Proto pokud bychom měli tyto uspořádané n-tice (zapisované v hranatých závorkách)
  • A = [“karel”, ”franta”, “pepa”]
  • B = [”franta”, “pepa”, “karel”]
  • C = [“karel”, “pepa”, 1,2]
  • D = [“karel”, “pepa”, 1,1,2]
tak v porovnání s množinám již neplatí rovnost A a B, a C a D, což se nám hodí pro vysvětlení dalšího pojmu: kartézský součin.

Kartézksý součin lze poměrně složitě definovat, pro jedoduchost ho popíšem slovně selským rozumem a příkladem:

Kartézksý součin dvou množin A a B je množina uspořádaných dvojic vytvořená jako "každý prvek z A s každým prvkem B".


Příklad 1 (z wikipedie):
pokud A = {x, y, z} a B = {1, 2, 3} pak 
AxB = { [x,1],[x,2],[x,3],[y,1],[y,2],[y,3],[z,1],[z,2],[z,3] }



Další praktičtější příklad (rovněž z wikipedie), který popisuje hrací karty:  
  • A = { sedma, osma, devítka, desítka, spodek, svršek, král, eso} 
  • B = { srdce, listy, kule, žaludy }

Výsledek: 
A × B = {  [sedma,   srdce   ],
       [sedma,   listy   ],
       [sedma,   kule    ],
       [sedma,   žaludy  ],
       [osma,    srdce   ],
        …,
       [eso,     kule    ],
       [eso,     žaludy  ]}.
 
Jak je vidět, kartézský součin nám v tomto případě definoval celý hrací balíček karet, ve kterém je jedna karta tvořená uspořádanou dvojcí [číslo, barva].

Ted je čas na poslední zajímavý pojem, pojem jež dal relačním databázím jméno - relace. Definice je velice jednoduchá a zní:

Relace je podmožina kartézského součinu.
 

 

Samo o sobě to nezní užitečně, ovšem můžem si ukázat nějaké příklady relace z kartézským součinu vytvořeného v předchozím příkladu:

R1 = { [sedma,   srdce    ],
       [devítka, žaludy   ], 

       [svršek,  kule     ]} 

R2 = { [sedma,   srdce    ],
       [devítka, žaludy   ],
       [svršek,  žaludy   ],
       [desítka, kule     ],
       [eso,     kule     ]}

Takto definované relace nám můžou představovat jakoukoliv část balíčku (například karty hráče, talón či nerozdané karty). Důležité je, že relace je množina, takže s ní můžeme formálně provádět operace jako sjednocení. odečtení, porovnání apod.

Pokud se podíváme na relace R1 a R2 příkladu karetních her, možná nám nápadně pripomínají ještě něco - ano, tabulky. Pověstné tabulky které jsou srdcem všech relačních databází, tabulkových procesorů a kostičkových papírů. Relace R1 i R2 vypadají jako tabulky, buď dvě různé a nebo se může jednat o jednu a tu samou tabulku v jiném čase. 

Nyní je čas se podívat zpátky k úvodní otázce ze začátku kapitoly: Jak je v obrázku zakreslená relace (z pohledu relační databáze)? Odpověď je tedy "tabulkou". Již zmíněné "vydličky", tedy vztahy mezi tabulkami, nejsou v původním slova smyslu relace.



Teorie relačních databází, relační algebra


K plnému využití relačních databází je nutné pochopit, na jakém principu byly tyto databáze postaveny. V předchozí části jsme si ukázali, z jakého matematického základu relační databáze čerpají. Nyní se posuneme z matematické teorie do teorie relačních databází.

Základy relačních databází definoval pan Edgar F. Codd kolem roku 1970 ve své práci "A Relational Model of Data for Large Shared Data Banks". V této práci formalizoval relační model, relace (tabulky) a  definoval tzv. relační algebru.


Nemá smysl zacházet příliš do hloubky, je však vhodné uvést operátory relační algebry, které se používají pro práci s relacemi:
  • Selection (výběr, selekce)
  • Projection (projekce)
  • Inner and outer joins (sjednocení)
  • Division (rozdíl)
  • Cartesian product (kartézský součin)
  • Rename (přejmenování )
Vstupem do operátoru jsou relace, výstupem jsou (to je velice důležité) rovněž relace. Díky tomu lze operátory a relace libovolně skládat a řetězit stejně, jako jsme zvyklí u běžných matematických operátoru a vytvořit komplexní výrazy.

Relační algebra je implementována v relační databázi a zapisuje se pomocí SQL takto:

select <projection>
from   <relation>,<relation>… (kartézský součin)
where  <selection>
inner/outer join <relations>
union  <relation> 


Jak je vidět, každý sql dotaz se v databázi interpretuje jako sada relačních operátorů nad tabulkami (relacemi), kde výsledkem je opět relace. SQL dotazy lze tedy libovolně skládat, používat několikásobně vnořené selekty a vůbec provádět všeljaká kouzla.

Závěr


Ukázali jsme si základy teorie množin a relačních databází, čímž jsme si otevřeli cestu do praxe. V dalších dílech se objeví ukázky, které uvedenou teorii maximálně využijí. Příkady budou psány pro databízi Oracle, ale principiálně fungují stejně téměř ve všech relačníc databázích. Tak si je nenechte ujít:)

David