You are on page 1of 176

UF2-

UF2-M02. Gestió de Bases de Dades


1ASIX
UF1 – M10. Adminsitració de Bases de Dades

INS Bosc de la Coma | 2011/2012


Sistemes gestors de bases de dades relacionals
Apunts

Autor: Marc Nicolau Reixach


Adaptació: Úrsula Heredia Garcia

Data creació: Agost de 2007


Darrera modificació: Agost de 2008

Aquest document està subjecte a una llicència de Reconeixement-


No comercial-Compartir Igual 3.0 Espanya de Creative Commons
Continguts

Continguts

Llenguatge SQL
1. DML SQL
2. DDL SQL
3. Transaccions i concurrència

SQL hostatjat
1. SQL hostatjat amb Oracle PL/SQL
2. Disparadors

Àlgebra relacional
1. Operacions amb àlgebra relacional

Annex I. SGBD Oracle. Eines.

Annex II. Dades de treball

ii
Llenguatge SQL
Estudi del llenguatge ANSI SQL. Utilització del
llenguatge SQL en el SGBDR Oracle.
Contingut

Contingut
Capítol 1. Introducció a SQL ....................................................................................3
1.1. Història d’SQL ............................................................................................................................ 3
1.1.1. Introducció ...................................................................................................................... 3
1.1.2. Versions .......................................................................................................................... 3
1.2. Modes d’utilització ...................................................................................................................... 3
1.3. Elements del llenguatge SQL ..................................................................................................... 4
Capítol 2. DML SQL..................................................................................................6
2.1. Consulta de dades sobre una taula............................................................................................ 6
2.1.1. Sintaxi ............................................................................................................................. 6
2.1.2. Ús d’ÀLIES...................................................................................................................... 8
2.1.3. Càlculs ............................................................................................................................ 8
2.1.4. Condicions de selecció ................................................................................................. 11
2.1.5. Ordenació ..................................................................................................................... 17
2.1.6. Funcions ....................................................................................................................... 19
2.1.7. Agrupacions .................................................................................................................. 34
2.2. Consulta de dades sobre vàries taules .................................................................................... 37
2.2.1. Introducció .................................................................................................................... 37
2.2.2. Producte cartesià de taules .......................................................................................... 38
2.2.3. Combinació de taules ................................................................................................... 40
2.2.4. Obtenir registres que no estan relacionats ................................................................... 42
2.2.5. Auto combinacions........................................................................................................ 43
2.2.6. Sintaxi SQL 1999 .......................................................................................................... 43
2.2.7. Subconsultes ................................................................................................................ 47
2.2.8. Operadors de conjunts.................................................................................................. 53
2.3. Inserció, modificació i eliminació .............................................................................................. 55
2.3.1. Introducció .................................................................................................................... 55
2.3.2. Inserció de dades.......................................................................................................... 55
2.3.3. Modificació de dades .................................................................................................... 58
2.3.4. Eliminació de dades...................................................................................................... 60
2.3.5. Utilització dels valors per defecte.................................................................................. 61
Capítol 3. DDL SQL ................................................................................................62
3.1. Introducció a les sentències de definició .................................................................................. 62
3.1.1. Introducció .................................................................................................................... 62
3.1.2. Creació i esborrat d’una BDR ....................................................................................... 62
3.1.3. Objectes de BD............................................................................................................. 63
3.2. Definició del nivell conceptual: taules i restriccions .................................................................. 63
3.2.1. Creació de taules .......................................................................................................... 64
3.2.2. Modificar l’estructura de taules ..................................................................................... 70
3.2.3. Eliminar l’estructura de taules ....................................................................................... 73
3.2.4. Canviar el nom de taules (Oracle) ................................................................................ 74
3.2.5. Esborrar el contingut d’una taula (Oracle) .................................................................... 74
3.2.6. Restriccions .................................................................................................................. 74
3.3. Definir el nivell intern: índexs.................................................................................................... 85
3.3.1. Introducció .................................................................................................................... 85
3.3.2. Creació d’índexs ........................................................................................................... 86
3.3.3. Índexs basats en funcions ............................................................................................ 87
3.3.4. Llistar els índexs ........................................................................................................... 87
3.3.5. Esborrar índexs............................................................................................................. 87
3.4. Definició del nivell extern: vistes............................................................................................... 87
3.4.1. Introducció .................................................................................................................... 87
3.4.2. Creació de vistes .......................................................................................................... 88
3.4.3. Llistar les vistes............................................................................................................. 90
3.4.4. Esborrar vistes .............................................................................................................. 90
3.5. Definir altres objectes de la base de dades.............................................................................. 91
3.5.1. Introducció .................................................................................................................... 91
3.5.2. Seqüències ................................................................................................................... 91
3.5.3. Sinònims ....................................................................................................................... 94
Capítol 4. Transaccions i concurrència ..................................................................96
4.1. Gestió de transaccions ............................................................................................................. 96
4.1.1. Introducció .................................................................................................................... 96
4.1.2. Transaccions................................................................................................................. 96
4.2. Gestió de la concurrència......................................................................................................... 98
4.2.1. Consistència de lectura................................................................................................. 99
4.2.2. Bloqueig...................................................................................................................... 100

ii
UD2. Llenguatge SQL Introducció a SQL

Capítol 1. Introducció a SQL


1.1. Història d’SQL

1.1.1. Introducció

L’any 1970, Codd va introduir el concepte de Base de Dades Relacional, però va portar
un temps el disseny d’un sistema real de gestió de bases de dades relacional (SGBDR o
RDMBS). El primer i que es recorda més és System R (dissenyat per IBM), el qual no
era més que un prototipus, l’objectiu principal del qual era demostrar que amb aquest
sistema era possible construir un Sistema Relacional, que es podia utilitzar en un entorn
real, per solucionar problemes reals. No obstant, va ser Oracle qui el va introduir per
primera vegada en un programa comercial (1979).
Aquest sistema incorporava un llenguatge de dades que permetia fer qualsevol accés a
la base de dades, que es va anomenar SEQUEL (Structured English Query Language).
Posteriorment altres sistemes van adoptar aquest subllenguatge, que es va passar a
anomenar SQL, com a subllenguatge de consulta de dades, que fins avui dia ha patit
diverses modificacions.
La seva utilització dins l’àmbit comercial és realment extensa. Les cases comercials
l’inclouen dins els seus productes i és l’estàndard més important en aquest camp.
SQL és una abreviació de “Structured Query Language” (llenguatge de consulta
estructurat). Amb aquest llenguatge es poden crear operacions relacionals, és a dir,
operacions que permeten definir i manipular una base de dades relacional.

1.1.2. Versions

ANSI SQL ha patit varies revisions al llarg del temps:


Any Nom Àlies Comentaris
Primera publicació feta per ANSI. Confirmada per ISO
1986 SQL-86 SQL-87
l’any 1987.
1989 SQL-89 SQL1 Revisió i ampliació menor.
Àmplia revisió i ampliació. És la versió més estesa en
1992 SQL-92 SQL2
els SGBDR comercials.
Es van afegir expressions regulars, consultes
1999 SQL:1999 SQL2000 recursives (per relacions jeràrquiques), triggers i
algunes característiques orientades a objectes.
Introdueix algunes característiques de XML, canvis en
2003 SQL:2003 les funcions, estandardització de l’objecte SEQUENCE
i de les columnes auto numèriques.
Defineix la forma amb la que SQL es pot utilitzar
conjuntament amb XML. Defineix com importar i
2006 SQL:2006 guardar dades XML a una base de dades SQL,
manipulant-les dins de la base de dades i publicant el
XML i les dades SQL convencionals en forma de XML.

Nosaltres estudiarem SQL-92. Per tant, quan parlem del llenguatge SQL, ens estarem
referint a la versió SQL-92. En els casos en que es parli de característiques pròpies de
versions posteriors, ja s’indicarà.

1.2. Modes d’utilització

3
UD2. Llenguatge SQL Introducció a SQL

El llenguatge SQL pot utilitzar-se de diferents formes:


Execució directa (també anomenat SQL interactiu)
En aquest cas, les sentències SQL s’introdueixen mitjançant una eina que les tradueix
immediatament a la base de dades, i per tant, s’executen a l’instant.
Execució incrustada o submergida
Les sentències SQL es col·loquen com a part del codi d’un altre llenguatge (C, Java,
Pascal, etc.). Aquestes comandes estan separades de la resta del codi d’una certa
forma. Quan es compila el codi s’utilitza un precompilador de la pròpia base de dades
que separa les instruccions del llenguatge de programació de les del llenguatge SQL.
Una alternativa a aquesta forma de treballar són les rutines SQL/CLI (SQL/Call-Level
Interface), que es van afegir a l’estàndard SQL92 l’any 1995. En aquest cas, també
permeten utilitzar el llenguatge SQL des d’un llenguatge de programació, però sense
necessitat de precompilador.
Cal tenir present que tot i ser el llenguatge estàndard per bases de dades relacionals,
SQL no reflexa tota la teoria del model relacional establerta per E.F. Codd.

1.3. Elements del llenguatge SQL

A part d’un llenguatge de consulta, en realitat el llenguatge SQL és molt més que això, ja
que té altres funcions a més a més de les de consultar una base de dades. Entre
aquestes hi ha:
DDL. Llenguatge de definició de dades.
DML. Llenguatge de manipulació de les dades.
DCL. Llenguatge de control de dades. Permet indicar restriccions d’accés i seguretat.
A continuació veurem per sobre com fer aquestes tasques, amb varis exemples:

4
UD2. Llenguatge SQL Introducció a SQL

Crear una taula (comanda DDL) que contingui les dades dels productes de l’empresa:
CREATE TABLE producte Nom de la taula
(
codi INTEGER,
nom CHAR(20),
tipus CHAR(20), Nom de les columnes i tipus (domini)
descripcio CHAR(50),
preu REAL,
PRIMARY KEY (codi) Clau primària
);

Inserir (comanda DML) un producte nou a la taula:


Nom
INSERT INTO de la taula
producte
VALUES (1250, ‘LENA’, ‘taula’, ‘Disseny Joan Pi. Any 1920.’, 2500);

Valors
Consultar (comanda DML) quins productes són de la fila
cadires:
Nom de la taula
Columnes
SELECT seleccionades
codi, nom
FROM producte
WHERE tipus = ‘cadira’;

Files seleccionades

Deixar accedir (comanda DCL) a un dels venedors de l’empresa a la informació de la


taula producte:
Fer consultes
Usuari
GRANT SELECT ON producte TO jmontserrat;

Nom de la taula
Les operacions a SQL reben el nom de sentències i estan formades per diferents parts
anomenades clàusules.

SELECT codi, nom Clàusula


Sentència

FROM producte Clàusula


WHERE tipus = ‘cadira’; Clàusula

A més de sentències i clàusules, el llenguatge SQL té els següents elements:


Operadors: permeten crear expressions complexes.
Ex: op. aritmètics +, -, *, /, etc.
Ex: op. lògics >,<, >=, <=, <>, =, AND, OR, NOT, etc.
Funcions: permeten obtenir valors complexes
Ex: SUM(), AVG(), COUNT(), etc.
Constants: valors constants per les consultes, números, textos, caràcters, etc.
Dades: obtingudes de la pròpia base de dades.

Quan escrivim sentències del llenguatge SQL, cal tenir present que hi ha unes normes
d’escriptura:
No hi ha distinció entre majúscules i minúscules.
Una sentència sempre acaba amb el símbol ;
Les sentències SQL es poden escriure en vàries línies per facilitar-ne la lectura (molt
recomanable!!)
Per incloure comentaris en el codi SQL, aquests es posen entre /* i */.

5
UD2. Llenguatge SQL DML SQL

Capítol 2. DML SQL


2.1. Consulta de dades sobre una taula

Sens dubte el comandament més utilitzat de llenguatge SQL és el comandament


SELECT. Aquest comandament permet:
 Obtenir dades de certes columnes d’una taula (projecció).
 Obtenir registres (files) d’una taula que compleixen certs criteris (selecció).
 Combinar dades de taules diferents (combinació, join).
 Amb aquesta instrucció l’usuari especifica QUÈ és el que vol obtenir, no ON
ni COM.
 L’usuari pot realitzar sentències SELECT de diferents nivells de complexitat.
 Les dades poden ser representades en un ordre determinat.

2.1.1. Sintaxi

SELECT * | {[DISTINCT] columna | expressió, ...}


FROM taula;

On:
 SELECT s’utilitza per determinar les columnes que es volen obtenir.
 FROM especifica una llista de taules que s’utilitzen a la consulta.
 * significa que se seleccionen totes les columnes.
 DISTINCT fa que no es mostrin els valors duplicats.
 columna. És el nom d’una columna de la taula que es vol mostrar.
 expressió. És una expressió SQL vàlida (una operació, una funció de
totals, etc.)

6
UD2. Llenguatge SQL DML SQL

Exemple 1

Seleccionar tots els números de departament de la taula DEPT:


SQL> select dept_num from dept;

DEPT_NUM
---------
10
20
30
40

Exemple 2

Seleccionar totes les columnes de la taula DEPT:


SQL> select * from dept;

DEPT_NUM DEPT_NOM DEPT_LOC


--------- -------------- -------------
10 Comptabilitat Sevilla
20 Investigacio Madrid
30 Vendes Barcelona
40 Produccio Bilbao

Exemple 3

Seleccionar la columna emp_dept_num de la taula EMPL.


SQL> SELECT empl_dept_num
2 FROM empl;

EMPL_DEPT_NUM
-------------
20
30
30
20
30
30
10
20
10
30
20
30
20
10

14 rows selected.

7
UD2. Llenguatge SQL DML SQL

Exemple 4

Seleccionar els diferents departaments on hi ha empleats:


SQL> SELECT DISTINCT empl_dept_num
2 FROM empl;

EMPL_DEPT_NUM
-------------
10
20
30

2.1.2. Ús d’ÀLIES

Quan es consulta una taula, els noms de columnes s’utilitzen com a capçaleres de
presentació. Si aquests noms són massa llargs o críptics es poden canviar amb la
mateixa sentència SQL de consulta, creant un ALIES.

Sintaxi

SELECT columna “alies” | columna AS alies


FROM taula

Com es pot veure tenim dues maneres de definir un àlies:


 Posant entre cometes dobles un nom d’àlies després de la columna. En
aquest cas es respecten les majúscules i minúscules a l’hora de mostrar el títol
de la columna.
 Indicant el nom de l’alies sense cometes dobles després de la clàusula AS que
va després de la columna. D’aquesta forma, el títol de columna sempre es
mostra amb majúscules.

2.1.3. Càlculs

Aritmètics

Els operadors + (suma), - (resta), * (multiplicació) i / (divisió), es poden utilitzar per fer
càlculs a les consultes. Quan s’utilitzen com expressió en una consulta SELECT, no
modifiquen les dades originals sinó que com a resultat de l’execució del SELECT,
apareix una columna amb el resultat de l’expressió.
La prioritat d’aquests operadors és:
tenen més prioritat la multiplicació i divisió,
després la suma i la resta.
En cas d’igualtat de prioritat es realitza primer la operació que estigui més a l’esquerra
(associativitat per l’esquerra).
Com és lògic, es pot evitar complir aquesta prioritat utilitzant parèntesis; l’interior dels
parèntesis és el que s’executa primer.
Quan una expressió aritmètica es calcula sobre valors NULL, el resultat de l’expressió és
sempre NULL.
Exemple:
SQL> SELECT empl_num, empl_nom, empl_salari, empl_salari*2
2 FROM empl ;

8
UD2. Llenguatge SQL DML SQL

EMPL_NUM EMPL_NOM EMPL_SALARI EMPL_SALARI*2


---------- ---------------- ----------- -------------
7369 SANCHEZ 104000 208000
7499 ARROYO 208000 416000
7521 SALA 162500 325000
7566 JIMENEZ 386750 773500
7654 MARTIN 182000 364000
7698 NEGRO 370500 741000
7782 CEREZO 318500 637000
7788 GIL 390000 780000
7839 REY 650000 1300000
7844 TOVAR 195000 390000
7876 ALONSO 143000 286000
7900 JIMENO 123500 247000
7902 FERNANDEZ 390000 780000
7934 MUNOZ 169000 338000

14 rows selected.

Aquesta consulta obté tres columnes. Com es pot veure, la tercera té com a títol,
l’expressió utilitzada. És en aquests casos quan és més freqüent la utilització d’alies.
Exemple:
SQL> SELECT empl_num, empl_nom, empl_salari,
2 empl_salari*2 as doble_salari
3 FROM empl;

EMPL_NUM EMPL_NOM EMPL_SALARI DOBLE_SALARI


---------- ---------------- ----------- ------------
7369 SANCHEZ 104000 208000
7499 ARROYO 208000 416000
7521 SALA 162500 325000
7566 JIMENEZ 386750 773500
7654 MARTIN 182000 364000
7698 NEGRO 370500 741000
7782 CEREZO 318500 637000
7788 GIL 390000 780000
7839 REY 650000 1300000
7844 TOVAR 195000 390000
7876 ALONSO 143000 286000
7900 JIMENO 123500 247000
7902 FERNANDEZ 390000 780000
7934 MUNOZ 169000 338000

14 rows selected.

Els noms d’alies poden portar espais si es posen entre cometes dobles:
SQL> SELECT empl_num, empl_nom, empl_salari,
2 empl_salari*2 as "doble salari"
3 FROM empl;

EMPL_NUM EMPL_NOM EMPL_SALARI doble salari


---------- ---------------- ----------- ------------
7369 SANCHEZ 104000 208000
7499 ARROYO 208000 416000
7521 SALA 162500 325000
7566 JIMENEZ 386750 773500
7654 MARTIN 182000 364000
7698 NEGRO 370500 741000
7782 CEREZO 318500 637000

9
UD2. Llenguatge SQL DML SQL

7788 GIL 390000 780000


7839 REY 650000 1300000
7844 TOVAR 195000 390000
7876 ALONSO 143000 286000
7900 JIMENO 123500 247000
7902 FERNANDEZ 390000 780000
7934 MUNOZ 169000 338000

14 rows selected.

Concatenació

L’operador || és el de la concatenació. Serveix per unir textos.


Exemple:
SQL> select empl_num || ' - ' || empl_nom "Numero i Nom"
2 from empl;

Numero i Nom
-----------------------------------------------------------
7369 - SANCHEZ
7499 - ARROYO
7521 - SALA
7566 - JIMENEZ
7654 - MARTIN
7698 - NEGRO
7782 - CEREZO
7788 - GIL
7839 - REY
7844 - TOVAR
7876 - ALONSO
7900 - JIMENO
7902 - FERNANDEZ
7934 - MUNOZ

14 rows selected.

10
UD2. Llenguatge SQL DML SQL

2.1.4. Condicions de selecció

Es poden realitzar consultes que filtrin les dades de sortida de les taules. Per això
s’utilitza la clàusula WHERE. Aquesta clàusula permet col·locar una condició que han de
complir tots els registres, els que no la compleixin no apareixeran en el resultat.
Exemple: Seleccionar el número, nom i ofici dels empleats.
SQL> select empl_num, empl_nom, empl_ofici
2 from empl;

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7369 SANCHEZ EMPLEAT
7499 ARROYO VENEDOR
7521 SALA VENEDOR
7566 JIMENEZ DIRECTOR
7654 MARTIN VENEDOR
7698 NEGRO DIRECTOR
7782 CEREZO DIRECTOR
7788 GIL ANALISTA
7839 REY PRESIDENT
7844 TOVAR VENEDOR
7876 ALONSO EMPLEAT
7900 JIMENO EMPLEAT
7902 FERNANDEZ ANALISTA
7934 MUNOZ EMPLEAT
14 rows selected.

Exemple: Seleccionar el número, nom i ofici dels empleats que són directors.
SQL> select empl_num, empl_nom, empl_ofici
2 from empl
3 Where empl_ofici='DIRECTOR';

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7566 JIMENEZ DIRECTOR
7698 NEGRO DIRECTOR
7782 CEREZO DIRECTOR

Sintaxi

SELECT columna “alies” | columna AS alies [,mesColumnes]


FROM taula
WHERE condició

La clàusula WHERE sempre es col·loca després de la llista de taules de la clàusula


FROM.
La condició serà una expressió booleana que s’avaluarà i que permetrà cercar totes les
files que la compleixen. Aquesta expressió pot ser molt complexa i es poden utilitzar
múltiples operadors en la seva construcció.

11
UD2. Llenguatge SQL DML SQL

Operadors de comparació

Es poden utilitzar en la clàusula WHERE. Són:


Operador Significat
> Major que
< Menor que
>= Major o igual
que
<= Menor o igual
que
= Igual
<> Diferent
!= Diferent

Es poden utilitzar tant per comparar números com per comparar textos i dates. En el cas
dels textos, les comparacions es fan en ordre alfabètic.

Operadors lògics

Operador Significat
Retorna CERT si les
AND expressions de la seva esquerra
i dreta són les dues certes.
Retorna CERT si qualsevol de
OR les expressions de la seva
esquerra i dreta són certes.
Inverteix la lògica de l’expressió
que està a la seva dreta. Si era
NOT
cert, mitjançant NOT passa a
ser fals.

Exemple: Seleccionar el número, nom i ofici dels empleats.


SQL> select empl_num, empl_nom, empl_ofici
2 from empl;

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7369 SANCHEZ EMPLEAT
7499 ARROYO VENEDOR
7521 SALA VENEDOR
7566 JIMENEZ DIRECTOR
7654 MARTIN VENEDOR
7698 NEGRO DIRECTOR
7782 CEREZO DIRECTOR
7788 GIL ANALISTA
7839 REY PRESIDENT
7844 TOVAR VENEDOR
7876 ALONSO EMPLEAT
7900 JIMENO EMPLEAT
7902 FERNANDEZ ANALISTA
7934 MUNOZ EMPLEAT

14 rows selected.

12
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir els empleats que són director o president.


SQL> select empl_num, empl_nom, empl_ofici
2 from empl
3 where empl_ofici='DIRECTOR' OR empl_ofici='PRESIDENT';

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7566 JIMENEZ DIRECTOR
7698 NEGRO DIRECTOR
7782 CEREZO DIRECTOR
7839 REY PRESIDENT

Operador BETWEEN

Permet obtenir dades que es trobin (o no es trobin) en un rang de dades (valorInferior,


valorSuperior).
SINTAXI
expressió1 [NOT] BETWEEN expressió2 AND expressió3

on:
 expressió1 és una expressió avaluable de la que es vol
comprovar si està dins els rang definit entre expressió2 i
expressió3.
 [NOT] és opcional. S’utilitza per indicar que es vol
seleccionar tots els registres que no tenen valors entre
expressió2 i expressió3.
 expressió2 és una expressió avaluable que indica el límit
inferior del rang de valors.
 expressió3 és una expressió avaluable que indica el límit
superior del rang de valors.
Exemple: Obtenir tots els empleats que tenen un salari entre 100000 i 200000.
SQL> select empl_num, empl_nom, empl_salari
2 from empl
3 where empl_salari between 100000 and 200000;

EMPL_NUM EMPL_NOM EMPL_SALARI


---------- ---------------- -----------
7369 SANCHEZ 104000
7521 SALA 162500
7654 MARTIN 182000
7844 TOVAR 195000
7876 ALONSO 143000
7900 JIMENO 123500
7934 MUNOZ 169000

7 rows selected.

Exemple: Obtenir tots els empleats que no tenen un salari entre 100000 i 200000.
SQL> select empl_num, empl_nom, empl_salari
2 from empl
3 where empl_salari not between 100000 and 200000;

EMPL_NUM EMPL_NOM EMPL_SALARI


---------- ---------------- -----------
7499 ARROYO 208000
7566 JIMENEZ 386750

13
UD2. Llenguatge SQL DML SQL

7698 NEGRO 370500


7782 CEREZO 318500
7788 GIL 390000
7839 REY 650000
7902 FERNANDEZ 390000

7 rows selected.

Operador IN

Permet obtenir registres que tenen (o no tenen) valors dins una llista.
SINTAXI
expressió1 [NOT] IN (llistaValors)

on:
expressió1 és una expressió avaluable de la que es vol

comprovar si està dins la llistaValors.
 [NOT] és opcional. S’utilitza per indicar que es vol
seleccionar tots els registres que no tenen valors dins la
llistaValors.
 llistaValors és una llista de valors.
Exemple: Obtenir els empleats que són director o president.
SQL> select empl_num, empl_nom, empl_ofici
2 from empl
3 where empl_ofici IN ('DIRECTOR','PRESIDENT');

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7566 JIMENEZ DIRECTOR
7698 NEGRO DIRECTOR
7782 CEREZO DIRECTOR
7839 REY PRESIDENT

14
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir els empleats que no són director ni president.


SQL> select empl_num, empl_nom, empl_ofici
2 from empl
3 where empl_ofici NOT IN ('DIRECTOR','PRESIDENT');

EMPL_NUM EMPL_NOM EMPL_OFICI


---------- ---------------- ----------
7369 SANCHEZ EMPLEAT
7499 ARROYO VENEDOR
7521 SALA VENEDOR
7654 MARTIN VENEDOR
7788 GIL ANALISTA
7844 TOVAR VENEDOR
7876 ALONSO EMPLEAT
7900 JIMENO EMPLEAT
7902 FERNANDEZ ANALISTA
7934 MUNOZ EMPLEAT

10 rows selected.

Operador LIKE

S’utilitza sobretot amb textos. Permet obtenir registres que tenen alguna columna que es
vol que compleixi una condició textual.
SINTAXI
expressió1 [NOT] LIKE cadena

on:
 expressió1 és una expressió avaluable de la que es vol
comprovar si és com cadena.
 [NOT] és opcional. S’utilitza per indicar que es vol
seleccionar tots els registres que no tenen valors que
compleixen cadena.
 cadena és un valor textual. Aquest valor textual pot
incloure dos símbols especials:
Operador Significat
Indica que on hi hagi aquest
símbol s’interpreta com si hi
%
hagués 0 o més caràcters en
aquella posició.
Indica que on hi hagi aquest
símbol s’interpreta com
_
exactament un caràcter
qualsevol.

NOTA: quan es fan comparacions amb cadenes textuals la diferència entre minúscules i
majúscules és significativa.

15
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir tots els empleats que el seu nom acabi amb EZ.
SQL> select empl_num, empl_nom
2 from empl
3 where empl_nom like '%EZ';

EMPL_NUM EMPL_NOM
---------- ----------------
7369 SANCHEZ
7566 JIMENEZ
7902 FERNANDEZ

Exemple: Obtenir tots els empleats que el seu nom tingui 3 caràcters i comenci amb GI.
SQL> select empl_num, empl_nom
2 from empl
3 where empl_nom like 'GI_';

EMPL_NUM EMPL_NOM
---------- ----------------
7788 GIL

Operador IS NULL

Retorna CERT si una expressió conté un valor NULL.


SINTAXI
expressió1 IS [NOT] NULL
on:
 expressió1 és una expressió avaluable de la que es vol
comprovar si el seu valor resultant és NULL.
 [NOT] és opcional. S’utilitza per indicar que es vol
comprovar si el valor de l’expressió no és NULL.
Exemple: Seleccionar el número, el nom i la comissió dels empleats que tenen el valor
NULL al camp comissió.
SQL> select empl_num,empl_nom,empl_comissio
2 from empl
3 where empl_comissio is null;

EMPL_NUM EMPL_NOM EMPL_COMISSIO


---------- ---------------- -------------
7369 SANCHEZ
7566 JIMENEZ
7698 NEGRO
7782 CEREZO
7788 GIL
7839 REY
7876 ALONSO
7900 JIMENO
7902 FERNANDEZ
7934 MUNOZ
Exemple: Seleccionar el número, el nom i la comissió dels empleats que no tenen el
valor NULL al camp comissió.
SQL> SELECT empl_num,empl_nom,empl_comissio
2 FROM empl
3 WHERE empl_comissio IS NOT NULL;

EMPL_NUM EMPL_NOM EMPL_COMISSIO


---------- ---------------- -------------
7499 ARROYO 39000
7521 SALA 65000

16
UD2. Llenguatge SQL DML SQL

7654 MARTIN 182000


7844 TOVAR 0

Precedència d’operadors

De vegades les expressions que podem arribar a crear en instruccions de selecció són
molt extenses i és difícil saber quina part de l’expressió és la que s’avalua primer.
En la següent taula s’indica la precedència dels operadors:
Ordre Operador
1 * /
2 + -
3 ||
4 > < >= <= <>
5 IS [NOT] NULL, [NOT] LIKE, IN
6 [NOT] BETWEEN
6 NOT
7 AND
8 OR

2.1.5. Ordenació

L’ordre inicial dels registres obtinguts per una instrucció SELECT té relació amb l’ordre
en que es van introduir les dades. Per tal d’ordenar en base a criteris mes interessants,
s’utilitza la clàusula ORDER BY.
En aquesta clàusula es col·loca una llista de camps que indica la forma d’ordenar.
S’ordena primer pel primer camp de la llista, si hi ha coincidències pel segon, si també hi
ha coincidències pel tercer, i així successivament.
Es poden col·locar les paraules ASC o DESC (per defecte sempre és ASC). Aquestes
paraules indiquen l’ordenació que es vol fer (ASCendent o DESCendent,
respectivament).

17
UD2. Llenguatge SQL DML SQL

Sintaxi completa de la instrucció SELECT


SELECT expressions
FROM taula
[WHERE condició]
[ORDER BY expressionsAOrdenar1 {ASC|DESC}];

Exemple: Obtenir l’ofici, nom i salari dels empleats que tenen un salari superior a
200000, ordenat ascendentment per ofici i nom.
SQL> SELECT empl_ofici,empl_nom,empl_dept_num
2 FROM empl
3 WHERE empl_salari>200000
4 ORDER BY empl_ofici,empl_nom ASC;

EMPL_OFICI EMPL_NOM EMPL_DEPT_NUM


---------- ---------------- -------------
ANALISTA FERNANDEZ 20
ANALISTA GIL 20
DIRECTOR CEREZO 10
DIRECTOR JIMENEZ 20
DIRECTOR NEGRO 30
PRESIDENT REY 10
VENEDOR ARROYO 30

7 rows selected.

Exemple: Obtenir l’ofici, nom i salari dels empleats que tenen un salari superior a
200000, ordenat ascendentment per ofici i descendentment per nom.
SQL> SELECT empl_ofici,empl_nom,empl_dept_num
2 FROM empl
3 WHERE empl_salari>200000
4 ORDER BY empl_ofici,empl_nom DESC;

EMPL_OFICI EMPL_NOM EMPL_DEPT_NUM


---------- ---------------- -------------
ANALISTA GIL 20
ANALISTA FERNANDEZ 20
DIRECTOR NEGRO 30
DIRECTOR JIMENEZ 20
DIRECTOR CEREZO 10
PRESIDENT REY 10
VENEDOR ARROYO 30

7 rows selected.

1
Per indicar quines expressions es volen ordenar es pot fer indicant l’expressió o bé el número d’expressió tenint
en compte l’ordre en què han estat escrites. Exemple: …ORDER BY empl_nom; o bé … ORDER BY 1;

18
UD2. Llenguatge SQL DML SQL

2.1.6. Funcions

SQL no incorpora funcions específiques pel tractament dels diferents tipus de dades.
Aquestes funcions doncs, són pròpies de cada SGBD. Nosaltres, com que estudiem el
SGBD Oracle veurem les funcions que incorpora que permeten realitzar càlculs
avançats, o bé facilitar l’escriptura de certes expressions. Totes les funcions reben dades
per poder operar (paràmetres) i retornen un resultat (que depèn dels paràmetres passats
a la funció). Els paràmetres es passen entre parèntesi:
nomFunció [(paràmetre1[, paràmetre2,...])]

Si una funció no necessita paràmetres (com SYSDATE) no fa falta col·locar els


parèntesis.

Funcions de caràcters

Conversió de text a majúscules i minúscules


Funció Descripció
LOWER(text) Converteix el text a minúscules.
UPPER(text) Converteix el text a majúscules.
Posa la primera lletra de cada
INITCAP(text)
paraula a majúscules.

Exemples:
SQL> SELECT lower('Hola Món')
2 FROM dual;

LOWER('H
--------
hola món

SQL> SELECT upper('Hola Món')


2 FROM dual;

UPPER('H
--------
HOLA MÓN

SQL> SELECT initcap('hola món')


2 FROM dual;

INITCAP(
--------
Hola Món

19
UD2. Llenguatge SQL DML SQL

Funcions de transformació
Funció Descripció
RTRIM(text) Elimina els espais a la dreta del
text.
RTRIM(text,car) Elimina el conjunt de caràcters car
de la dreta del text.
Elimina els espais a l’esquerra del
LTRIM(text)
text.
Elimina el conjunt de caràcters car
LTRIM(text,car)
de l’esquerra del text.
Elimina els espais en blanc a la
TRIM(text)
dreta i esquerra de text.
Elimina del text els caràcters
indicats.
TRIM(caràcters FROM text)
Exemple: TRIM(‘s’ FROM
‘supers’) retorna ‘uper’.
Obté els m següents caràcters del
text a partir de la posició n (si m
SUBSTR(text,n[,m])
no s’indica s’agafen des de n fins
al final.
LENGTH(text) Obté la mida del text.
Obté la posició en la que es troba
el text que es vol trobar en el text
inicial. Es pot començar a buscar
a partir d’una posició inicial
concreta i fins i tot indicar el
INSTR(text,textATrobar número d’aparició del text que es
[,inici[,nAparició]]) vol trobar.
Exemple: si busquem la lletra ‘a’ i
posem 2 en el paràmetre
nAparició, retorna la posició de la
segona lletra ‘a’ del text.
Si no ho troba retorna 0.
Buscar el text textATrobar en un
REPLACE(text, determinat text (paràmetre text) i
textATrobar, nouText) un cop trobat el canvia pel
nouText.
Omple el text a l’esquerra (LPAD)
LPAD(text,ampladaMàxima, o a la dreta (RPAD) amb el
caràcterOmplir) caràcter indicat per ocupar
RPAD(text,ampladaMàxima, l’amplada indicada.
caràcterOmplir) Si el text és més gran que
l’amplada indicada, es retalla.

Exemples:
SQL> SELECT RTRIM('hola món ')
2 FROM dual;

RTRIM('H
--------
hola món

20
UD2. Llenguatge SQL DML SQL

SQL> SELECT RTRIM('hola món','món') as missatge


2 FROM dual;

MISSATGE
--------------------
hola

SQL> SELECT LTRIM(' hola món') as missatge


2 FROM dual;

MISSATGE
--------------------
hola món

SQL> SELECT LTRIM('hola món','hola') as missatge


2 FROM dual;

MISSATGE
--------------------
món

SQL> SELECT TRIM(' hola món ') as missatge


2 FROM dual;

MISSATGE
--------------------
hola món

SQL> SELECT SUBSTR('hola món',6,3) as missatge


2 FROM dual;

MISSATGE
--------------------
món

SQL> SELECT SUBSTR('hola món',6) as missatge


2 FROM dual;

MISSATGE
--------------------
món

SQL> SELECT LENGTH('hola món') as LONGITUD


2 FROM dual;

LONGITUD
----------
8

SQL> SELECT INSTR('hola món','món') as posicio


2 FROM dual;

POSICIO
----------
6

21
UD2. Llenguatge SQL DML SQL

SQL> SELECT INSTR('hola món món','món',1,2) as posicio


2 FROM dual;

POSICIO
----------
10

SQL> SELECT REPLACE('hola món','món','a tots') as canvi


2 FROM dual;

CANVI
-----------
hola a tots

SQL> SELECT LPAD(empl_nom,10,'*') AS NOM


2 FROM empl;

NOM
----------
***SANCHEZ
****ARROYO
******SALA
***JIMENEZ
****MARTIN
*****NEGRO
****CEREZO
*******GIL
*******REY
*****TOVAR
****ALONSO
****JIMENO
*FERNANDEZ
*****MUNOZ

14 rows selected.

SQL> SELECT RPAD(empl_nom,10,'*') AS NOM


2 FROM empl;

NOM
----------
SANCHEZ***
ARROYO****
SALA******
JIMENEZ***
MARTIN****
NEGRO*****
CEREZO****
GIL*******
REY*******
TOVAR*****
ALONSO****
JIMENO****
FERNANDEZ*
MUNOZ*****

22
UD2. Llenguatge SQL DML SQL

14 rows selected.

23
UD2. Llenguatge SQL DML SQL

Funcions numèriques

Arrodoniments
Funció Descripció
Arrodoneix el número n al següent número amb
ROUND(n,decimals) el nombre de decimals indicat més proper.
Ex: ROUND(8.239, 2)  8.24
Retorna el numero n només amb el nombre de
TRUNC(n,decimals) decimals indicat.
Ex: ROUND(8.239, 2)  8.23
Obté l’enter immediatament més petit o igual que
FLOOR(n) n.
Ex: FLOOR(8.6)  8
Obté l’enter immediatament més gran o igual que
CEIL(n) n.
Ex: FLOOR(8.6)  9

Matemàtiques
Funció Descripció
Retorna el residu de dividir m entre n.
MOD(m,n)
Ex: MOD(7, 5)  2
Retorna el numero m elevat a la potència n.
POWER(m,n)
Ex: POWER(2,3)  8
Obté l’arrel quadrada de n.
SQRT(n)
Ex: SQRT(2)  1.41421356
Retorna -1 si n és negatiu; 0 si n és 0 i 1 si n és positiu.
Ex: SIGN(-2.3)  -1
SIGN(n)
SIGN(0)  0
SIGN(2.3)  1
Calcula el valor absolut de n.
ABS(n)
Ex: ABS(-2.3)  2.3
Calcula en, és a dir, l’exponent amb base e del número n.
EXP(n)
Ex: EXP(2)  7.3890561
Calcula el logaritme naperià de n.
LN(n)
Ex: LN(2)  0.693147181
Calcula el logaritme amb base m de n.
LOG(m,n)
Ex: LOG(10,100)  2
Calcula el sinus de n (n ha d’estar amb radiants)
SIN(n)
Ex: SIN(0)  0
Calcula el cosinus de n (n ha d’estar amb radiants)
COS(n)
Ex: COS(0)  1
Calcula la tangent de n (n ha d’estar amb radiants)
TAN(n)
Ex: TAN(0)  0

Altres
Funció Descripció
Mida en bytes que usa Oracle per emmagatzemar el
VSIZE(valor) valor.
Ex: VSIZE(200000)  2

Funcions per treballar amb valors NULL

24
UD2. Llenguatge SQL DML SQL

Permeten definir els valors a utilitzar en el cas que les expressions agafin el valor NULL.
Funció Descripció
Si el valor és NULL, retorna el valor
substitut; altrament retorna valor.
NVL(valor,substitut)
Ex: NVL(234, 5)  234
NVL(NULL, 6)  6
Si el valor NO és NULL retorna el valor
NVL2(valor,substitut1, substitut1; altrament retorna substitut2.
substitut2) Ex: NVL2( 234, 5, 6 )  5
NVL2( NULL, 5, 6 )  6
Retorna NULL si valor1 = valor2;
NULLIF(valor1,valor2) altrament retorna valor1
Ex: NULLIF(2,2)  NULL
Retorna valor1 si aquest NO és NULL; si
ho és retorna el valor2, si aquest NO és
NULL. Si són NULL el valor1 i el valor2,
COALESCE(valor1,
valor2, retorna el valor3 si aquest NO és NULL, i
[,valor3...]) així successivament.
Si tots els valors indicats són NULL retorna
un error.
Ex: COELESCE(NULL,2,3)  2

Funcions per treballar amb dates

Les dates s’utilitzen molt en totes les bases de dades. Oracle proporciona dos tipus de
dades per gestionar dades, els tipus DATE i TIMESTAMP. En el primer cas
s’emmagatzema una data concreta (que fins i tot pot contenir l’hora), en el segon cas
s’emmagatzema un instant de temps concret que pot tenir fins i tot fraccions de segon.
Cal tenir en compte que als valors de tipus data se’ls hi pot sumar números i s’entendria
que aquesta suma és de dies. En general es pot operar amb números (sumes, restes,
multiplicacions i divisions). Si té decimals llavors se sumen dies, hores, minuts i segons.

25
UD2. Llenguatge SQL DML SQL

Obtenir la data i hora actual


Funció Descripció
SYSDATE Obté la data i hora actuals.
CURRENT_DATE
SYSTIMESTAMP Obté la data i hora actuals amb format
CURRENT_TIMESTAMP TIMESTAMP (instant de temps).
DBTIMEZONE Retorna la zona horària actual.

Calcular dates
Funció Descripció
ADD_MONTHS(data, n) Afegeix n mesos a la data actual.
MONTHS_BETWEEN(data1,data2) Obté la diferència en mesos de les
dues dates.
NEXT_DAY(data, dia) Indica quin és el dia resultant
d’afegir a la data el dia indicat. El
dia pot ser el text ‘Dilluns’,
‘Dimarts’, ‘Dimecres’, ... (si la
configuració està en català) o el
número de dia de la setmana
(1=dilluns, 2=dimarts,...)
LAST_DAY(data) Obté l’últim dia del mes al que
pertany la data. Retorna un valor
DATE.
EXTRACT(valor FROM [DATE] Extreu un valor d’una data. El valor
data) pot ser day (dia), month (mes),
year (any), etc. La data s’ha
d’indicar com a yyyy-mm-dd.
La paraula DATE només cal posar-
la quan el valor de la data és un
valor constant.
GREATEST(data1, data2,...) Retorna la data més moderna de la
llista.
LEAST(data1, data2,...) Retorna la data més vella de la
llista.
ROUND(data [,‘format’]) Arrodoneix la data al valor d’aplicar
el format a la data. El format pot
ser:
 ‘YEAR’. Fa que la data
mostri l’any sencer.
 ‘MONTH’. Fa que la
data mostri el més
sencer més proper a la
data (tenint en compte
les quinzenes)
 ‘HH24’. Arrodoneix
l’hora a les 00:00 més
properes.
 ‘DAY’. Arrodoneix al
primer dia de la setmana
més proper.
TRUNC(data [,‘format’]) Igual que l’anterior però trunca la
data en comptes de fer un
arrodoniment.

26
UD2. Llenguatge SQL DML SQL

27
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir la data resultant de sumar-li 6 mesos a l’11/11/2005.


SQL> SELECT ADD_MONTHS('11/11/2005',6)
2 FROM dual;

ADD_MONT
--------
11/05/06

Exemple: Obtenir els mesos que han passat des de l’11/11/1785 a l’11/11/2005.
SQL> SELECT MONTHS_BETWEEN('11/11/2005','11/11/1785')
2 FROM dual;

MONTHS_BETWEEN('11/11/2005','11/11/1785')
-----------------------------------------
2640

Exemple: Obtenir el següent dimecres després del 14/12/2005.


/* Versió 1 */

SQL> SELECT NEXT_DAY('14/12/2005','Dimecres')


2 FROM dual;

NEXT_DAY
--------
21/12/05

/* Versió 2 */

SQL> SELECT NEXT_DAY('14/12/2005',3)


2 FROM dual;

NEXT_DAY
--------
21/12/05

Exemple: Obtenir l’últim dia del mateix mes que la data 14/12/2005.
SQL> SELECT LAST_DAY('14/12/2005')
2 FROM dual;

LAST_DAY
--------
31/12/05

Exemple: Obtenir el valor de dia de la data 14/12/2005.


SQL> SELECT EXTRACT(day from date '2005-12-14')
2 FROM dual;

EXTRACT(DAYFROMDATE'2005-12-14')
--------------------------------
14

Exemple: Obtenir el valor de mes de la data 14/12/2005.


SQL> SELECT EXTRACT(month from date '2005-12-14')
2 FROM dual;

EXTRACT(MONTHFROMDATE'2005-12-14')
----------------------------------
12

28
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir el valor d’any de la data 14/12/2005.


SQL> SELECT EXTRACT(year from date '2005-12-14')
2 FROM dual;

EXTRACT(YEARFROMDATE'2005-12-14')
---------------------------------
2005

Exemple: Dir quina data és més recent: 11/11/2005 o 14/12/2005?


SQL> SELECT GREATEST('11/11/2005','14/12/2005')
2 FROM dual;

GREATEST('
----------
14/12/2005

Exemple: Dir quina data és més antiga: 11/11/2005 o 14/12/2005?


SQL> SELECT LEAST('11/11/2005','14/12/2005')
2 FROM dual;

LEAST('11/
----------
11/11/2005

Exemple: Arrodonir el valor de la data 14/12/2005 a l’any.


SQL> SELECT ROUND(TO_DATE('14-12-05'),'YEAR')
2 FROM dual;

ROUND(TO
--------
01/01/06

Exemple: Arrodonir el valor de la data 14/12/2005 al mes.


SQL> SELECT ROUND(TO_DATE('14-12-05'),'month')
2 FROM dual;

ROUND(TO
--------
01/12/05

29
UD2. Llenguatge SQL DML SQL

Exemple: Arrodonir el valor de la data 14/12/2005 al dia.


SQL> SELECT ROUND(TO_DATE('14-12-05'),'day')
2 FROM dual;

ROUND(TO
--------
12/12/05

Exemple: Truncar el valor de la data 14/12/2005 a l’any.


SQL> SELECT TRUNC(TO_DATE('14-12-05'),'year')
2 FROM dual;

TRUNC(TO
--------
01/01/05

Exemple: Truncar el valor de la data 14/12/2005 al mes.


SQL> SELECT TRUNC(TO_DATE('14-12-05'),'month')
2 FROM dual;

TRUNC(TO
--------
01/12/05

Exemple: Truncar el valor de la data 14/12/2005 al dia.


SQL> SELECT TRUNC(TO_DATE('14-12-05'),'day')
2 FROM dual;

TRUNC(TO
--------
12/12/05

Funcions de conversió

Oracle és capaç de convertir dades automàticament per tal que l’expressió final tingui
significat. En aquest sentit són fàcils les conversions de text a número i viceversa.
Exemple:
SQL> SELECT 5 + '3'
2 FROM dual;

5+'3'
----------
8
SQL> SELECT 5 || '3'
2 FROM dual;

5|
--
53

També succeeix això amb la conversió de text a data. De fet és la forma habitual
d’assignar dates.
Però de vegades voldrem realitzar conversions explícites.
TO_CHAR
TO_CHAR(valor [, format])

30
UD2. Llenguatge SQL DML SQL

Obté un text a partir d’un número o una data. S’utilitza especialment amb dates (ja que
de número a text se sol utilitzar de forma implícita).
Dates
En el cas de les dates s’indica el format de conversió, que és una cadena que pot
incloure aquests símbols (en una cadena de text):
Símbol Significat
YY Any en format de dues xifres.
YYYY Any en format de quatre xifres.
MM Mes en format de dues xifres.
MON Les tres primeres lletres del mes.
MONTH Nom complert del mes.
DY Dia de la setmana amb tres lletres.
DAY Dia complet de la setmana.
DD  Dia en format de dues xifres.
Q Semestre.
WW Setmana de l’any.
D Dia de la setmana (de l’1 al 7).
DDD Dia de l’any.
AM Indicador AM.
PM Indicador PM.
HH12 Hora de 1 al 12.
HH24 Hora de 0 a 24.
MI Minuts (de 0 a 59).
SS Segons (de 0 a 59).
SSSS Segons des de mitjanit.
/., Posició dels separadors.

Exemple:
SQL> SELECT TO_CHAR(SYSDATE, 'DD MONTH YYYY, DAY HH24:MI:SS')
2 FROM dual;

TO_CHAR(SYSDATE,'DDMONTHYYYY,DAYHH24
------------------------------------
10 DESEMBRE 2005, DISSABTE 14:57:06

Números
Per convertir números a text s’utilitza aquesta funció quan es volen unes característiques
especials. En aquest cas en el format es poden utilitzar aquests símbols:

31
UD2. Llenguatge SQL DML SQL

Símbol Significat
9 Posició del número.
0 Posició del número (mostra zeros).
$ Format dòlar.
L Símbol local de moneda.
. Posició del decimal.
, Posició del separador de milers.

Exemple:
SQL> SELECT TO_CHAR(346545.4, '000,000.00L')
2 FROM dual;

TO_CHAR(346545.4,'000
---------------------
346,545.40€

TO_NUMBER
TO_NUMBER(valor [, format])

Converteix text a números. Es pot indicar el format de la conversió utilitzant els mateixos
símbols que els comentats anteriorment.
TO_DATE
TO_DATE(valor [, format])

Converteix text a data. Es pot indicar el format de la conversió utilitzant els mateixos
símbols vistos anteriorment.
Exemple:
SQL> SELECT TO_DATE('14/12/2005', 'DD/MM/YY') AS DATA
2 FROM dual;

DATA
--------------------
14/12/05

Funcions condicionals

CASE
És una instrucció incorporada a la versió 9 d’Oracle que permet establir condicions de
sortida (a l’estil si-llavors-altrament del pseudocodi).

32
UD2. Llenguatge SQL DML SQL

Sintaxi
CASE expressió WHEN valor1 THEN resultat1
[ WHEN valor2 THEN resultat2 ....
...
ELSE resultatElse
]
END

El funcionament és el següent:
 S’avalua l’expressió indicada.
 Es comprova si aquesta expressió és igual al valor del primer WHEN. Si és així,
retorna el primer resultat (qualsevol valor menys Nul).
 Si l’expressió no és igual al valor 1, llavors es comprova si és igual que el
segon. Si és així s’escriu el resultat 3. Si no és així continua amb el següent
WHEN.
 El resultat indicat a la zona ELSE només s’escriu si l’expressió no val cap valor
dels indicats.
Exemple: Seleccionar el número, nom, ofici, codi departament i salari dels empleats que
tenen com ofici EMPLEAT.
SQL> select empl_num, empl_nom, empl_ofici, empl_dept_num, empl_salari
2 from empl
3 where empl_ofici='EMPLEAT';

EMPL_NUM EMPL_NOM EMPL_OFICI EMPL_DEPT_NUM EMPL_SALARI


---------- ---------------- ---------- ------------- -----------
7369 SANCHEZ EMPLEAT 20 104000
7876 ALONSO EMPLEAT 20 143000
7900 JIMENO EMPLEAT 30 123500
7934 MUNOZ EMPLEAT 10 169000

4 rows selected.

Exemple: Seleccionar el número, nom, ofici, codi departament i salari dels empleats que
tenen com ofici EMPLEAT i augmentar amb 10000 el salari si pertanyen al departament
10, disminuir amb 10000 si pertanyen al departament 20 i no fer res en els altres casos.
SQL> SELECT empl_num, empl_nom, empl_ofici,
2 CASE empl_dept_num
3 WHEN 10 THEN empl_salari + 10000
4 WHEN 20 THEN empl_salari - 10000
5 ELSE empl_salari
6 END AS "Increment salari", empl_salari
7 FROM empl
8 WHERE empl_ofici='EMPLEAT';

EMPL_NUM EMPL_NOM EMPL_OFICI Increment salari EMPL_SALARI


---------- ---------------- ---------- ---------------- -----------
7369 SANCHEZ EMPLEAT 94000 104000
7876 ALONSO EMPLEAT 133000 143000
7900 JIMENO EMPLEAT 123500 123500
7934 MUNOZ EMPLEAT 179000 169000
4 rows selected.
Funció DECODE
Similar a l’anterior però en forma de funció. S’avalua una expressió i es col·loquen a
continuació parells valor-resultat de forma que si l’expressió equival al valor, es retorna el
resultat associat a ell. Es pot indicar un últim paràmetre amb el resultat a retornar en cas
de no trobar cap dels valors indicats.
Sintaxi:
DECODE( expressió, valor1, resultat1
[,valor2, resultat2,...]

33
UD2. Llenguatge SQL DML SQL

[,valorPerDefecte]
)

Exemple:
SQL> SELECT empl_num, empl_nom, empl_ofici,
2 DECODE(empl_dept_num, 10, empl_salari + 10000,
3 20, empl_salari - 10000,
4 empl_salari) AS "Increment salari",
5 empl_salari
6 FROM empl
7 WHERE empl_ofici='EMPLEAT';

EMPL_NUM EMPL_NOM EMPL_OFICI Increment salari EMPL_SALARI


---------- ---------------- ---------- ---------------- -----------
7369 SANCHEZ EMPLEAT 94000 104000
7876 ALONSO EMPLEAT 133000 143000
7900 JIMENO EMPLEAT 123500 123500
7934 MUNOZ EMPLEAT 179000 169000

4 rows selected.

2.1.7. Agrupacions

És molt habitual crear consultes en les que es vol agrupar les dades per tal de realitzar
càlculs en vertical, és a dir, calculats a partir de dades de diferents registres.
Per poder fer aquestes agrupacions s’utilitza la clàusula GROUP BY que permet indicar
en base a quins registres es fa l’agrupació.
Amb GROUP BY la sintaxi de la instrucció SELECT queda d’aquesta forma:
SELECT llistaExpressions
FROM llistaTaules
[WHERE condicionsSeleccio_I_CondicionsCombinació]
[GROUP BY llistaCampsPerAgrupar]
[HAVING condicionsSeleccioDeGrups]
[ORDER BY llistaCampsOrdenació];

A la clàusula GROUP BY, s’indiquen les columnes per les que s’agrupa. La funció
d’aquest apartat és crear un únic registre per cada valor diferent en les columnes del
grup.
Si per exemple agrupem en base a les columnes plantilla_hospital_codi i
plantilla_sala_codi de la taula plantilla, es crearà un únic registre per cada hospital i sala
diferents:
SQL> select plantilla_hospital_codi, plantilla_sala_codi
2 from plantilla
3 group by plantilla_hospital_codi, plantilla_sala_codi;

Si la taula PLANTILLA sense agrupar és:


PLANTILLA_HOSPITAL_CODI PLANTILLA_SALA_CODI PLANTILLA_NOM
----------------------- ------------------- ----------------
13 6 Diaz B.
13 6 Hernandez J.
18 4 Karplus W.
22 6 Higueras D.
22 6 Bocina G.
22 2 Nunez C.
22 1 Rivera G.
22 1 Carlos R.
45 4 Amigo R.
45 1 Frank H.

34
UD2. Llenguatge SQL DML SQL

10 rows selected.

La consulta anterior produeix el següent resultat:


PLANTILLA_HOSPITAL_CODI PLANTILLA_SALA_CODI
----------------------- -------------------
13 6
18 4
22 1
22 2
22 6
45 1
45 4

7 rows selected.

És a dir, és un resum de les dades anteriors. La columna plantilla_nom no està


disponible directament ja que és diferent en els registres del mateix grup. Només es
podria utilitzar des de funcions (com es veurà a continuació). És a dir, aquesta consulta
és errònia:
SQL> SELECT plantilla_hospital_codi, plantilla_sala_codi, plantilla_nom
2 FROM plantilla
3 GROUP BY plantilla_hospital_codi, plantilla_sala_codi;

SELECT plantilla_hospital_codi, plantilla_sala_codi, plantilla_nom


*
ERROR at line 1:
ORA-00979: no és una expressió GROUP BY

35
UD2. Llenguatge SQL DML SQL

Funcions de càlcul amb grups (funcions de totals o d’agregats)

El que és realment interessant de la creació de grups és les possibilitats de càlcul que


ofereix. Per poder fer càlculs de grups s’utilitzen funcions que permeten treballar amb els
registres d’un grup. Són:
Funció Descripció
Compta el nombre d’elements d’un
COUNT(*)
grup.
Expressió pot ser una columna o
expressió on hi intervé alguna
COUNT(expressió) columna.
Compta el número de vegades que
expressió no és NULL.
SUM(expressió) Suma els valors de expressió.
Calcula la mitjana aritmètica sobre
AVG(expressió)
l’expressió indicada.
Mínim valor que agafa l’expressió
MIN(expressió)
indicada.
Màxim valor que agafa l’expressió
MAX(expressió)
indicada.

Exemple: Obtenir la suma de salaris per cada ofici dels empleats.


SQL> SELECT empl_ofici, SUM(empl_salari)
2 FROM empl
3 GROUP BY empl_ofici;

EMPL_OFICI SUM(EMPL_SALARI)
---------- ----------------
ANALISTA 780000
DIRECTOR 1075750
EMPLEAT 539500
PRESIDENT 650000
VENEDOR 747500

Com es pot veure, en l’exemple se sumen les quantitats per cada grup.

HAVING

De vegades es vol restringir el resultat d’una expressió agrupada, com per exemple:
SQL> SELECT empl_ofici, SUM(empl_salari)
2 FROM empl
3 WHERE SUM(empl_salari)>700000
4 GROUP BY empl_ofici;

36
UD2. Llenguatge SQL DML SQL

Però Oracle retornaria aquest error:


WHERE SUM(empl_salari)>700000
*
ERROR at line 3:
ORA-00934: aquí no es permet la funció d'agrupament

La raó d’aquest error és perquè Oracle sempre executa primer el WHERE i llavors els
grups; i per tant aquesta condició del WHERE no la pot fer pel fet de que encara no hi ha
els grups fets.
Per això s’executa la clàusula HAVING, que s’executa després de fer els grups.
S’utilitzaria d’aquesta forma:
SQL> SELECT empl_ofici, SUM(empl_salari)
2 FROM empl
3 GROUP BY empl_ofici
4 HAVING SUM(empl_salari)>700000;

EMPL_OFICI SUM(EMPL_SALARI)
---------- ----------------
ANALISTA 780000
DIRECTOR 1075750
VENEDOR 747500

Això no significa que no puguem utilitzar la clàusula WHERE quan fem agrupacions. Per
exemple, aquesta consulta si que seria vàlida:
SQL> SELECT empl_ofici, SUM(empl_salari)
2 FROM empl
3 WHERE UPPER(EMPL_OFICI)<>'DIRECTOR'
4 GROUP BY empl_ofici
5 HAVING SUM(empl_salari)>700000;

EMPL_OFICI SUM(EMPL_SALARI)
---------- ----------------
ANALISTA 780000
VENEDOR 747500

En definitiva, l’ordre d’execució de la consulta marca el que es pot utilitzar amb el WHERE
i el que es pot utilitzar amb HAVING.
Passes en l’execució d’una instrucció d’agrupació per part del gestor de bases de dades:
 Seleccionar les files desitjades utilitzant WHERE. Aquesta clàusula eliminarà
files en base a la condició indicada.
 S’estableixen els grups indicats en la clàusula GROUP BY.
 Es calculen els valors de les funcions de totals (COUNT, SUM, AVG,...)
 Es filtren els grups que compleixen la clàusula HAVING.
 El resultat s’ordena en base a l’apartat ORDER BY.

2.2. Consulta de dades sobre vàries taules

2.2.1. Introducció

És molt normal que en una consulta es necessitin dades que es troben distribuïes en
diferents taules. Les bases de dades relacionals es basen, com hem vist, en que les
dades es distribueixen en relacions que es poden relacionar mitjançant un atribut. Aquest
atribut és el que permet combinar les dades de les relacions.

37
UD2. Llenguatge SQL DML SQL

Per exemple, si tenim una relació de departaments amb clau primària dept_codi i una
altra relació d’empleats que es refereix als empleats que treballen a cada departament,
segur que (si el disseny està ben fet) a la relació d’empleats hi haurà el DNI de l’empleat
(empl_dni) per saber a quin departament pertany l’empleat.

2.2.2. Producte cartesià de taules

Si per exemple, es vol obtenir una llista de les dades dels departaments i dels empleats,
es podria fer de la següent forma:
SELECT dept_codi, dept_nom, dept_loc, empl_dni, empl_nom, …
FROM dept, empl ;

La sintaxi és correcta ja que es pot indicar més d’una taula a l’apartat de la clàusula
FROM. Però això produeix un producte cartesià (mateix significat que l’operador de
producte cartesià de l’àlgebra relacional) i apareixeran tots els registres dels empleats
relacionats amb tots els registres de departament.

d1 e1

e1
d2 e2

e3
d3 e4

e5

DEPT EMPL

38
UD2. Llenguatge SQL DML SQL

Exemple:
SQL> SELECT dept_num,dept_nom,empl_num,empl_nom
2 FROM dept, empl;

DEPT_NUM DEPT_NOM EMPL_NUM EMPL_NOM


---------- -------------- ---------- ----------------
10 Comptabilitat 7369 SANCHEZ
20 Investigacio 7369 SANCHEZ
30 Vendes 7369 SANCHEZ
40 Produccio 7369 SANCHEZ
10 Comptabilitat 7499 ARROYO
20 Investigacio 7499 ARROYO
30 Vendes 7499 ARROYO
40 Produccio 7499 ARROYO
10 Comptabilitat 7521 SALA
20 Investigacio 7521 SALA
30 Vendes 7521 SALA
40 Produccio 7521 SALA
10 Comptabilitat 7566 JIMENEZ
20 Investigacio 7566 JIMENEZ
30 Vendes 7566 JIMENEZ
40 Produccio 7566 JIMENEZ
10 Comptabilitat 7654 MARTIN
20 Investigacio 7654 MARTIN
30 Vendes 7654 MARTIN
40 Produccio 7654 MARTIN
10 Comptabilitat 7698 NEGRO
20 Investigacio 7698 NEGRO
30 Vendes 7698 NEGRO
40 Produccio 7698 NEGRO
10 Comptabilitat 7782 CEREZO
20 Investigacio 7782 CEREZO
30 Vendes 7782 CEREZO
40 Produccio 7782 CEREZO
10 Comptabilitat 7788 GIL
20 Investigacio 7788 GIL
30 Vendes 7788 GIL
40 Produccio 7788 GIL
10 Comptabilitat 7839 REY
20 Investigacio 7839 REY
30 Vendes 7839 REY
40 Produccio 7839 REY
10 Comptabilitat 7844 TOVAR
20 Investigacio 7844 TOVAR
30 Vendes 7844 TOVAR
40 Produccio 7844 TOVAR
10 Comptabilitat 7876 ALONSO
20 Investigacio 7876 ALONSO
30 Vendes 7876 ALONSO
40 Produccio 7876 ALONSO
10 Comptabilitat 7900 JIMENO
20 Investigacio 7900 JIMENO
30 Vendes 7900 JIMENO
40 Produccio 7900 JIMENO
10 Comptabilitat 7902 FERNANDEZ
20 Investigacio 7902 FERNANDEZ
30 Vendes 7902 FERNANDEZ
40 Produccio 7902 FERNANDEZ
10 Comptabilitat 7934 MUNOZ
20 Investigacio 7934 MUNOZ
30 Vendes 7934 MUNOZ
40 Produccio 7934 MUNOZ

56 rows selected.

39
UD2. Llenguatge SQL DML SQL

Com es pot observar a l’exemple anterior, el producte cartesià entre dues taules no té
molta utilitat. Cal discriminar el producte per tal que només ens doni com a resultat els
departaments relacionats amb els seus empleats. A aquesta discriminació se l’anomena
combinació (join) de taules.
En general nosaltres tindrem diferents opcions per treballar amb múltiples taules:
Combinacions de taules (joins).
Subconsultes (subqueries).
Combinacions especials.

2.2.1. Combinació de taules

Combinacions d’igualtat
Sintaxi:
SELECT <columnes de les taules de la clàusula from>
FROM taula1 [alies1],taula2 [alies2],..., taulaN [aliesN]
WHERE [{taula1|alies1}.]columna = [{taula2|alies2}.]columna
[ AND [{taulaX|aliesX}].columna =
[{taulaY|aliesY}].columna ...]

Exemple:
SQL> SELECT dept_num, dept_nom, empl_num, empl_nom
2 FROM empl, dept
3 WHERE dept_num = empl_dept_num;

DEPT_NUM DEPT_NOM EMPL_NUM EMPL_NOM


---------- -------------- ---------- ----------------
20 Investigacio 7369 SANCHEZ
30 Vendes 7499 ARROYO
30 Vendes 7521 SALA
20 Investigacio 7566 JIMENEZ
30 Vendes 7654 MARTIN
30 Vendes 7698 NEGRO
10 Comptabilitat 7782 CEREZO
20 Investigacio 7788 GIL
10 Comptabilitat 7839 REY
30 Vendes 7844 TOVAR
20 Investigacio 7876 ALONSO
30 Vendes 7900 JIMENO
20 Investigacio 7902 FERNANDEZ
10 Comptabilitat 7934 MUNOZ

14 rows selected.

40
UD2. Llenguatge SQL DML SQL

REGLES DE LES COMBINACIONS


 Poden utilitzar-se tantes taules com es desitgi.
 Pot utilitzar-se més d’una parella de columnes per especificar una condició de
combinació entre dues taules qualsevol.
 A la clàusula SELECT es poden utilitzar columnes de totes les taules que
s’utilitzin a la combinació.
 Si hi ha el mateix nom en columnes de diferents taules llavors utilitzarem la
sintaxi NOM_TAULA.Nom_columna, per poder-les diferenciar.
 Per combinar N taules, cal un mínim de N-1 condicions de combinació. Per
exemple, per combinar 3 taules, calen un mínim de 2 condicions de
combinació.


Exemple 1: Seleccionar tots els noms dels doctors d’especialitat Cardiologia que treballin
a l’hospital General.
SQL> SELECT doctor_nom
2 FROM doctor, hospital
3 WHERE hospital_codi=doctor_hospital_codi AND
4 hospital_nom='General' AND
5 doctor_especialitat='Cardiologia';

DOCTOR_NOM
----------------
Cajal R.

Exemple 2: Seleccionar el nom dels empleats, i el número de telèfon de l’hospital dels


empleats que treballen a la sala de Recuperacions de l’hospital la Paz.
SQL> SELECT plantilla_nom, hospital_telefon
2 FROM plantilla, hospital, sala
3 WHERE plantilla_sala_codi = sala_codi AND
4 plantilla_hospital_codi = sala_hospital_codi AND
5 plantilla_hospital_codi = hospital_codi AND
6 sala_nom = 'Recuperacio' AND
7 hospital_nom = 'La Paz';

PLANTILLA_NOM HOSPITAL
---------------- --------
Rivera G. 923-5411
Carlos R. 923-5411

Combinacions de no igualtat
Són aquelles combinacions on la condició de combinació no conté l’operador d’igualtat.
Exemple 1: obtenir els treballadors de la plantilla que no treballen a l’hospital ‘La Paz’.
SQL> select plantilla_nom
2 from plantilla, hospital
3 where plantilla_hospital_codi <> hospital_codi and
4 hospital_nom = 'La Paz';

PLANTILLA_NOM
----------------
Diaz B.
Hernandez J.
Karplus W.
Amigo R.
Frank H.

41
UD2. Llenguatge SQL DML SQL

2.2.2. Obtenir registres que no estan relacionats

A l’exemple 2 de combinacions d’igualtat, (on es feia una combinació d’igualtat o


equijoin) dels departaments i els empleats podria haver passat que un departament
encara no tingués empleats i, per tant, hi hauria departaments que no sortirien a la
consulta al no tenir cap empleat relacionat.
La forma d’aconseguir que surtin tots els registres d’una taula encara que no estiguin
relacionats amb els de l’altra és fer una combinació externa (també anomenada outer
join). En aquestes combinacions, el signe (+) indica que es volen tots els registres de la
taula estiguin o no relacionats.
Sintaxi:
SELECT taula1.columna1, taula1.columna2,....
taula2.columna1, taula2.columna2,...
FROM taula1, taula2
WHERE taula1.columnaRelacionada(+)=taula2.columnaRelacionada

Amb aquesta sintaxi s’obtenen els registres relacionats entre les taules i a més a més els
registres no relacionats de la taula2.
Exemple:
SQL> SELECT dept_num, dept_nom, empl_nom
2 FROM dept, empl
3 WHERE empl_dept_num(+) = dept_num
4 ORDER BY dept_num;

DEPT_NUM DEPT_NOM EMPL_NOM


---------- -------------- ----------------
10 Comptabilitat CEREZO
10 Comptabilitat REY
10 Comptabilitat MUNOZ
20 Investigacio SANCHEZ
20 Investigacio ALONSO
20 Investigacio FERNANDEZ
20 Investigacio GIL
20 Investigacio JIMENEZ
30 Vendes ARROYO
30 Vendes NEGRO
30 Vendes MARTIN
30 Vendes JIMENO
30 Vendes TOVAR
30 Vendes SALA
40 Produccio
15 rows selected.
Es podria utilitzar també aquesta altra forma:
SELECT taula1.columna1, taula1.columna2,....
taula2.columna1, taula2.columna2,...
FROM taula1, taula2
WHERE taula1.columnaRelacionada=taula2.columnaRelacionada(+)

En aquest cas surten els relacionats i els de la segona taula que no estan relacionats
amb cap de la primera.
Exemple:
SQL> SELECT dept_num, dept_nom, empl_nom
2 FROM dept, empl
3 WHERE empl_dept_num = dept_num(+)
4 ORDER BY dept_num;

DEPT_NUM DEPT_NOM EMPL_NOM

42
UD2. Llenguatge SQL DML SQL

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


10 Comptabilitat CEREZO
10 Comptabilitat REY
10 Comptabilitat MUNOZ
20 Investigacio SANCHEZ
20 Investigacio ALONSO
20 Investigacio FERNANDEZ
20 Investigacio GIL
20 Investigacio JIMENEZ
30 Vendes ARROYO
30 Vendes NEGRO
30 Vendes MARTIN
30 Vendes JIMENO
30 Vendes TOVAR
30 Vendes SALA

14 rows selected.

2.2.3. Auto combinacions

Una auto combinació s’utilitza quan ens trobem davant una relació reflexiva (relació
d’una columna d’una taula amb una columna de la mateixa taula).
Exemple: Obtenir el codi i nom d’empleat, juntament amb el codi i nom del seu director.
SQL> SELECT e.empl_num, e.empl_nom,
2 d.empl_num "Codi Director", d.empl_nom "Nom director"
3 FROM empl e, empl d
4 WHERE e.empl_dir = d.empl_num;

EMPL_NUM EMPL_NOM Codi Director Nom director


---------- ---------------- ------------- ----------------
7369 SANCHEZ 7902 FERNANDEZ
7499 ARROYO 7698 NEGRO
7566 JIMENEZ 7839 REY
7654 MARTIN 7698 NEGRO
7698 NEGRO 7839 REY
7782 CEREZO 7839 REY
7788 GIL 7566 JIMENEZ
7844 TOVAR 7698 NEGRO
7876 ALONSO 7788 GIL
7900 JIMENO 7698 NEGRO
7902 FERNANDEZ 7566 JIMENEZ
7934 MUNOZ 7782 CEREZO

12 rows selected.

2.2.4. Sintaxi SQL 1999

En la versió SQL 1999 es va crear una nova sintaxi per consultar varies taules. La raó va
ser la de separar les condicions de combinació de les condicions de selecció de
registres.
SINTAXI:
SELECT taula1.columna1, taula1.columna2,...
taula2.columna1, taula2.columna2,...
FROM taula1
[CROSS JOIN taula2] |

43
UD2. Llenguatge SQL DML SQL

[NATURAL JOIN taula2] |


[JOIN taula2 USING(columna1,columna2,...)] |
[[INNER]JOIN taula2 ON
(taula1.columa=taula2.columna)] |
[LEFT|RIGHT|FULL OUTER JOIN taula2 ON

(taula1.columa=taula2.columna)] ;

CROSS JOIN
S’utilitza per fer un producte cartesià entre les taules.
Exemple :
SELECT empl_nom, dept_num
FROM empl CROSS JOIN dept;

És equivalent a:
SELECT empl_nom, detp_num
FROM dept, empl ;

NATURAL JOIN
Estableix una relació d’igualtat entre les dades de les taules a partir de les columnes que
tinguin el mateix nom en les dues taules.
Si no hi ha columnes que tinguin el mateix nom en les dues taules, es produirà un
producte cartesià.
Si les columnes que tenen el mateix nom tenen tipus de dades diferents, dóna un error.
Exemple 1: Suposem que tenim les taules:
EMPL(empl_num, empl_nom, dept_num)
DEPT(dept_num, dept_nom)

SQL> SELECT empl_nom, dept_nom


2 FROM empl NATURAL JOIN dept;

EMPL_NOM DEPT_NOM
---------------- --------------
SANCHEZ Investigacio
ARROYO Vendes
SALA Vendes
JIMENEZ Investigacio
MARTIN Vendes
NEGRO Vendes
CEREZO Comptabilitat
GIL Investigacio
REY Comptabilitat
TOVAR Vendes
ALONSO Investigacio
JIMENO Vendes
FERNANDEZ Investigacio
MUNOZ Comptabilitat

14 rows selected.

És equivalent a:
SQL> SELECT empl_nom, dept_nom
FROM empl e, dept d
WHERE e.dept_num = d.dept_num;

Exemple 2: Es vol fer la mateixa consulta que a l’exemple 1, però ara que només mostri
els empleats dels departaments de vendes i de comptabilitat.

44
UD2. Llenguatge SQL DML SQL

SQL> SELECT empl_nom, dept_nom


2 FROM empl NATURAL JOIN dept
4 WHERE dept_nom IN (‘Vendes’,‘Comptabilitat’);

És equivalent a:
SQL> SELECT empl_nom, dept_nom
FROM empl e, dept d
WHERE e.dept_num = d.dept_num
AND dept_nom IN (‘Vendes’, ‘Comptabilitat’);

JOIN USING
Permet establir relacions indicant quina columna (o columnes) comuns a les dues taules
cal utilitzar per fer la combinació.
Exemple: Suposem que tenim les taules:
EMPL(empl_num, empl_nom, dept_num) i DEPT(dept_num, dept_nom)

SQL> SELECT empl_nom, dept_nom


2 FROM empl JOIN dept USING (dept_num);

EMPL_NOM DEPT_NOM
---------------- --------------
SANCHEZ Investigacio
ARROYO Vendes
SALA Vendes
JIMENEZ Investigacio
MARTIN Vendes
NEGRO Vendes
CEREZO Comptabilitat
GIL Investigacio
REY Comptabilitat
TOVAR Vendes
ALONSO Investigacio
JIMENO Vendes
FERNANDEZ Investigacio
MUNOZ Comptabilitat

14 rows selected.

És equivalent a:
SQL> SELECT empl_nom, dept_nom
FROM empl e, dept d
WHERE e.dept_num = d.dept_num;

Quan cal utilitzar la clàusula USING?


Si varies columnes tenen els mateixos noms però els tipus de dades no coincideixen, es
pot utilitzar USING per indicar les columnes que cal utilitzar a la combinació d’igualtat.
Quan es vol fer coincidir només una columna quan en coincideixen varies.
A tenir en compte:
No utilitzar un àlies de taula a les columnes que s’indiquen a la clàusula USING.

JOIN ON

45
UD2. Llenguatge SQL DML SQL

Permet establir relacions on la condició s’estableix manualment, el que permet realitzar


combinacions més complexes o bé combinacions on les columnes de les taules
relacionades no tenen el mateix nom:
Exemple:
SQL> SELECT empl_nom, dept_nom
2 FROM empl JOIN dept ON empl_dept_num = dept_num;

EMPL_NOM DEPT_NOM
---------------- --------------
SANCHEZ Investigacio
ARROYO Vendes
SALA Vendes
JIMENEZ Investigacio
MARTIN Vendes
NEGRO Vendes
CEREZO Comptabilitat
GIL Investigacio
REY Comptabilitat
TOVAR Vendes
ALONSO Investigacio
JIMENO Vendes
FERNANDEZ Investigacio
MUNOZ Comptabilitat

14 rows selected.

És equivalent a:
SQL> SELECT empl_nom, dept_nom
FROM empl e, dept d
WHERE empl_dept_num = dept_num;

I si es combinen 3 taules, com s’utilitza la clàusula JOIN ON?


EXEMPLE : Seleccionar el nom dels empleats, i el número de telèfon de l’hospital dels
empleats que treballen a la sala de Recuperacions de l’hospital la Paz.
SQL> SELECT plantilla_nom, hospital_telefon
2 FROM plantilla
3 JOIN hospital ON plantilla_hospital_codi = hospital_codi
4 JOIN sala ON sala_hospital_codi = hospital_codi AND
5 sala_codi = plantilla_sala_codi
6 WHERE sala_nom = 'Recuperacio' AND
7 hospital_nom = 'La Paz';

PLANTILLA_NOM HOSPITAL
---------------- --------
Rivera G. 923-5411
Carlos R. 923-5411

Combinacions externes
La última possibilitat és obtenir combinacions externes (outer joins). Per fer-ho utilitzarem
la següent sintaxi:
SQL> SELECT empl_nom, dept_nom
2 FROM empl RIGHT OUTER JOIN dept ON empl_dept_num = dept_num;

EMPL_NOM DEPT_NOM
---------------- --------------
SANCHEZ Investigacio

46
UD2. Llenguatge SQL DML SQL

ARROYO Vendes
SALA Vendes
JIMENEZ Investigacio
MARTIN Vendes
NEGRO Vendes
CEREZO Comptabilitat
GIL Investigacio
REY Comptabilitat
TOVAR Vendes
ALONSO Investigacio
JIMENO Vendes
FERNANDEZ Investigacio
MUNOZ Comptabilitat
Produccio
15 rows selected.

És equivalent a:
SQL> SELECT empl_nom, dept_nom
2 FROM empl, dept
3 WHERE empl_dept_num (+) = dept_num;

En aquesta consulta, a més a més dels departaments relacionats amb empleats,


apareixen aquells departaments que no tenen cap empleat. Si el RIGHT el canviem per
LEFT, apareixeran els empleats que no estan relacionats amb cap departament.
La clàusula FULL OUTER JOIN produeix un resultat en el que apareixen els registres
relacionats i no relacionats d’ambdues taules.
Són externes, totes aquelles combinacions que no són internes. Les combinacions
internes són les que tornen només les files coincidents en les taules combinades.

2.2.5. Subconsultes

Fins ara hem utilitzat la clàusula WHERE per definir els subconjunts de dades que
desitgem.
A més a més, hem utilitzat SQL per relacionar un valor d’una columna amb una constant
o un grup de constants.
S’utilitzen les subconsultes quan es desconeixen els valors de les constants.

47
UD2. Llenguatge SQL DML SQL

Exemple: Quins empleats tenen un salari superior a la mitja?


Calen dues consultes:
Una per saber quina és la mitja dels salaris dels empleats,
Una altra per buscar els empleats que guanyen més que aquesta quantitat.
Es pot resoldre aquest problema combinant les dues consultes, col·locant una dins
l’altra. D’aquesta manera, la consulta interna o subconsulta retorna un valor que utilitza
la consulta externa o principal.

Sintaxi:
SELECT llistaExpressions
FROM taula
WHERE expressió operador
(SELECT llistaExpressions
FROM taula);

Es pot col·locar el SELECT dins de les clàusules WHERE, HAVING o FROM. L’operador
pot ser >, <, >=, <=, <>, =, IN, ANY, ALL.
Exemple:
Per obtenir el salari mig de la plantilla d’empleats:
SQL> SELECT AVG(plantilla_salari)
2 FROM plantilla;

AVG(PLANTILLA_SALARI)
---------------------
230210

Per obtenir el nom dels empleats que tenen un salari superior a la mitja, hauríem
d’anotar el valor anterior a un paper i després fer:
SQL> SELECT plantilla_nom
2 FROM plantilla
3 WHERE plantilla_salari > 230210;

PLANTILLA_NOM
----------------
Hernandez J.
Karplus W.
Frank H.

48
UD2. Llenguatge SQL DML SQL

O podem utilitzar una subconsulta:


SQL> SELECT plantilla_nom
2 FROM plantilla
3 WHERE plantilla_salari > ( SELECT AVG(plantilla_salari)
4 FROM plantilla);

PLANTILLA_NOM
----------------
Hernandez J.
Karplus W.
Frank H.

La subconsulta (la comanda SELECT entre parèntesis) s’executa primer i, posteriorment,


el valor que s’extreu s’introdueix a la consulta principal.
El valor de comparació pot ser un valor simple recuperat mitjançant una comanda de
selecció, o un conjunt de valors recuperats per una altra sentència SELECT.
Resultat subconsulta Operador comparatiu
Valor simple (una fila) Aritmètic (>, <, >=, <=, <>, =)
Més d’un valor (varies Lògic ( [NOT] IN, ANY, ALL )
files)

Subconsultes que retornen un valor simple


Exemple: Retornar els noms dels empleats que tenen el mateix treball que JIMENEZ.
SELECT empl_nom
FROM empl
WHERE empl_ofici = (SELECT empl_ofici
FROM empl
WHERE UPPER(empl_nom) = ‘JIMENEZ’);

Exemple: Retornar la informació sobre els empleats que guanyen més que qualsevol
empleat del departament 30.
SELECT *
FROM empl
WHERE empl_salari > (SELECT MAX(empl_salari)
FROM empl
WHERE empl_dept_num = 30);

49
UD2. Llenguatge SQL DML SQL

Exemple: Retornar la informació sobre els empleats que tenen el mateix treball que
l’empleat SALA i guanyen més que l’empleat MARTIN.
SQL> SELECT empl_nom, empl_ofici, empl_salari
2 FROM empl
3 WHERE empl_ofici =
4 (SELECT empl_ofici
5 FROM empl
6 WHERE empl_nom = 'SALA')
7 AND empl_salari >
8 (SELECT empl_salari
9 FROM empl
10 WHERE empl_nom = 'MARTIN');

EMPL_NOM EMPL_OFICI EMPL_SALARI


---------------- ---------- -----------
ARROYO VENEDOR 208000
TOVAR VENEDOR 195000

Exemple: per què dóna error aquesta consulta?


SQL> SELECT empl_num, empl_nom
2 FROM empl
3 WHERE empl_salari =
4 (SELECT MIN(empl_salari)
5 FROM empl
6 GROUP BY empl_dept_num);
(SELECT MIN(empl_salari)
*
ERROR at line 4:
ORA-01427: single-row subquery returns more than one row

El motiu de l’error és el d’utilitzar un operador d’una sola fila amb una subconsulta de
varies files.

Exemple: per què no torna cap fila aquesta consulta?


SQL> SELECT empl_num, empl_nom
2 FROM empl
3 WHERE empl_ofici =
4 (SELECT empl_ofici
5 FROM empl
6 WHERE empl_nom = 'PERE');

no rows selected
No hi ha cap empleat que es digui PERE, per tant, la subconsulta no torna cap fila. La
consulta externa agafa els resultants de la subconsulta (valor nul) i els utilitza dins la
seva clàusula WHERE. La consulta externa no troba cap empleat amb ofici igual a NUL i
no torna cap fila. Si hi hagués ofici amb valor NUL, tampoc es tornaria la fila com a
resultat, ja que la comparació de dos valors nuls dóna un altre valor nul (ni cert ni fals),
per tant la condició WHERE no és certa.

Subconsultes que retornen una llista de valors


Retornen més d’una fila i s’utilitzen operadors de comparació de varies files:
Operador Significat
[NOT] Compara amb qualsevol fila de la subconsulta. La
ANY instrucció és vàlida si hi ha una fila a la subconsulta
que permet que la comparació sigui certa.
[NOT] Compara amb totes les files de la subconsulta. La

50
UD2. Llenguatge SQL DML SQL

ALL instrucció és certa si és certa tota comparació amb les


files de la subconsulta.
[NOT] IN Serveix per comprovar si un valor es troba en el
resultat de la subconsulta.

Exemple: Retornar tots els treballadors de la plantilla de l’hospital que no són Infermera i
que el seu salari sigui inferior al de qualsevol Infermera.
SQL> SELECT plantilla_nom, plantilla_funcio, plantilla_salari
2 FROM plantilla
3 WHERE plantilla_salari < ANY
4 (SELECT plantilla_salari
5 FROM plantilla
6 WHERE plantilla_funcio = 'Infermera')
7 AND plantilla_funcio <> 'Infermera';
PLANTILLA_SALARI
PLANTILLA_NOM PLANTILLA_ PLANTILLA_SALARI ----------------
---------------- ---------- ---------------- 226200
Bocina G. Infermer 183800 200500
Amigo R. Intern 221000 162600
Nunez C. Intern 221000 221900
252200
< ANY significa menys que el valor màxim de la subconsulta
> ANY significa més que el valor mínim de la subconsulta
= ANY és equivalent a IN.

Exemple: Obtenir el nom i el salari dels empleats que tenen el salari igual a algun dels
empleats del departament 20.
SQL> SELECT empl_nom, empl_salari
2 FROM empl
3 WHERE empl_salari = ANY (SELECT empl_salari
4 FROM empl
5 WHERE empl_dept_num = 20);

EMPL_NOM EMPL_SALARI
---------------- -----------
SANCHEZ 104000
ALONSO 143000
JIMENEZ 386750
GIL 390000
FERNANDEZ 390000

Exemple: Retornar tots els treballadors de la plantilla de l’hospital que no són Infermera i
que el seu salari sigui inferior al de qualsevol Infermera.
SQL> SELECT plantilla_nom, plantilla_funcio, plantilla_salari
2 FROM plantilla
3 WHERE plantilla_salari < ALL
4 (SELECT plantilla_salari
5 FROM plantilla
6 WHERE plantilla_funcio = 'Infermer')
7 AND plantilla_funcio <> 'Infermer'
PLANTILLA_SALARI
PLANTILLA_NOM PLANTILLA_ PLANTILLA_SALARI ----------------
---------------- ---------- ---------------- 275000
Rivera G. Infermera 162600 183800

< ALL significa menys que el valor mínim de la subconsulta


> ALL significa més que el valor màxim de la subconsulta

51
UD2. Llenguatge SQL DML SQL

Exemple: Obtenir l’empleat que cobra més.


SQL> SELECT empl_nom, empl_salari
2 FROM empl
3 WHERE empl_salari >= ALL (SELECT empl_salari FROM empl);

EMPL_NOM EMPL_SALARI
---------------- -----------
REY 650000

Exemple: Retornar tots els empleats que treballen a Madrid o a Barcelona


SELECT empl_nom,empl_datalt,empl_dept_num
FROM empl
WHER empl_dept_num IN
(SELECT dept_num
FROM dept
WHERE dept_loc IN ('Madrid','Barcelona'));
Exemple: Retornar els noms de tots els empleats del departament 20 que tenen un
treball idèntic al de qualsevol dels empleats del departament de VENDES
SELECT empl_nom
FROM empl
WHERE empl_dept_num=20
AND empl_ofici IN (SELECT empl_ofici
FROM empl
WHERE empl_dept_num IN
(SELECT empl_dept_num
FROM dept
WHERE UPPER(dept_nom)='VENDES'));

52
UD2. Llenguatge SQL DML SQL

Observant l’últim exemple:


 Una subconsulta pot contenir una altra subconsulta. Es poden tenir un número
infinit de nivells.

 L’operador de comparació utilitzat és IN, ja que la consulta interior retorna més
d’una fila.

 L’ordre en que la consulta interior retorna les files no és important i per tant, no
pot especificar-se.

Subconsultes que retornen més d’una columna


També es pot donar el cas en que una subconsulta retorna més d’una columna.
SELECT empl_nom
FROM empl
WHERE (empl_ofici, empl_salari)=
(SELECT empl_ofici, empl_salari
FROM empl
WHERE UPPER(empl_nom) = 'JIMENEZ');

Exemple: Obtenir els empleats amb el mateix ofici i salari que JIMENEZ
SELECT empl_nom
FROM empl
WHERE (empl_ofici, empl_salari)=
(SELECT empl_ofici, empl_salari
FROM empl
WHERE UPPER(empl_nom) = 'JIMENEZ');

2.2.6. Operadors de conjunts

Unió
Aquest operador equival a l’operació UNIÓ de l’àlgebra relacional.
La clàusula UNION permet afegir el resultat d’un SELECT a un altre SELECT. Per poder-
ho fer, les dues instruccions han d’utilitzar el mateix número i tipus de columnes.
SQL> SELECT empl_nom
2 FROM empl
3 UNION
4 SELECT plantilla_nom
5 FROM plantilla;

EMPL_NOM
----------------
ALONSO
ARROYO
Amigo R.
Bocina G.
CEREZO
Carlos R.
Diaz B.
FERNANDEZ
Frank H.
GIL
Hernandez J.
Higueras D.
JIMENEZ
JIMENO
Karplus W.

53
UD2. Llenguatge SQL DML SQL

MARTIN
MUNOZ
NEGRO
Nunez C.
REY
Rivera G.
SALA
SANCHEZ
TOVAR

24 rows selected.

El resultat és una taula que tindrà els noms dels empleats i empleats de plantilla.
És a dir, UNION crea una sola taula (temporal) amb les files de les dues consultes. Si hi
ha files repetides, només apareixeran una vegada. Per mostrar duplicats s’utilitza UNION
ALL enlloc de UNION.
Per defecte, s’ordena el resultat per la primera columna seleccionada.

Intersecció
De la mateixa forma, la paraula INTERSECT permet fer la intersecció dues consultes
SELECT de manera que el resultat seran les files que estiguin a les dues consultes.
Aquest operador equival a l’operació INTERSECCIÓ de l’àlgebra relacional.

Diferència
Amb MINUS es fa la diferència de dues consultes SELECT de manera que apareixeran
els registres del primer SELECT que no estiguin en el segon.
Aquest operador equival a l’operació DIFERÈNCIA de l’àlgebra relacional.
Exemple:
SQL> SELECT empl_nom
2 FROM empl
3 MINUS
4 SELECT plantilla_nom
5 FROM plantilla;

EMPL_NOM
----------------
ALONSO
ARROYO
CEREZO
FERNANDEZ
GIL
JIMENEZ
JIMENO
MARTIN
MUNOZ
NEGRO
REY
SALA
SANCHEZ
TOVAR

14 rows selected.

Es poden utilitzar aquests operadors de forma niuada (una unió on el resultat es utilitzat
amb la diferència amb un altre SELECT, per exemple). En aquest cas cal posar
parèntesis per indicar quina operació es fa primer:
(SELECT....

54
UD2. Llenguatge SQL DML SQL

....
UNION
SELECT....
...
)
MINUS
SELECT.... /* Primer es fa la unió i després la diferència */

2.3. Inserció, modificació i eliminació

2.3.1. Introducció

Dins del llenguatge de manipulació de dades SQL (DML SQL) també hi trobem les
instruccions per poder manipular les dades que contenen les taules de la base de dades.
En totes aquestes consultes, normalment l’única dada retornada pel SGBDR (en el
nostre cas Oracle) és el nombre de registres que s’han modificat.

2.3.2. Inserció de dades

Per poder afegir dades a una taula es fa mitjançant la instrucció INSERT. La seva
sintaxi bàsica és:
INSERT INTO taula [(llistaDeCamps)]
VALUES (valor1, [valor2, valor3, ...)];

On:
taula indica la taula on volem inserir el nou registre de dades.
llistaDeCamps és una dada opcional i serveix per indicar en quins camps volem
inserir noves dades.
Després de la paraula clau VALUES s’indiquen els valors dels camps del nou registre
que volem afegir a la taula.
La llistaDeCamps no és obligatori indicar-la. En aquest cas hem d’indicar la llista de
valors de tots els camps de la taula i en el mateix ordre que apareixen en la definició de
la taula.
Si indiquem la llistaDeCamps llavors permet indicar només els valors d’uns quants
camps de la taula. Els valors que no indiquem s’omplen amb el seu valors per defecte
(DEFAULT en la definició dels camps de la taula) o bé amb NULL. Si hi ha algun camp
que té una restricció NOT NULL, es produirà un error si no indiquem cap valor per aquell
camp.
Exemple: Volem inserir un nou departament a la taula DEPT. Observem abans quina és
la definició de la taula:
SQL> desc dept
Name Null? Type
----------------------------------------- -------- -------------------------
DEPT_NUM NOT NULL NUMBER(2)
DEPT_NOM VARCHAR2(14)
DEPT_LOC VARCHAR2(13)

Si només volem inserir les dades del NUM i el NOM del departament ho podem fer així:
SQL> INSERT INTO dept(dept_num,dept_nom)
2 VALUES (50,'Informatica');

55
UD2. Llenguatge SQL DML SQL

1 row created.

SQL> SELECT *
2 FROM dept;

DEPT_NUM DEPT_NOM DEPT_LOC


---------- -------------- -------------
10 Comptabilitat Sevilla
20 Investigacio Madrid
30 Vendes Barcelona
40 Produccio Bilbao
50 Informatica

Es pot veure com en la columna DEPT_LOC del nou departament hi ha com a valor
NULL, ja que no s’ha indicat aquest valor en la instrucció INSERT i a més a més no hi
havia cap restricció sobre la columna DEPT_LOC que indiqués que no es puguin inserir
valors NULL en aquesta columna.

56
UD2. Llenguatge SQL DML SQL

Exemple: Si volem inserir totes les dades d’un nou departament ho podem fer així:
SQL> INSERT INTO dept
2 VALUES (50,'Informatica','Olot');

Exemple: Si no indiquem les dades d’alguna de les columnes que tenen alguna restricció
d’integritat, donaria un error semblant a aquest:
SQL> INSERT INTO dept(dept_nom,dept_loc)
2 VALUES ('Informatica','Olot');
INSERT INTO dept(dept_nom,dept_loc)
*
ERROR at line 1:
ORA-01400: no es pot inserir NULL a ("MNICOLAU"."DEPT"."DEPT_NUM")

Errors d’inserció
Els errors més habituals que es poden produir quan s’insereixen o es modifiquen dades
són els següents:
Falta un valor obligatori per una columna NOT NULL.
Un valor duplicat viola la restricció d’unicitat.
Es viola una restricció de clau forana.
Es viola una restricció CHECK.
El tipus de dades no coincideix.
El valor és massa gran per la columna.
Inserció de valors especials
Quan es fa la inserció d’una nova fila a una taula es poden utilitzar funcions (les
mateixes que hem vist quan estudiàvem les consultes de selecció).
Per exemple:
INSERT INTO empl (empl_num, empl_nom, empl_ofici, empl_dir,
empl_datalt, empl_salari, empl_comissio,
empl_dept_num)
VALUES (800, 'JORDI','ANALISTA',7258,
SYSDATE,200000,NULL,
10);

Creació d’un fitxer de comandaments


Es poden guardar comandaments SQL amb variables de substitució dins un fitxer
d’script SQL i executar el fitxer d’script.
Per exemple:
INSERT INTO dept (dept_num, dept_nom, dept_loc)
VALUES (&num_dept,’&nom_dept’,’&localitat_dept’);
Quan s’executi el fitxer que conté aquesta instrucció, el primer que farà serà demanar el
valor de cada una de les variables de substitució (les que tenen el símbol & davant el
nom). Els valors introduïts es substituiran llavors dins la instrucció.
Això permet executar el mateix fitxer de comandes tantes vegades com calgui.
Inserció de registres a partir de les files d’una taula
Hi ha un tipus de consulta, anomenada d’addició de dades, que permet omplir dades
d’una taula copiant el resultat d’una consulta.
Aquest tipus d’addició de dades es basa amb la consulta SELECT que serà la que
retornarà les dades a afegir. Com és lògic, l’ordre d’aquests camps ha de coincidir amb
la llista de camps indicada en la instrucció INSERT. Sintaxi:
INSERT INTO taula (camp1, camp2, ...)]
SELECT campCompatibleCamp1,
campCompatibleCamp2, ...
FROM taula(es)
[altres clàusules del SELECT...];

57
UD2. Llenguatge SQL DML SQL

Exemple: Suposem que hem creat una taula nova que contindrà les dades dels empleats
que són Analistes i que la volem omplir a partir d’una consulta feta a la taula EMPL.
En primer lloc és necessari que la nova taula estigui creada. Suposem que la taula que
creem és la següent:
CREATE TABLE empl_analistes
(
num NUMBER(4) PRIMARY KEY,
nom VARCHAR(16),
dept NUMBER(2),
foreign key(dept) references dept(dept_num)
)

La consulta que ompliria la taula amb tots els analistes de la taula EMPL seria:
INSERT INTO empl_analistes (num,nom,dept)
SELECT empl_num, empl_nom, empl_dept_num
FROM empl
WHERE UPPER(empl_ofici)='ANALISTA';

2.3.3. Modificació de dades

Podem modificar / actualitzar les dades dels registres d’una taula amb la instrucció
UPDATE.
Sintaxi:
UPDATE taula
SET columna1 = valor1 [,columna2 = valor2...]
[WHERE condició]
On:
 taula indica la taula on volem fer alguna modificació de les dades dels seus
registres.

A partir de la paraula SET s’indiquen les assignacions de les noves dades per cada una
de les columnes on hem de canviar valors.
La condició WHERE és opcional i permet indicar quines seran les files que es veuran
afectades per l’actualització de dades.
Exemple: Actualitzar a Barna el camp dept_loc d’aquells departaments que estan ubicats
a Barcelona.
SQL> UPDATE dept
2 SET dept_loc='Barna'
3 WHERE UPPER(dept_loc)='BARCELONA';

Exemple: Actualitzar el salari i la comissió dels empleats que guanyen menys de 200000
amb un 10% més.
SQL> UPDATE empl
2 SET empl_salari=empl_salari*1.10, empl_comissio=empl_comissio*1.10
3 WHERE empl_salari<200000;

En el primer exemple s’assigna un nou valor utilitzant una constant de tipus cadena. En
el segon exemple, el nou valor que s’assigna s’obté a partir d’una operació de producte.
En general, el nou valor que assignem es pot obtenir de qualsevol forma per complexa
que sigui, fins i tot a partir de subconsultes.
Exemple: Assignar als empleats del departament 10 el mateix departament que l’empleat
Fernandez.
SQL> UPDATE empl
2 SET empl_dept_num=(
3 SELECT empl_dept_num

58
UD2. Llenguatge SQL DML SQL

4 FROM empl
5 WHERE UPPER(empl_nom)='FERNANDEZ'
6 )
7 WHERE empl_dept_num=10;

Aquest tipus d’actualitzacions només són vàlides si la subconsulta retorna un únic valor i
a més a més que sigui compatible amb el tipus de dades de la columna a actualitzar.
S’ha de tenir molt en compte que les actualitzacions no es poden saltar les regles
d’integritat que tinguin les taules.

59
UD2. Llenguatge SQL DML SQL

Exemple d’error d’integritat:


SQL> UPDATE empl
2 SET empl_dept_num=55
3 WHERE empl_dept_num=10;
ERROR at line 1:
ORA-02291: integrity constraint (MNICOLAU.FK_EMPL_DEPT_NUM) violated-
parent key not found

2.3.4. Eliminació de dades

Es realitza mitjançant la instrucció DELETE.


Sintaxi:
DELETE [FROM] taula
[WHERE condició]

On:
 FROM és opcional en algun SGBDR, com Oracle.

Cal tenir en compte que l’eliminació d’un registre no pot provocar error d’integritat i que la
opció d’integritat ON DELETE CASCADE (veure els apunts de DDL, on es parla de la
creació de claus foranes) fa que no només s’esborrin els registres que compleixen la
condició de la taula indicada, sinó tots els registres relacionats amb els que s’eliminen.
Si no s’especifica la condició del WHERE, s’eliminaran totes les files de la taula.

Exemple: Esborrar els empleats del departament 50


SQL> DELETE FROM empl
WHERE empl_dept_num=50;

Exemple: Esborrar els empleats del departament 20 que guanyen menys que l’empleat
amb el millor sou del departament 30.
SQL> DELETE FROM empl
2 WHERE empl_dept_num = 20 and empl_salari<(
3 SELECT MAX(empl_salari)
4 FROM empl
5 WHERE empl_dept_num=30
);

60
UD2. Llenguatge SQL DML SQL

2.3.5. Utilització dels valors per defecte

Es pot utilitzar la paraula DEFAULT dins una instrucció INSERT o UPDATE com a valor
d’una columna si es vol utilitzar el valor per defecte de la columna en la instrucció
d’inserció o modificació.
Aquesta opció és nova a partir de l’estàndard SQL:1999.
Permet que l’usuari controli on i quan s’ha d’aplicar el valor per defecte.
Exemple: utilització de DEFAULT en una inserció
INSERT INTO dept (dept_num, dept_nom, dept_loc)
VALUES (33,’Enginyeria’,DEFAULT);

Exemple: utilització de DEFAULT en una modificació


UPDATE dept
SET dept_loc = DEFAULT WHERE dept_num = 10;

61
UD2. Llenguatge SQL DDL SQL

Capítol 3. DDL SQL

3.1. Introducció a les sentències de definició

3.1.1. Introducció

Per poder treballar amb BD relacionals, el primer que cal fer és definir-les. Veurem les
instruccions de l’estàndard SQL92 per crear i esborrar una base de dades relacional i per
inserir, esborrar i modificar les diferents taules que la composen.
En aquest apartat també veurem com es defineixen els dominis, les restriccions i les
vistes.
La senzillesa del SQL92 fa que:
Per crear bases de dades, taules, dominis, restriccions, índexs i vistes s’utilitza la
sentència CREATE.
Per modificar taules i dominis s’utilitzi la sentència ALTER.
Per esborrar bases de dades, taules, dominis, restriccions, índexs i vistes s’utilitza la
sentència DROP.

Cal tenir molta cura en utilitzar una sentència DDL, ja que aquestes no poden ser
anul·lades (a diferencia de les sentències d’actualització de dades).

3.1.2. Creació i esborrat d’una BDR

L’estàndard SQL92 no té cap sentència de creació de BD. La idea és que una BD no és


més que un conjunt de taules i, per tant, les sentències que té SQL92 es centren en la
creació, modificació i esborrat d’aquestes taules.
Molts dels SGBDR han incorporat sentències de creació de BD. Amb Oracle, per
exemple, aquesta sentència té la següent sintaxi:
CREATE DATABASE nomBD;

En el cas d’Oracle, només es poden crear BD si es tenen privilegis d’administrador


(DBA).
Aquesta sentència, pot tenir altres paràmetres, com per exemple:
CREATE DATABASE prova
LOGFILE prova.log
MAXLOGFILES 25
MAXINSTANCES 10
ARCHIVELOG
NATIONAL CHARACTER SET UTF8
DATAFILE prova1.dbf AUTOEXTEND ON MAXSIZE 500MB;
L’estàndard SQL, en canvi, té una sentència potser més potent que la creació de BD: la
sentència de creació d’esquemes anomenada CREATE SCHEMA. Amb la creació
d’esquemes es pot agrupar un conjunt d’elements de la BD que són d’un usuari.
La sintaxi d’aquesta sentència amb SQL92 és la següent:
CREATE SCHEMA {nom_esquema | AUTHORIZATION usuari}
[llista_elements_esquema];

62
UD2. Llenguatge SQL DDL SQL

On:
nom_esquema: nom que es vol que tingui l’esquema
AUTHORIZATION usuari: indicar l’usuari de l’esquema (l’esquema tindrà el nom de
l’usuari).
llista_elements_esquema: sentències de creació de taules, vistes, dominis, etc.

Exemple:
CREATE SCHEMA AUTHORIZATION ususari1
CREATE TABLE producte
(color VARCHAR(10) PRIMARY KEY, quantitat NUMBER)
CREATE VIEW producte_view AS
SELECT color, quantitat FROM producte WHERE color = 'vermell'
GRANT select ON producte_view TO usuari1;

La sintaxi d’aquesta sentència amb Oracle és la següent:


CREATE SCHEMA AUTHORIZATION usuari
[llista_elements_esquema];

On:
llista_elements_esquema: només poden ser sentències de creació de taules, vistes
i assignació de permisos.

Per esborrar un esquema hi ha la sentència DROP SCHEMA que té la següent sintaxi:


DROP SCHEMA nomEsquema [RESTRICT|CASCADE];
On:
RESTRICT: només es podrà esborrar l’esquema si no conté cap element.
CASCADE: es pot esborrar l’esquema encara que no estigui buit.

3.1.3. Objectes de BD

La majoria dels SGBDR tenen varis objectes que es poden definir en una BD. Molts
d’ells estan definits en l’estàndard SQL, però altres no. Nosaltres estudiarem el cas
particular dels objectes que podem crear en BD Oracle, èmfasi amb la seva definició
segons l’estàndard ANSI SQL.
Una base de dades Oracle pot tenir varies estructures de dades, cadascuna de les quals
s’ha de descriure en el disseny de la base de dades de manera que es pugui crear
durant la fase de creació del desenvolupament de la BD.
Els tipus d’objectes que es poden crear amb Oracle són:
Objecte Descripció
Taula Unitat bàsica d’emmagatzematge formada per files i columnes.
Vista Representa lògicament subconjunts de dades d’una o més taules.
Seqüència Generador de valor numèric.
Índex Millora el rendiment d’algunes consultes.
Sinònim Noms alternatius a objectes.

3.2. Definició del nivell conceptual: taules i restriccions

63
UD2. Llenguatge SQL DDL SQL

3.2.1. Creació de taules

Per crear una taula s’utilitza la sentència CREATE TABLE.


Sintaxi:
CREATE TABLE [esquema.]nomTaula
(
definicióColumna1
[, definicióColumna2...]
);

On definicióColuma és:
nomColumna {tipusDades|domini} [DEFAULT expr]

On:
nomColumna: és el nom de la columna.
tipusDades: és la mida i tipus de dades de la columna
• domini: és el domini dels valors admesos per la columna (Oracle no té
dominis).

• DEFAULT expr: indica un valor per defecte si no s’indica a l’executar una


sentència INSERT sobre la taula.

Amb Oracle, per executar aquesta sentència cal tenir privilegi CREATE TABLE.

64
UD2. Llenguatge SQL DDL SQL

Regles de nomenclatura
Els noms de les taules i columnes han de seguir les següents regles estàndard:
• Han de començar per una lletra.

• Han de tenir entre 1 i 30 caràcters.

• El nom de bases de dades està limitat a 8 caràcters.

• Només poden tenir els caràcters A-Z, a-z, 0-9, _ (subguió), $ i # (aquests
últims, no és recomanat utilitzar-los).

• Els noms no han de duplicar el nom d’un altre objecte del mateix esquema.

• No pot coincidir amb el nom d’una paraula reservada (CREATE, SELECT,


UPDATE, etc.)

• En el cas que el nom tingui espais en blanc o caràcters nacionals (com la Ç)


s’han de posar entre cometes (en Oracle, amb cometes dobles, en SQL Server
i MySQL amb cometes simples).

Recomanacions:
• Utilitzar noms descriptius per taules i altres objectes de la BD.

• Els noms no són sensibles a majúscules/minúscules. Per exemple, empleat és


el mateix que emPLEat.

L’opció DEFAULT
Sintaxi:
DEFAULT (literal|expr|funció|NULL)

A una columna se li pot assignar un valor per defecte utilitzant l’opció DEFAULT. Aquesta
opció evita que s’introdueixin valors nuls a les columnes si s’insereix una fila sense un
valor per la columna. Si no s’especifica DEFAULT, llavors val NULL.
El valor per defecte pot ser un literal, una expressió o una funció SQL, com SYSDATE
(que dóna la data del sistema) i USER (que indica qui és l’usuari), però el valor no pot
ser el nom d’una altra columna o una pseudocolumna, com NEXTVAL o CURRVAL (que
s’explicaran més endavant). Si s’indica una expressió, el tipus d’aquesta ha de ser igual
al tipus de dades de la columna.
Exemple de creació de taula
CREATE TABLE departament
(
dept_num NUMBER(3)
dept_nom VARCHAR2(14),
dept_loc VARCHAR2(13)
);

Taules de la BD Oracle
Les taules d’usuari són les taules creades per l’usuari, com per exemple,
departament. Hi ha un altre conjunt de taules i vistes a la BD Oracle coneguda com el
diccionari de dades. Aquest conjunt de taules el crea i manté el servidor Oracle i conté
informació sobre la BD.
Totes les taules del diccionari de dades són propietat de l’usuari SYS. L’usuari no
accedeix gairebé mai a les taules de base, ja que la informació que contenen no és fàcil

65
UD2. Llenguatge SQL DDL SQL

d’entendre. Per tant, els usuaris normalment accedeixen a vistes del diccionari de dades,
on la informació es mostra amb un format més senzill d’entendre. La informació que es
guarda al diccionari de dades inclou noms dels usuaris, privilegis dels usuaris, noms
d’objectes de la BD, restriccions de taules i informació d’auditoria.
Hi ha quatre categories de vistes del diccionari de dades; cadascuna té un prefix diferent
que indica la seva utilitat:
Prefix Descripció
USER_ Vistes amb informació sobre els objectes propietat de l’usuari.
ALL_ Vistes amb informació sobre totes les taules accessibles per
l’usuari.
DBA_ Vistes restringides i només hi poden accedir persones amb el rol
DBA.
V$ Vistes de rendiment dinàmiques, rendiment del servidor de BD,
memòria i bloqueig.

Consulta del diccionari de dades Oracle


Es poden consultar les taules del diccionari de dades per veure els diferents objectes de
BD. Les taules del diccionari de dades que s’utilitzen normalment són:
• USER_TABLES

• USER_OBJECTS

• USER_CATALOG

Té un sinònim anomenat CAT. Es pot utilitzar aquest sinònim enlloc de USER_CATALOG.


Exemple 1: veure les taules de l’usuari
SELECT table_name
FROM user_tables;

Exemple 2: veure els tipus d’objectes de l’usuari


SELECT DISTINCT object_type
FROM user_objects;

66
UD2. Llenguatge SQL DDL SQL

Exemple 3: veure les taules de l’usuari


SELECT *
FROM cat;

Tipus de dades
Per cada columna cal escollir entre algun domini definit per l’usuari o algun dels tipus de
dades predefinits següents:
Descripció ANSI SQL ORACLE SQL
Text de CHARACTER(n) CHAR(n)
longitud fixe CHAR(n) n: entre 1 (per defecte) i
2000
Text de CHARACTER VARYING(n) VARCHAR2(n)
longitud CHAR VARYING(n) n: entre 1 i 4000
variable
Text de NATIONAL CHARACTER(n) NCHAR(n)
longitud fixa NATIONAL CHAR(n)
per caràcters NCHAR(n)
nacionals
Text de NATIONAL CHARACTER NVARCHAR2(n)
longitud VARYING(n)
variable per NATIONAL CHAR VARYING(n)
NCHAR VARYING(n)
caràcters
nacionals
Text gran LOB LONG (fins a 2GB) i CLOB (fins a
4GB)
Cadena de BIT(n) RAW(n) (fins a 2000B)
bits de LONG RAW (fins a 2GB)
longitud fixe BLOB (fins a 4GB)
BFILE (a un fitxer extern; fins a
4GB)
Cadena de BIT VARYING(n) RAW(n) (fins a 2000B)
bits de LONG RAW (fins a 2GB)
longitud BLOB (fins a 4GB)
variable BFILE (a un fitxer extern;
fins a 4GB)
Números de NUMERIC(p,s) p: precisió (total de dígits).
longitud variable DECIMAL(p,s) De 1 a 38
NUMBER(p,s) s: escala (dígits a la dreta
de la coma decimal). De -
84 a 127
Números enters INTEGER
INT
SMALLINT
Números de FLOAT(p)
coma flotant DOUBLE PRECISION
REAL
Data i hora DATE  DATE
YEAR (0001..9999) Valors de data i hora entre
MOTNH (01..12) 4712 a.C i el 31-12-9999
DAY(01..31) d.C
TIME 
HOUR (00..23) TIMESTAMP
MINUT(00..59)
Any, mes, dia, hora, minut,

67
UD2. Llenguatge SQL DDL SQL

SECOND(00..59.precisió) segon i segon fraccionat.


TIMESTAMP 
YEAR (0001..9999) INTERVAL YEAR TO MONTH
MOTNH (01..12) Guarda la data com
DAY(01..31)
interval d’anys i mesos.
HOUR (00..23)
MINUT(00..59)
INTERVAL DAY TO SECOND
SECOND(00..59.precisió)
C Guarda el temps com
o interval de dies i hores,
n minuts i segons.
sideracions:

• Tipus NUMBER d’Oracle

Format L’usuari escriu… S’emmagatzema com…


NUMBER 3452255.345 3452255.345
NUMBER(9) 3452255.345 3452255
NUMBER(9,2) 3452255.345 3452255.35
NUMBER(7) 3452255.345 3452255
NUMBER(7,-2) 3452255.345 345300
NUMBER(7,2) 3452255.345 Error de precisió

Si el valor de l’escala és negatiu indica el número de zeros a l’esquerra del


símbol decimal.

• Tipus LONG, LOB, CLOB, BLOB i RAW

Amb Oracle, una columna d’aquest tipus no pot formar part de la clau, ni d’un
índex.

Només hi pot haver una columna d’aquests tipus a una mateixa taula.

• Data i hora

DATE

 Les dades d’aquest tipus van entre cometes simples ‘ ‘ (igual que les
dades textuals).

 El separador entre el dia, el mes i l’any pot ser una barra de divisió (/),
una guió (-) i altres símbols.

 SYSDATE és una funció d’Oracle que permet obtenir la data actual del
sistema.

TIMESTAMP

 És una extensió de l’anterior.

 Exemple: ‘2/2/2004 18:34:23,34521’

Dominis
Creació de dominis

68
UD2. Llenguatge SQL DDL SQL

A part dels dominis representats pels tipus de dades predefinits, SQL92 ofereix la
possibilitat de treballar amb dominis definits per l’usuari.
Per crear un domini s’utilitza la sentència CREATE DOMAIN. La seva sintaxi és:
CREATE DOMAIN nomDomini [AS] tipusDades
[DEFAULT expr] [restriccionsDomini];

On restriccionsDomini té la següent sintaxi:


[CONSTRAINT nomRestricció] CHECK (condicions)

Exemple: definir un domini per les ciutats on hi ha departaments de l’empresa.


CREATE DOMAIN domCiutats AS CHAR(20)
CONSTRAINT ciutatsValides
CHECK (VALUE IN (‘Barcelona’,’Tarragona’,’Lleida’,’Girona’));

Quan es defineixi una columna, per exemple amb nom ciutat, dins la taula
departament, no s’hauria de definir amb tipus CHAR(20), sinó de tipus domCiutats.
Això assegura, segons el model relacional, que només farem operacions sobre la
columna ciutat amb altres columnes que tenen aquest mateix domini definit per
l’usuari. No obstant, SQL92 no té les eines per assegurar que les comparacions que fem
siguin entre els mateixos dominis definits per l’usuari.
Per exemple, si tenim una columna amb els noms dels treballadors definida sobre el
tipus de dades CHAR(20), SQL permet comparar-la amb la columna ciutat, tot i que
semànticament no tingui sentit. En canvi, segons els model relacional, aquesta
comparació no s’hauria de permetre.
Esborrar dominis

Per esborrar un domini s’utilitza la sentència DROP DOMAIN. La seva sintaxi és:
DROP DOMAIN nomDomini {RESTRICT|CASCADE};

On:
• RESTRICT fa que el domini només s’esborri si no s’utilitza a cap lloc.

• CASCADE esborra el domini encara que estigui referenciat, i posa el tipus de


dades del domini allà on s’utilitza.

Exemple: esborrar el domini creat anteriorment.


DROP DOMAIN domCiutats RESTRICT;

Modificar dominis

Per modificar un domini s’utilitza la sentència ALTER DOMAIN. La seva sintaxi és:
ALTER DOMAIN nomDomini {acció_modif_domini|
acció_modif_restricció_domini};
On:
• acció_modif_domini pot ser:

{SET DEFAULT expr|DROP DEFAULT}

• acció_modif_restricció_domini pot ser:

{ADD restricció_domini|DROP CONSTRAINT nom_restricció}

69
UD2. Llenguatge SQL DDL SQL

Exemple: afegir una ciutat (Olot) al domini que hem creat abans.
ALTER DOMAIN domCiutats DROP CONSTRAINT ciutatsValides;

Amb això s’ha esborrat la restricció del domini. Ara cal afegir la nova restricció:
ALTER DOMAIN domCiutats ADD CONSTRAINT ciutatsValides
CHECK (VALUE IN (‘Barcelona’,’Tarragona’,’Lleida’,’Girona’,’Olot’));

3.2.2. Modificar l’estructura de taules

Després de crear una taula, és possible que calgui canviar la seva estructura per
qualsevol motiu (ens hem oblidat d’una columna, el tipus de dades d’una columna no és
correcte, etc.). Per poder fer aquestes tasques, s’utilitza la sentència ALTER TABLE.
Per tant, amb ALTER TABLE es pot:
• Afegir una nova columna.

• Modificar una columna.

• Definir un valor per defecte per la nova columna.

• Esborrar una columna.

Afegir una columna


Sintaxi:
ALTER TABLE nomTaula ADD
(
nomCol tipusDades [DEFAULT expr]
[,nomCol tipusDades ...]
);

Exemple: afegir una columna a la taula de departament.


ALTER TABLE departament ADD
(
codiTreball CHAR(3)
);

A tenir en compte amb Oracle:

• La nova columna passa ser l’última. No hi ha manera de dir a quina posició


s’ha de col·locar la columna.

• Si afegim una nova columna a una taula que ja té files de dades, totes les files
inicialment tindran valor NUL per aquesta nova columna.

Modificar una columna


Permet canviar el tipus de dades, la mida i el valor per defecte d’una columna.
Sintaxi:
ALTER TABLE nomTaula MODIFY
(
nomCol tipusDades [DEFAULT expr]
[,nomCol tipusDades...]
);

70
UD2. Llenguatge SQL DDL SQL

Exemple: modificar el tipus de dades d’una columna de la taula de departament.


ALTER TABLE departament MODIFY
(
cognom CHAR(30)
);

A tenir en compte amb Oracle:

• Es pot augmentar la precisió o l’escala d’una columna numèrica.

• Es pot augmentar la mida de columnes numèriques o de caràcters.

• Es pot disminuir la mida d’una columna només si aquesta conté només valors
nuls o si la taula no té files.

• Es pot canviar el tipus de dades només si la columna conté valors nuls.

• Es pot convertir una columna CHAR amb VARCHAR2 o convertir una columna
VARCHAR2 amb CHAR només si la columna conté valors nuls o si no canvia
la mida.

• Cal tenir present que un canvi en el valor per defecte només afecta a les
insercions posteriors al canvi.

Esborrar una columna


Sintaxi:
ALTER TABLE nomTaula DROP (nomCol);

Exemple: esborrar una columna de la taula de departament.


ALTER TABLE departament DROP (codiTreball);

A tenir en compte amb Oracle:

• La columna pot tenir o no dades.

• Només es pot esborrar una columna cada vegada.

• La taula ha de tenir com a mínim una columna després de la modificació.

• Un cop esborrada la columna, no es pot recuperar.

Canviar el nom d’una columna


Sintaxi:
ALTER TABLE nomTaula RENAME COLUMN nomAntic TO nomNou;

Opció SET UNUSED d’Oracle


L’opció SET UNUSED marca una o varies columnes com a no utilitzades perquè es
puguin esborrar quan la demanda de recursos del sistema és menor. Aquesta funció
està disponible a partir de Oracle8i.

71
UD2. Llenguatge SQL DDL SQL

Quan s’indica aquesta clàusula no s’eliminen realment les columnes de destí de cada fila
de la taula (no es restaura l’espai de disc utilitzat per aquestes columnes). Per tant, el
temps de resposta és menor que si s’executés la sentència DROP. Les columnes no
utilitzades es consideren esborrades, tot i que les seves dades estiguin a les files de la
taula.
Un cop una columna està marcada com a no utilitzada, no s’hi pot accedir. Una consulta
SELECT * no dóna dades de les columnes no utilitzades. Tampoc es mostren en el
llistat de la comanda DESCRIBE. Fins i tot, es pot afegir una nova columna a la taula
amb el mateix nom que la no utilitzada.
La informació de SET UNUSED es guarda a la vista del diccionari
USER_UNUSED_COL_TABS.

72
UD2. Llenguatge SQL DDL SQL

Sintaxi:
ALTER TABLE nomTaula
SET UNUSED (nomColumna);

O bé

ALTER TABLE nomTaula


SET UNUSED COLUMN nomColumna;

Opció DROP UNUSED COLUMNS d’Oracle


L’opció DROP UNUSED COLUMNS elimina de la taula totes les columnes marcades
actualment com a no utilitzades. Es pot utilitzar aquesta sentència per reclamar l’espai
de disc addicional de les columnes que no s’utilitzen de la taula. Si la taula no conté
columnes no utilitzades, la sentència no dóna cap error.
Sintaxi:
ALTER TABLE nomTaula
DROP UNUSED COLUMNS;

3.2.3. Eliminar l’estructura de taules

La sentència DROP TABLE elimina la definició d’una taula.


Sintaxi:
DROP TABLE nomTaula;

A tenir en compte amb Oracle:

• S’esborren totes les dades de la taula.

• S’esborren tots els índexs associats a la taula.

• Les vistes i sinònims associats a la taula continuen essent-hi, però no són


vàlids.

• Es valida qualsevol transacció pendent.

• Només pot eliminar una taula el seu creador o un usuari amb privilegi DROP
ANY TABLE.

• És una sentència irreversible i Oracle no demana confirmació a l’hora


d’eliminar-la.

73
UD2. Llenguatge SQL DDL SQL

3.2.4. Canviar el nom de taules (Oracle)

La sentència RENAME permet canviar el nom d’una taula, una vista, una seqüència o un
sinònim.
Sintaxi:
RENAME nomVell TO nomNou;

Cal ser-ne propietari per poder fer el canvi de nom.

3.2.5. Esborrar el contingut d’una taula (Oracle)

Esborrar els continguts d’una taula o truncar una taula elimina totes les files de la taula i
allibera l’espai que ocupa aquesta taula.
Sintaxi:
TRUNCATE TABLE nomTaula;

Cal ser-ne propietari o tenir permisos DELETE TABLE per poder truncar una taula.
Amb SQL hi ha la sentència DELETE que també permet eliminar totes les files d’una
taula, però no allibera l’espai de disc ocupat. La sentència TRUNCATE és més ràpida que
DELETE per eliminar files, ja que:
• TRUNCATE és una sentència del llenguatge de definició de dades i no genera
informació de rollback (“tornar enrere”).

• Truncar una taula no engega els disparadors (triggers) d’eliminació de la taula.

• Si la taula és la principal en una restricció d’integritat referencial, no es pot


truncar. Abans caldrà desactivar la restricció.

3.2.6. Restriccions

Introducció
Les restriccions són normes que es fan complir a les dades. En el cas d’Oracle, es
poden utilitzar les restriccions per:
• Forçar regles sobre les dades d’una taula quan s’insereix, actualitza o elimina
una fila de la taula. La restricció s’ha de complir per tal que es faci
correctament l’operació.

• Evitar l’eliminació d’una taula si hi ha dependències d’altres taules.

L’estàndard SQL92 defineix les següents restriccions d’integritat de les dades:


Restricció model Restricció Descripció
relacional SQL92
Integritat d’entitat NOT NULL Indica que una columna no pot tenir un
valor nul.
Clau UNIQUE Indica que una columna o una combinació
de columnes han de tenir valors únics en
totes les files de la taula.
Clau PRIMARY KEY Identifica de forma única cada fila de la
taula.

74
UD2. Llenguatge SQL DDL SQL

Integritat FOREIGN KEY Estableix i força una relació de clau forana


referencial entre la columna i una columna de la taula
a la que es fa referència.
Domini CHECK Indica una condició que ha de ser certa.

Definició de restriccions
Podem definir les restriccions mentre es crea una taula o després de crear la taula.
La sintaxi per definir les restriccions mentre es crea la taula és:
CREATE TABLE [esquema.]nomTaula
(
columna tipus [DEFAULT expr] [restriccióColumna],
...
[restriccióTaula] [,...]
);

On:
• restriccióColumna : restricció d’integritat com a part de la definició de
columna. Fa referència a una única columna.

• restriccióTaula : restricció d’integritat com a part de la definició de taula.


Fa referència a una o varies columnes i es defineix per separat des de les
definicions de les columnes de taula. Pot definir qualsevol restricció menys
NOT NULL.

Les restriccions també es poden afegir a una taula després d’haver-la crear i també es
poden desactivar temporalment.

La sintaxi de la restricció a nivell de columna és:


definicióColumna [CONSTRAINT nomRestricció] tipusRestricció,

On:
• nomRestricció : és un nom que podem donar a la restricció (molt
recomanat!)

• tipusRestricció: és una de les restriccions de la taula de la pàgina


anterior.

La sintaxi de la restricció a nivell de taula és:


definicióColumna, ...
[CONSTRAINT nomRestricció] tipusRestricció(columna,...),

On:
• nomRestricció : és un nom que podem donar a la restricció (molt
recomanat!)

• tipusRestricció: és una de les restriccions de la taula de la pàgina


anterior.

• columna: és la columna/es a les que fa referència la restricció.

Noms de restricció amb Oracle


Amb Oracle (i també la majoria dels SGBDR) les restriccions es guarden al diccionari de
dades i es fàcil fer-hi referència si se’ls hi assigna un nom significatiu.

75
UD2. Llenguatge SQL DDL SQL

Els noms de restriccions ha de seguir les normes estàndard de nomenclatura d’objectes


(veure 3.1.1). Si no s’assigna nom a una restricció, Oracle genera un nom amb el format
SYS_Cn, on n és un enter de manera que el nom de la restricció sigui únic, ja que no es
poden repetir dins el mateix esquema de base de dades.
Les restriccions es poden definir en el moment de la creació de la taula o un cop ja
creada.
Com a conveni, pel nom de les restriccions utilitzarem la següent nomenclatura:
Restricció Nom de la restricció
NOT NULL NN_taula_columna
UNIQUE UK_taula_columna
PRIMARY KEY PK_taula
FOREIGN KEY FK_taula_columna
CHECK CK_taula_columna

Podem veure les restriccions definides a una taula consultant a la taula del diccionari de
dades USER_CONSTRAINTS.
La restricció NOT NULL
La restricció NOT NULL assegura que la columna no conté valors nuls. Cal recordar que
no es pot definir a nivell de taula; tant sols a nivell de columna
Les columnes sense aquesta restricció poden tenir valors nuls per defecte.

76
UD2. Llenguatge SQL DDL SQL

Exemple:
CREATE TABLE empleat
(
codi NUMBER(6),
nom VARCHAR2(30) NOT NULL,
cognom VARCHAR2(30),
sou NUMBER(8,2),
comissio NUMBER(2,2),
dataAlta DATE CONSTRAINT NN_empleat_dataAlta NOT NULL,
...
);

Com es pot veure a l’exemple, s’aplica la restricció NOT NULL a les columnes nom i
dataAlta. En el primer cas no s’ha especificat cap nom de restricció, per la qual cosa
Oracle li donarà un nom que tindrà la forma indicada anteriorment. En el segon cas s’ha
donat el nom NN_empleat_dataAlta a la restricció, on NN indica NOT NULL, empleat
indica la taula sobre la que s’estableix la restricció i dataAlta la columna on s’inclou la
restricció.

La restricció UNIQUE
Amb una restricció d’integritat de clau UNIQUE es garanteix que no pot haver-hi dues
files d’una taula que tinguin valors duplicats en una columna o conjunt de columnes
indicat.
La columna (o conjunt de columnes) inclosa a la definició de la restricció UNIQUE
s’anomena clau única. Si la restricció UNIQUE està formada per més d'una columna, el
grup de columnes s’anomena clau única composta.
Les restriccions UNIQUE permeten l’entrada de valors nuls a no ser que també defineixi
restriccions NOT NULL per les mateixes columnes.
Exemple:
CREATE TABLE empleat
(
codi NUMBER(6),
nom VARCHAR2(30) NOT NULL,
cognom VARCHAR2(30),
email VARCHAR2(40) CONSTRAINT UK_empleat_email,
sou NUMBER(8,2),
comissio NUMBER(2,2),
dataAlta DATE CONSTRAINT NN_empleat_dataAlta NOT NULL,
...
);

Es poden crear restriccions UNIQUE a nivell de columna o de taula, però les restriccions
UNIQUE compostes només es poden crear a nivell de taula.
NOTA: En el cas d’Oracle, si es crea un índex únic, crea automàticament una restricció
UNIQUE a la columna o les columnes on s’hagi definit l’índex.
La restricció PRIMARY KEY
Una restricció PRIMARY KEY crea una clau primària per la taula. Només es pot crear
una clau primària per cada taula.
La restricció PRIMARY KEY és una columna o conjunt de columnes que identifica de
forma única a cada fila d’una taula. Definint aquesta restricció es defineixen
implícitament les restriccions NOT NULL i UNIQUE.

77
UD2. Llenguatge SQL DDL SQL

Exemple:
CREATE TABLE departament
(
codi NUMBER(3),
nom VARCHAR2(30) CONSTRAINT NN_dept_nom NOT NULL,
localitat VARCHAR2(20),
CONSTRAINT PK_dept PRIMARY KEY(codi)
...
);

A l’exemple es defineix una restricció PRIMARY KEY a la columna codi de la taula


departament.
Es poden crear restriccions PRIMARY KEY a nivell de columna o de taula, però les
restriccions PRIMARY KEY compostes només es poden crear a nivell de taula.
Dins una taula només pot haver-hi una restricció PRIMARY KEY, però vàries restriccions
UNIQUE.
NOTA: En el cas d’Oracle, es crea un índex UNIQUE automàticament per una columna
PRIMARY KEY.
La restricció FOREIGN KEY
Una restricció FOREIGN KEY, o restricció d’integritat referencial, defineix una columna o
conjunt de columnes com clau forana i estableix una relació entre una clau primària o
una clau única a la mateixa taula o en una de diferent.
Quan es crea una clau forana cal tenir en compte que el domini de les claus que es
relacionen ha de ser el mateix.
Exemple:
CREATE TABLE empleat
(
codi NUMBER(6),
nom VARCHAR2(30) NOT NULL,
cognom VARCHAR2(30),
email VARCHAR2(40) CONSTRAINT UK_empleat_email,
sou NUMBER(8,2),
comissio NUMBER(2,2),
dataAlta DATE CONSTRAINT NN_empleat_dataAlta NOT NULL,
...
codiDept NUMBER(3),
CONSTRAINT FK_empleat_codiDept FOREIGN KEY (codiDept)
REFERENCES departament(codi)
);

Es poden crear restriccions FOREIGN KEY a nivell de columna o de taula, però les
restriccions FOREIGN KEY compostes només es poden crear a nivell de taula.
A l’exemple es defineix una restricció FOREIGN KEY a la columna codiDept de la taula
empleat, utilitzant la sintaxi a nivell de taula.
La clau forana també es pot definir a nivell de columna, sempre que la restricció es basi
en una única columna. La sintaxi es diferencia en que no hi ha les paraules FOREIGN
KEY.
Exemple:
CREATE TABLE empleat
(
...
codiDept NUMBER(3) CONSTRAINT FK_empleat_codiDept
REFERENCES departament(codi),
...
);

78
UD2. Llenguatge SQL DDL SQL

Quan definim una clau forana hem dit que estem establint una regla d’integritat
referencial. Quan vam estudiar el model relacional, vam veure que la integritat referencial
podia provocar problemes en certs casos. Concretament, en l’eliminació o actualització
de files de la taula principal.
• Eliminació de files a la taula principal

Quan s’eliminen files de la taula principal que tenen files relacionades de la


taula secundària, Oracle no ho permet.

Per solucionar-ho, Oracle ofereix dues solucions a aquest problema, que


consisteix en afegir aquestes clàusules:

• ON DELETE SET NULL: converteix a NULL els valors de la clau


forana de la taula secundària quan s’esborra el valor de la
principal.

• ON DELETE CASCADE: quan s’esborra la fila de la taula principal,


també s’esborraran les files que en depenen de la taula
secundària.

Sense les opcions ON DELETE CASCADE o ON DELETE SET NULL, la fila


de la taula principal no es pot suprimir si a la taula secundària s’hi fa
referència.

• Actualització de files a la taula principal

Oracle no té cap mecanisme directe per solucionar això, com passa amb el
cas anterior. La única solució que es pot adoptar en aquest cas és la
implementació de disparadors (triggers).

Cal tenir present que amb Oracle, que per defecte no es permet l’actualització o la
supressió de les dades a les que es fa referència.
Exemple 1: eliminar les files de la taula empleat si s’esborra la fila de qui depèn a la
taula departament.
CREATE TABLE empleat
(
...
codiDept NUMBER(3) CONSTRAINT FK_empleat_codiDept
REFERENCES departament(codi) ON DELETE CASCADE,
...
);
Exemple 2: posar a null el valor de la columna codiDept a les files de la taula empleat
si s’esborra la fila de qui depèn a la taula departament.
CREATE TABLE empleat
(
...
codiDept NUMBER(3) CONSTRAINT FK_empleat_codiDept
REFERENCES departament(codi) ON DELETE SET NULL,
...
);

La restricció CHECK
La restricció CHECK defineix una condició que ha de complir cada fila.

79
UD2. Llenguatge SQL DDL SQL

En la definició de la condició s’ha de complir:


• No es pot fer referències a les pseudocolumnes CURRVAL, NEXTVAL, LEVEL i
ROWNUM.

• No es poden utilitzar les funcions SYSDATE, UID, USER i USERENV.

• No es pot fer referències a columnes d’altres taules (però si a les de la


mateixa taula).

Una mateixa columna pot tenir vàries restriccions CHECK que fan referència a la columna
en la seva definició. No hi ha límit en el número de restriccions CHECK que es poden
definir en una columna.
Exemple:

CREATE TABLE empleat


(
codi NUMBER(6),
nom VARCHAR2(30) NOT NULL,
cognom VARCHAR2(30),
email VARCHAR2(40) CONSTRAINT UK_empleat_email,
sou NUMBER(8,2)
CONSTRAINT NN_empleat_sou NOT NULL
CONSTRAINT CK_empleat_sou_min CHECK (sou>0)
CONSTRAINT CK_empleat_sou_max CHECK (sou<6000),
comissio NUMBER(2,2),
dataAlta DATE CONSTRAINT NN_empleat_dataAlta NOT NULL,
...
codiDept NUMBER(3),
CONSTRAINT FK_empleat_codiDept FOREIGN KEY (codiDept)
REFERENCES departament(codi),
CONSTRAINT CK_empleat_comissio (comissio<=(sou/10))
);

Es poden definir restriccions CHECK a nivell de columna o de taula


En l’exemple es pot veure com es poden definir vàries restriccions sobre una mateixa
columna (ULL!, per separar les restriccions no es posa cap coma, tant sols un espai!!!!).
La restricció CK_empleat_comissio de l’exemple es defineix com una restricció de
taula ja que la condició fa referència a diferents columnes de la taula. Aquesta restricció
indica que la comissio no pot ser superior al 10% del sou.
Afegir una restricció
Es pot afegir una restricció a taules que ja estan creades utilitzant la sentència ALTER
TABLE amb la clàusula ADD.
Sintaxi:
ALTER TABLE [esquema.]nomTaula
ADD [CONSTRAINT nomRestricció] tipusRestricció (columna);

On:
• nomRestricció : és un nom de la restricció.

• tipusRestricció: és el tipus de restricció que es vol crear.

• columna: és el nom de la columna/es afectada/es per la restricció.

80
UD2. Llenguatge SQL DDL SQL

Consideracions:

• Es pot afegir, esborrar, activar o desactivar una restricció, però no modificar la


seva estructura.

• Es pot afegir una restricció NOT NULL a una columna que ja existeix utilitzant
la clàusula MODIFY de la sentència ALTER TABLE.

 Només es pot fer si la taula està buida o si la columna té un valor per


cada fila.

Exemple: afegir restricció clau forana a la taula empleat que indiqui que ha d’existir un
director com empleat vàlid a la taula empleat.

ALTER TABLE empleat


ADD CONSTRAINT FK_empleat_codiDirector
FOREIGN KEY(codiDirector) REFERENCES empleat(codi);

Esborrar una restricció


Per esborrar una restricció, es pot trobar quina és la restricció que volem esborrar
utilitzant les vistes del diccionari de dades USER_CONSTRAINTS i
USER_CONS_COLUMNS. Tot seguit, per dur a terme l’acció d’esborrat, s’utilitza la
sentència ALTER TABLE amb la clàusula DROP.
Sintaxi:
ALTER TABLE [esquema.]nomTaula
DROP PRIMARY KEY | UNIQUE(nomColumna) |
CONSTRAINT nomRestricció [CASCADE];

On:
• columna: és el nom de la columna/es afectada/es per la restricció

• nomRestricció : és un nom de la restricció.

• CASCADE: fa que totes les restriccions que depenen d’aquesta també


s’esborrin.

Exemple: donada la següent taula que guarda informació de cursos


CREATE TABLE curs
(
codi CHAR(7) PRIMARY KEY,
dataIni DATE,
dataFi DATE,
titol VARCHAR2(60),
codiSegCurs CHAR(7),
CONSTRAINT CK_curs_dataFi CHECK(dataFi>dataIni),
CONSTRAINT FC_curs_codiSeg
FOREIGN KEY(codiSegCurs)
REFERENCES curs ON DELETE SET NULL
);

Si s’executa la següent sentència:


ALTER TABLE curs DROP PRIMARY KEY;

81
UD2. Llenguatge SQL DDL SQL

ORA-02273: a esta clave única/primaria hacen referencia algunas


claves ajenas

Produeix aquest error perquè hi ha claus foranes d’altres taules o de la mateixa que fan
referència a la clau primària de la taula curs.
Per solucionar aquest problema, s’hauria d’utilitzar la sentència:
ALTER TABLE curs DROP PRIMARY KEY CASCADE;

Aquesta sentència esborra la clau forana abans d’esborrar la clau primària.


També produeix error aquesta sentència:
ALTER TABLE curs DROP(dataIni);

ERROR en línea 1:
ORA-12991: se hace referencia a la columna en una restricción
de multicolumna
La solució passa també per esborrar amb cascada:
ALTER TABLE curs DROP(dataIni) CASCADE CONSTRAINTS;

Amb aquesta sentència s’esborra la restricció CHECK que hi havia sobre la columna
dataIni.

Desactivació de restriccions
Es poden desactivar restriccions sense esborrar-les ni tornar a crear-les.
Sintaxi:
ALTER TABLE [esquema.]nomTaula
DISABLE CONSTRAINT nomRestricció [CASCADE];

On:
• nomRestricció : és un nom de la restricció.

• CASCADE: fa que totes les restriccions que depenen d’aquesta també es


desactivin.

Consideracions:

• Es pot utilitzar la clàusula DISABLE tant dins la sentència CREATE TABLE com
dins ALTER TABLE.

• CASCADE desactiva restriccions d’integritat que són dependents d’altres.

• La desactivació d’una restricció de clau primària o única elimina l’índex únic.

Exemple:
ALTER TABLE empleat
DISABLE CONSTRAINT PK_empleat CASCADE;
Activació de restriccions
Es poden desactivar restriccions sense esborrar-les ni tornar a crear-les.

82
UD2. Llenguatge SQL DDL SQL

Sintaxi:
ALTER TABLE [esquema.]nomTaula
ENABLE CONSTRAINT nomRestricció;

Consideracions:

• Si s’activa una restricció, s’aplica a totes les dades de la taula, que s’han
d’ajustar a la restricció.

• Si s’activa una restricció de clau UNIQUE o PRIMARY KEY, es crea


automàticament un índex UNIQUE o PRIMARY KEY.

• Es pot utilitzar la clàusula ENABLE tant dins la sentència CREATE TABLE com
dins ALTER TABLE.

• L’activació d’una restricció de clau primària desactivada amb l’opció CASCADE


no activa cap clau forana que depengui de la primària.

Exemple:
ALTER TABLE empleat
ENABLE CONSTRAINT PK_empleat;

Canvi de nom de restriccions


Oracle permet canviar el nom de les restriccions.
Sintaxi:
ALTER TABLE [esquema.]nomTaula
RENAME CONSTRAINT nomAntic TO nomNou;

Mostrar les restriccions


Després de crear una taula, es pot comprovar que s’ha creat amb la comanda
DESCRIBE. Ara bé, amb DESCRIBE només es poden veure les restriccions NOT NULL.
Per poder veure totes les restriccions d’una taula, cal consultar la vista del diccionari de
dades USER_CONSTRAINTS.
Exemple:

SELECT constraint_name, constraint_type, search_condition


FROM user_constraints
WHERE table_name = ‘empleat’;

Els possibles tipus de restricció que es poden mostrar per constraint_type són:
Restricció constraint_type
NOT NULL C (is NOT NULL)
UNIQUE U
PRIMARY KEY P
FOREIGN KEY R
CHECK C

Mostrar les columnes associades a restriccions

83
UD2. Llenguatge SQL DDL SQL

Consultant la vista del diccionari de dades USER_CONS_COLUMNS es poden veure els


noms de les columnes implicades en restriccions. És molt útil consultar aquesta vista
sobretot per consultar les columnes associades a restriccions que tenen noms associats
pel sistema.
Exemple:
SELECT constraint_name, column_name
FROM user_cons_columns
WHERE table_name = ‘empleat’;

84
UD2. Llenguatge SQL DDL SQL

3.3. Definir el nivell intern: índexs

3.3.1. Introducció

Els índexs són objectes d’esquema que fan que el SGBD acceleri les operacions de
consulta i ordenació sobre els camps als que l’índex fa referència. Si no es té un índex a
una columna per la qual es fa una consulta o ordenació, l’operació en qüestió fa una
exploració completa de la taula.
Per tant, un índex proporciona accés directe i ràpid a les files d’una taula. El seu objectiu
és reduir la necessitat de fer operacions d’E/S de disc utilitzant un accés indexat per
trobar les dades ràpidament. En el cas d’Oracle, utilitza i manté els índexs
automàticament i, un cop creat l’índex, l’usuari no ha de fer cap operació sobre l’índex.
Es guarden a part de la taula a la que fa referència, el que permet crear-los i esborrar-los
en qualsevol moment (són independents lògica i físicament de la taula).
Els índexs gestionen una llista ordenada per la que el SGBD pot accedir-hi per facilitar la
cerca de les dades. Cada vegada que s’afegeix un nou registre, els índexs afectats
s’actualitzen per tal que la seva informació estigui actualitzada en tot moment. D’aquí ve
el problema de que quants més índexs hi hagi, té un cost major pel SGBD afegir
registres, però més ràpides són les instruccions de consulta.
La majoria dels índexs es creen de forma implícita, com a conseqüència de les
restriccions PRIMARY KEY (que obliga a crear un índex únic sobre els camps clau),
UNIQUE (crea també un índex únic) i FOREIGN KEY (crea un índex amb possibilitat de
repetir valors, índex amb duplicats). Aquests índexs són obligatoris, i gairebé sempre els
crea el mateix SGBD.
Cal tenir en compte que quan s’esborra un índex també s’esborren els índexs que en
depenen.
Una etiqueta d’índex es pot considerar com una taula de dues columnes, tal i com es
mostra a continuació:

CLAUS REGISTRE
ÍNDEX

Valors de les files en les Número de registre de la fila


columnes que constitueixen que es correspon amb el valor
Exemple: l’índex, situats segons l’ordre de l’índex.
especificat.
clau registre registre Clau índex plantilla_nom
índe (plantilla_empleat_n
x um)
3106 2 1 3754 Diaz B.
3754 1 2 3106 Hernandez
3855 20 J.
… … 3 6357 Karplus W.
… …
0020 9
0021 8

85
UD2. Llenguatge SQL DDL SQL

3.3.2. Creació d’índexs

Es poden crear dos tipus d’índexs:


• Índex únic: Oracle el crea automàticament quan es defineix una columna a
una taula amb una restricció PRIMARY KEY o UNIQUE. El nom de l’índex és
el nom que s’ha assignat a la restricció. També és pot crear un índex únic
manualment, però és millor crear una restricció única que ja crea un índex
únic.

• Índex no únic: el pot crear l’usuari. Per exemple, es pot crear un índex de
columna FOREIGN KEY per fer una combinació dins una consulta per millorar
la velocitat de recuperació de les files.

Sintaxi:
CREATE [UNIQUE] INDEX nomIndex
ON nomTaula (columna [ASC|DESC] [,columna [ASC|DESC]...] );

Cal tenir en compte que a l’hora de crear l’índex:


• Per defecte es defineix en ordre ascendent. Si es vol un ordre descendent,
s’ha d’indicar.


Exemple:
SQL> CREATE INDEX i_empleat_nom_ofici ON empl (empl_nom, empl_ofici);

A l’exemple es crea un índex pels camps nom i ofici. Això no és el mateix que fer un
índex per cada camp. Aquest tipus d’índex l’utilitza el SGBD quan es cerquen o ordenen
empleats utilitzant els dos camps a la vegada.
És aconsellable crear índexs en columnes que:
• Tinguin una gran quantitat de valors.

• Tinguin una gran quantitat de valors NULL.

• Una o més columnes s’utilitzen juntes habitualment dins una clàusula WHERE o
dins una condició de combinació.

• Habitualment formen part de clàusules WHERE, GROUP BY o ORDER BY.

• Formen part de llistats de consultes de grans taules sobre les que gairebé
sempre es mostren com a molt el 4% de les files.

No és aconsellable en columnes que:


• Pertanyin a taules petites.

• No s’utilitzen habitualment en la clàusula WHERE de consultes.

• S’espera que la majoria de les consultes recuperaran més del 2-4% de les files
de la taula.

• Pertanyen a taules que s’actualitzen habitualment.

• S’utilitzen dins d’expressions.

86
UD2. Llenguatge SQL DDL SQL

3.3.3. Índexs basats en funcions

Els índexs també es poden crear utilitzant expressions complexes:


CREATE INDEX i_empleat_nomt ON empl (UPPER(empl_nom));

Aquest tipus d’índexs tenen sentit si en les consultes s’utilitzen exactament aquestes
expressions (en l’exemple UPPER(empl_nom)). Si no s’utilitza aquesta expressió però,
per exemple, s’utilitza empl_nom a la condició de la consulta, no s’utilitzarà l’índex.
Oracle tracta els índexs amb columnes marcades DESC com índexs basats en funcions.
Les columnes marcades DESC s’ordenen descendentment. Per defecte un índex es crea
de tipus ASC.

3.3.4. Llistar els índexs

Amb Oracle, per veure la llista d’índexs que hi ha creats s’utilitza la vista USER_INDEXES
del diccionari de dades.
La vista USER_IND_COLUMNS del diccionari de dades mostra la llista de columnes que
utilitzen els índexs.
Exemple:
SQL> SELECT INDEX_NAME, INDEX_TYPE, TABLE_NAME
2 FROM USER_INDEXES;

INDEX_NAME INDEX_TYPE TABLE_NAME


------------------------------ --------------------------- ------------------
I_NOM_EMPLEAT NORMAL EMPL
I_NOM_EMPLEAT2 FUNCTION-BASED NORMAL EMPL

Exemple:
INDEX_NAME TABLE_NAME COLUMN_NAME DESC
------------------- --------------- ------------------------------- ----
I_NOM_EMPLEAT EMPL EMPL_NOM ASC

3.3.5. Esborrar índexs

Els índexs no es poden modificar. Per canviar-lo, cal esborrar-lo i tornar-lo a crear.
Sintaxi:
DROP INDEX nomIndex;

3.4. Definició del nivell extern: vistes

3.4.1. Introducció

Hem vist que una taula representa un concepte del món real:
 Gent diferent pot veure una taula conceptualment diferent.
 No tothom té necessitat d’accedir a totes les dades de la taula.
 De vegades convé amagar certa informació a determinats usuaris

87
UD2. Llenguatge SQL DDL SQL

Per ajudar a aconseguir aquestes característiques se solen utilitzar les vistes:


 Es poden considerar taules virtuals: no estan creades físicament.
 Permeten independència lògica de les dades.
 Es creen a través de consultes sobre les taules base o altres vistes, o bé:
 Aplicant restricció de files
 Aplicant restricció de columnes
 Els usuaris no saben que realment el que veuen no és la taula original.
 Qualsevol consulta sobre una vista està permesa.
 No sempre es permeten realitzar operacions d’inserció, d’actualització o
d’esborrat.
Amb el següent esquema pot quedar més clar el concepte de vista:

Usuaris Treballadors
privilegiats Dades Generals

Vistes

CTreb VTreb RHTreb


Dades comptables Dades Comercials ... Dades fiscals i de SS

Usuaris del Usuaris del Usuaris del


Dept. de Comptabilitat Dept. Comercial Dept. de Recursos Humans

Hi ha dos tipus de vistes:


 Simples. Les formen una sola taula i no contenen funcions d’agrupació. El seu
avantatge és que permeten realitzar operacions DML sobre elles.
 Complexes. Obtenen dades de varies taules, poden utilitzar funcions
d’agrupació. No sempre permeten operacions DML.


3.4.2. Creació de vistes

Sintaxi:
CREATE [OR REPLACE] VIEW vista [(alies1[, alies2...]]
AS consultaSELECT
[WITH CHECK OPTION [CONSTRAINT restricció]]
[WITH READ ONLY [CONSTRAINT restricció]]

on:
 OR REPLACE. Si la vista ja existeix, la canvia per l’actual.
 vista. El nom de la vista.
 alies1, alies2,… Llista d’àlies que s’estableixen per les columnes que
retorna la consulta SELECT amb la que es basa la vista. El número d’àlies ha
de coincidir amb el número de columnes que retorna el SELECT.
 WITH CHECK OPTION. Només permet fer operacions d’actualització
(INSERT, UPDATE) si es compleix les condicions de selecció de la consulta

88
UD2. Llenguatge SQL DDL SQL

que defineix la vista (les condicions del WHERE). La restricció que segueix a
aquesta secció és el nom que se li dóna a aquesta restricció CHECK OPTION.
 WITH READ ONLY. Fa que la vista sigui només de lectura.

Exemple: Creació d’una vista que contingui les dades dels empleats que són venedors.
SQL> CREATE VIEW Venedor(Numero, Nom, Data_alta, Salari)
2 AS
3 SELECT empl_num, empl_nom, empl_datalt, empl_salari
4 FROM empl
5* WHERE UPPER(empl_ofici) = 'VENEDOR';

Ara podem fer una consulta SELECT sobre la vista Venedor com si fos una taula:
SQL> SELECT * FROM venedor;

NUMERO NOM DATA_ALT SALARI


---------- ---------------- -------- ----------
7499 ARROYO 22/02/81 208000
7521 SALA 22/02/81 162500
7654 MARTIN 28/09/81 182000
7844 TOVAR 08/09/81 195000

Podem comprovar que és el mateix que la següent consulta:


SQL> SELECT empl_num, empl_nom, empl_datalt, empl_salari
2 FROM empl
3 WHERE empl_ofici = 'VENEDOR';

EMPL_NUM EMPL_NOM EMPL_DAT EMPL_SALARI


---------- ---------------- -------- -----------
7499 ARROYO 22/02/81 208000
7521 SALA 22/02/81 162500
7654 MARTIN 28/09/81 182000
7844 TOVAR 08/09/81 195000

Com que la vista no té cap tipus de restricció especial a part de les pròpies que té la
taula sobre la que es basa la vista, podem executar la següent instrucció:

SQL> INSERT INTO Venedor


2 VALUES (25, 'PERE PI', '25/07/1975', 150000);

Exemple: En el següent exemple es pot veure el funcionament de WITH CHECK


OPTION.
SQL> CREATE OR REPLACE VIEW Venedor(Numero, Nom, Data_alta, Salari)
2 AS
3 SELECT empl_num, empl_nom, empl_datalt, empl_salari
4 FROM empl
5 WHERE UPPER(empl_ofici) = 'VENEDOR'
6 WITH CHECK OPTION;

En la consulta anterior s’ha modificat la vista afegint la restricció WITH CHECK OPTION. Si
ara volem inserir un registre nou a la vista:
SQL> INSERT INTO Venedor
2 VALUES (26,'PERE PINATELL','30/03/1980',200000);
INSERT INTO Venedor
*
ERROR at line 1:
ORA-01402: violació de la clàusula where d'una vista WITH CHECK
OPTION

89
UD2. Llenguatge SQL DDL SQL

L’error es dóna perquè no es compleix la condició del WHERE de la consulta que


defineix la vista. Aquest error es produeix perquè hi ha la restricció WITH CHECK
OPTION en la definició de la vista.
Exemple: En el següent exemple es vol il·lustrar la possibilitat que ofereixen les vistes
d’amagar consultes molt complexes i fer que per l’usuari es mostrin com una simple
consulta.
La vista següent respon a la pregunta Quins són els hospitals amb el major nombre de
treballadors que tenen un sou per sota la mitja?
1 CREATE OR REPLACE VIEW MaxTrebSotaMitjana(Nom)
2 AS
3 SELECT hospital_nom
4 FROM hospital
5 WHERE hospital_codi =
6 (
7 SELECT plantilla_hospital_codi "CODI"
8 FROM plantilla
9 WHERE plantilla_salari <
10 (
11 SELECT AVG(plantilla_salari)
12 FROM plantilla
13 )
14 GROUP BY plantilla_hospital_codi
15 HAVING COUNT(*) =
16 (
17 SELECT MAX(NUM) "MAXI"
18 FROM (
19 SELECT COUNT(*) "NUM"
20 FROM plantilla
21 WHERE plantilla_salari <
22 (
23 SELECT AVG(plantilla_salari)
24 FROM plantilla
25 )
26 GROUP BY plantilla_hospital_codi
27 )
28 )
29* );
Ara, podríem executar la consulta de la següent forma:
SQL> SELECT nom
2 FROM MaxTrebSotaMitjana;

NOM
------------
La Paz

3.4.3. Llistar les vistes

Amb Oracle, la vista del diccionari de dades USER_VIEWS permet mostrar una llista de
totes les vistes que té l’usuari actual. És a dir, per saber quines vistes es tenen creades,
cal executar:
SQL> SELECT *
2 FROM USER_VIEWS;

La columna TEXT d’aquesta vista conté la sentència SQL que es va utilitzar per crear la
vista (sentència que és executada cada vegada que s’invoca a la vista).

3.4.4. Esborrar vistes

Per eliminar la definició d’una vista cal usar la següent sintaxi:


DROP VIEW nomVista;

90
UD2. Llenguatge SQL DDL SQL

3.5. Definir altres objectes de la base de dades

3.5.1. Introducció

A part dels objectes de la base de dades estudiats fins ara, els SGBDR incorporen altres
objectes d’esquema. En el cas d’Oracle, podem definir aquests altres objectes:
• Seqüències

• Sinònims

3.5.2. Seqüències

Introducció
Una seqüència serveix per generar automàticament números enters únics. S’acostumen
a utilitzar per generar valors per columnes que s’utilitzen com a clau primària forçada
(clau on el seu valor real no interessa, només serveixen per identificar els registres d’una
taula).
No tots es SGBD tenen la possibilitat de generar seqüències o bé si ho fan els hi donen
un nom diferent (per exemple, amb Access o MySQL es parla del tipus Autonumèric
quan es vol obtenir un valor de seqüència automàtic).
Amb Oracle, és una rutina interna la que genera i augmenta (o disminueix) la seqüència
de números. Les seqüències es guarden independentment de la taula, i per tant, la
mateixa seqüència es pot utilitzar per diferents taules.
Creació de seqüències
Sintaxi:
CREATE SEQUENCE nomSeqüència
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE n|NOMAXVALUE}]
[{MINVALUE n|NOMINVALUE}]
[{CYCLE|NOCYCLE}]
[{CACHE n|NOCACHE}]

on:
• nomSeqüència : és el nom que es dóna a l’objecte seqüència.

• INCREMENT BY: indica amb quina quantitat s’incrementa la seqüència cada


vegada que s’utilitza. Per defecte s’incrementa d’un en un.

• START WITH: indica el valor inicial de la seqüència (per defecte 1).

• MAXVALUE: serveix per indicar el valor màxim que pot agafar la seqüència. Si
no s’especifica, agafa el valor NOMAXVALUE que permet arribar fins a 1027(per
seqüència ascendent).

• MINVALUE: serveix per indicar el valor mínim que pot agafar la seqüència. Si
no s’especifica, agafa el valor NOMINVALUE que permet arribar fins a 10-26 (per
seqüència descendent).

91
UD2. Llenguatge SQL DDL SQL

• CYCLE | NOCYCLE: fa que la seqüència torni / no torni a començar si s’ha


arribat al valor màxim. NOCYCLE és l’opció per defecte.

• CACHE | NOCACHE: indica quants valors preassigna Oracle i quants manté a


memòria (per defecte 20).

Exemple: Definir una seqüència perquè generi els valors de la columna EMPL_NUM
SQL> CREATE SEQUENCE seq_empl_num
2 INCREMENT BY 1
3 START WITH 8000
4 MAXVALUE 99999;

Sequence created.

Llistar les seqüències


Amb Oracle una seqüència és un objecte més de l’esquema. Per tant, per comprovar
quines seqüències té creades un usuari pot consultar la vista USER_OBJECTS del
diccionari de dades.
També es pot consultar les seqüències amb la vista USER_SEQUENCES del diccionari de
dades.
Exemple:
SQL> SELECT *
2 FROM user_sequences;

SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER


------------------------- ---------- ---------- ------------ - - ---------- -----------
SEQ_EMPL_NUM 1 99999 1 N N 20 8000

En aquest exemple, destacar la columna LAST_NUMER que indica quin serà el proper
número que donarà la seqüència.

Utilitzar les seqüències


Quan es crea una seqüència, aquesta està formada per dues pseudocolumnes
anomenades NEXTVAL i CURRVAL.
NEXTVAL s’utilitza per obtenir números successius de la seqüència indicada. Quan es fa
referència a nomSequencia.NEXTVAL, es genera un nou número de la seqüència i el
número actual es col·loca a CURRVAL.
CURRVAL s’utilitza per fer referència a un número de seqüència que l’usuari actual acaba
de generar. NEXTVAL s’ha d’utilitzar per generar un número de seqüència a la sessió de
l’usuari actual abans que es pugui fer referència a CURRVAL. Quan es fa referència a
nomSequencia.CURRVAL, es mostra l’últim valor que ha retornat la seqüència.
Exemple: afegir un nom empleat al departament número 10
SQL> INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
2 VALUES (seq_empl_num.NEXTVAL, 'PERE PINATELL', 10);

1 row created.

SQL> SELECT empl_num, empl_nom


2 FROM empl;
EMPL_NUM EMPL_NOM
---------- ----------------
7369 SANCHEZ
7499 ARROYO
7521 SALA

92
UD2. Llenguatge SQL DDL SQL

7566 JIMENEZ
7654 MARTIN
7698 NEGRO
7782 CEREZO
7788 GIL
7839 REY
7844 TOVAR
7876 ALONSO
7900 JIMENO
7902 FERNANDEZ
7934 MUNOZ
1000 Pere
4000 Manel
25 PERE PI
8001 PERE PINATELL

Normes d’utilització de NEXTVAL i CURRVAL:


Es pot utilitzar NEXTVAL i CURRVAL en aquests casos:
• Dins la llista de columnes SELECT d’una sentència SELECT que no formi part
d’una subconsulta.

• Dins la llista de columnes SELECT d’una subconsulta que està dins una
sentència INSERT.

• Dins la clàusula VALUES d’una sentència INSERT.

• Dins la clàusula SET d’una sentència UPDATE.

No es pot utilitzar NEXTVAL i CURRVAL en aquests casos:


• Dins la llista de columnes SELECT d’una vista.

• Dins una sentència SELECT amb la paraula clau DISTINCT.

• Dins una sentència SELECT amb clàusules GROUP BY, HAVING o ORDER BY.

• Dins una subconsulta d’una sentència SELECT, DELETE o UPDATE.

• Dins l’expressió DEFAULT en una sentència CREATE TABLE o ALTER TABLE.

Modificar seqüències
Si la seqüència arriba a MAXVALUE, la seqüència no generarà més valors i es produirà
un missatge d’error que indicarà que la seqüència supera MAXVALUE. Per poder
continuar utilitzant la seqüència, es pot modificar amb ALTER SEQUENCE.
Sintaxi:
ALTER SEQUENCE nomSeqüència
[INCREMENT BY n]
[{MAXVALUE n|NOMAXVALUE}]
[{MINVALUE n|NOMINVALUE}]
[{CYCLE|NOCYCLE}]
[{CACHE n|NOCACHE}]

93
UD2. Llenguatge SQL DDL SQL

Consideracions per poder modificar una seqüència:


• Cal ser propietari o tenir privilegi ALTER per la seqüència.

• Només es veuen afectats els futurs números de seqüència després d’executar


ALTER SEQUENCE.

• L’opció START WITH no es pot canviar amb ALTER SEQUENCE. La seqüència


s’ha d’esborrar i tornar a crear.

• No es pot indicar un MAXVALUE menor que el número de seqüència actual.

Esborrar seqüències
Sintaxi:
DROP SEQUENCE nomSeqüència;

Cal ser el propietari de la seqüència o tenir privilegi DROP ANY SEQUENCE per esborrar-
la.

3.5.3. Sinònims

Introducció
Un sinònim és un nom que s’assigna a un objecte qualsevol. Normalment és un nom
menys descriptiu que l’original per tal de facilitar l’escriptura del nom de l’objecte en les
expressions on s’utilitza.
No tots els SGBD permeten la creació de sinònims.
Creació de sinònims
Sintaxi:
CREATE [PUBLIC] SYNONYM nomSinonim
FOR nomObjecte;

on:
• PUBLIC: crea un sinònim accessible per tots els usuaris.

• nomSinonim: és el nom que es dóna a l’objecte sinònim.

• nomObjecte: l’objecte pel que es crea el sinònim.

Consideracions:
• El nom d’un sinònim privat ha de ser diferent de tots els altres objectes
propietat del mateix usuari.

Exemple: crear un sinònim públic per la taula departament de l’usuari perepi


SQL> CREATE PUBLIC SYNONYM dept_ppi
2 FOR perepi.departament;

Synonym created.

94
UD2. Llenguatge SQL DDL SQL

Llistar els sinònims


Amb Oracle un sinònim és un objecte més de l’esquema. Per tant, per comprovar quins
sinònims té creats un usuari pot consultar la vista USER_OBJECTS del diccionari de
dades.
També es pot consultar els sinònims amb la vista USER_SYNONYMS del diccionari de
dades. La vista ALL_SYNONYMS permet veure tots els sinònims.

Esborrar sinònims
Sintaxi:
DROP SYNONYM nomSinònim;

Només l’administrador de la base de dades pot esborrar un sinònim públic.

95
UD2. Llenguatge SQL Transaccions i concurrència

Capítol 4. Transaccions i concurrència

4.1. Gestió de transaccions

4.1.1. Introducció

Una transacció és el conjunt d’instruccions d’actualització que s’executen


consecutivament, i es pot anul·lar o acceptar el resultat de l’execució de totes elles, ja
que una instrucció d’actualització no té validesa real fins que no s’accepta (COMMIT).
En un SGBDR com Oracle, l’única dada retornada per aquestes instruccions és el
nombre de registres que s’han modificat.
Exemple d’una transacció:
Una transferència entre dues comptes bancàries ha d’incloure el dèbit a un compte
corrent i el càrrec a un altre compte amb el mateix import. Les dues accions s’han de
realitzar correctament o incorrectament al mateix temps, de manera que el crèdit no es
pot validar sense el dèbit.

4.1.2. Transaccions

Què passaria si enmig de l’execució d’una seqüència d’instruccions DML hi hagués


alguna errada (de l’usuari o del sistema) que provoqués que les dades quedessin
inconsistents? Què passa si diferents usuaris o processos volen accedir o modificar les
mateixes dades? La resposta a aquesta pregunta no és senzilla. En tot cas el que cal fer
sempre és intentar assegurar la consistència de les dades. Per això alguns SGBDR
tenen mecanismes perquè això no succeeixi: les transaccions.
Una transacció és una seqüència d’instruccions DML que té un inici i un final.
En el SGBDR Oracle, una transacció comença amb la primera instrucció DML de la
seqüència i finalitza quan es produeix alguna d’aquestes situacions:
 Es troba una instrucció COMMIT o ROLLBACK.
 Es troba una instrucció DDL ( com per exemple, un ALTER TABLE).
 Es troba una instrucció DCL (Data Control Language).
 L’usuari abandona la sessió.
 Cau el sistema.

Cal tenir present que qualsevol instrucció DDL o DCL produeix un COMMIT implícit, és a
dir, totes les instruccions DML executades fins aquell moment passen a ser definitives.

COMMIT
La instrucció COMMIT fa que els canvis realitzats per la transacció siguin definitius i
irrevocables. Només cal utilitzar aquesta instrucció si estem d’acord amb els canvis. Cal
estar completament segur d’executar COMMIT ja que les instruccions executades poden
afectar a milers de registres. A més a més el tancament correcte de la sessió produeix el
COMMIT, tot i que sempre convé executar explícitament aquesta instrucció per tal
d’assegurar-nos del que fem.
Hi ha alguns SGBDR (com Oracle) que ofereixen mecanismes que permeten validar les
transaccions de forma automàtica sense haver-ho d’indicar de forma explícita.

96
UD2. Llenguatge SQL Transaccions i concurrència

Amb l’SQL *Plus, es pot configurar la variable AUTOCOMMIT. El valor d’aquesta es pot
comprovar amb el SHOW, de la següent forma:
SQL > SHOW AUTOCOMMIT;

Per defecte el valor d’AUTOCOMMIT és OFF, és a dir, no es guarden el canvis fins que
no es faci un COMMIT. En cas de voler validar automàticament els canvis fet, s’ha
d’escriure la següent ordre (des de la línia de comandes):
SQL > SET AUTOCOMMIT ON;

A partir d’aquest moment, qualsevol inserció, modificació i/o esborrat; es validarà


automàticament.

ROLLBACK
Aquesta instrucció permet tornar a l’estat anterior a l’inici de la transacció, normalment
l’últim COMMIT, la última instrucció DDL o DCL o a l’inici de sessió.
Anul·la definitivament els canvis, motiu pel qual cal estar també molt segur d’executar
aquesta operació.
Exemple de transacció:
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(1000,’Pere’,10);
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(2000,’Joan’,20);
COMMIT;
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(3000,’Albert’,10);
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(4000,’Manel’,40);
ROLLBACK;

En l’exemple anterior s’afegeixen els empleats Pere i Joan, però no l’Albert i en Manel, ja
que la instrucció de validació COMMIT s’executa abans de la instrucció d’inserció de
l’empleat Albert.

97
UD2. Llenguatge SQL Transaccions i concurrència

Amb Oracle hi ha dos tipus de Rollback:


A nivell de transacció: és el cas explicat, el que desfà tota la transacció.
A nivell d’instrucció: si falla una sentència DML durant l’execució d’una transacció, es
restaura només aquella acció que ha fallat. La resta d’instruccions de la transacció
s’hauran de confirmar o restaurar explícitament fent un COMMIT o ROLLBACK.

SAVEPOINT
Aquesta instrucció permet establir un punt de retorn dins una transacció. El problema
d’utilitzar conjuntament ROLLBACK/COMMIT és que un COMMIT ho accepta tot i un
ROLLBACK ho anul·la tot.
SAVEPOINT permet senyalar un punt entre l’inici i el final de la transacció. La seva
sintaxi és:
...instruccions DML...
SAVEPOINT nom
...instruccions DML...

Exemple:
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(1000,’Pere’,10);
SAVEPOINT Pere;
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(2000,’Joan’,20);
SAVEPOINT Joan;
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(3000,’Albert’,10);
ROLLBACK TO Pere;
INSERT INTO empl(empl_num, empl_nom, empl_dept_num)
VALUES(4000,’Manel’,40);
COMMIT;

Estat de les dades abans d’un COMMIT o ROLLBACK


Si s’inicia una transacció utilitzant instruccions DML cal tenir en compte que:
Es pot tornar a la instrucció anterior a la instrucció quan es vulgui.
Les instruccions de consulta SELECT realitzades per l’usuari que ha iniciat la transacció
mostren les dades ja modificades per les instruccions DML.
La resta d’usuaris veuen les dades tal com estaven abans de la transacció; de fet els
registres afectats per la transacció apareixen bloquejats fins que la transacció no
finalitza. Aquests usuaris no podran modificar els valors d’aquests registres.

Estat de les dades després d’un COMMIT


Els canvis de dades es fan permanents a la base de dades.
L’estat anterior de les dades es perd per sempre (no es pot tornar enrere).
Tots els usuaris poden veure els resultats.
Els bloquejos de les files afectades s’alliberen. Aquestes files estan disponibles perquè
altres usuaris les puguin manipular.
Tots els punts de retorn (SAVEPOINT) s’esborren.

Estat de les dades després d’un ROLLBACK


Els canvis de dades es perden.
Es recupera l’estat anterior de les dades.
S’alliberen els bloquejos de les files afectades.

4.2. Gestió de la concurrència

98
UD2. Llenguatge SQL Transaccions i concurrència

4.2.1. Consistència de lectura

Els usuaris de la base de dades executen bàsicament dos tipus d’operacions:


Operacions de lectura (SELECT)
Operacions d’escriptura (INSERT, UPDATE, DELETE)
Cal que hi hagi una consistència de lectura perquè:
Els qui escriuen i els qui llegeixen s’assegurin una visualització consistent de les dades.
Els qui llegeixen no vegin les dades que s’estan modificant.
Els qui escriuen s’assegurin que els canvis a la base de dades es fan de forma
consistent.
Els canvis fets per un escriptor no interfereixin als que està fent un altre escriptor ni
entrin en conflicte entre ells.
Per tant, la consistència de la lectura pretén assegurar que cada usuari vegi les dades tal
com eren a l’última validació, abans de començar una nova transacció.

Implementació de la consistència de lectura


La consistència de lectura és una implementació automàtica. Manté una còpia parcial de
la base de dades en segments de desfer.
Quan es fa una operació d’inserció, modificació o eliminació a la base de dades, Oracle
fa una còpia de les dades abans que es canviïn i les escriu en un segment de desfer.
Tots els lectors, menys el que ha fet el canvi, continuaran veient la base de dades com
era abans de que es fessin els canvis; és a dir, veuen la “instantània” dels segment de
rollback (desfer) de les dades.
Abans que es validin els canvis a la base de dades, només l’usuari que està modificant
les dades veu la base de dades amb les modificacions; els altres veuen la instantània
dins el segment de desfer. Això garanteix que els lectors de les dades llegeixen dades
consistents que no estan patint cap canvi actualment.
Quan es valida (es fa un COMMIT) una instrucció DML, el canvi fet a la base de dades
és visible per qualsevol persona que executi una instrucció SELECT. L’espai que ocupen
les dades antigues dins el fitxer del segment de desfer s’allibera.
Si es fa un rollback d’una transacció, els canvis es desfan:
La versió original (la més antiga) de les dades del segment de desfer es torna a escriure
a la taula.
Tots els usuaris veuen la base de dades com era abans de que comencés la transacció.

99
UD2. Llenguatge SQL Transaccions i concurrència

Exercici 1:
Un usuari A selecciona totes les dades de la taula EMPL.
A continuació, un usuari B esborra tots els empleats que són ANALISTA.
A continuació, l’usuari A torna a seleccionar totes les dades de la taula EMPL. Quines
dades veu?
Tot seguit, l’usuari B selecciona totes les dades de la taula EMPL. Quines dades veu?
Per què es produeix aquesta situació? Quines solucions es poden aplicar per solucionar
el problema?

Exercici 2:
Un usuari A vol incrementar un 20% el salari de l’empleat ALONSO.
A continuació, un usuari B vol incrementar un 10% el salari de l’empleat ALONSO.
Què passa? Com es soluciona aquesta situació?

4.2.2. Bloqueig

Els bloquejos són mecanismes que eviten una interacció destructiva entre les
transaccions que accedeixen a les mateixes dades.
Com bloqueja dades Oracle?
El bloqueig que fa Oracle es fa automàticament i no necessita que l’usuari faci res. El
bloqueig implícit es produeix per les instruccions SQL segons sigui necessari, en funció
de l’acció que es faci. Aquest bloqueig es produeix per totes les instruccions SQL menys
la instrucció SELECT.
Els usuaris també poden bloquejar dades manualment, el que s’anomena bloqueig
explícit.

100
UF1. Llenguatges SQL:
DCL i extensió
procedimental
M10. Administració de Bases
de Dades

SQL hostatjat dins un llenguatge de tercera


generació. PL/SQL d’Oracle. Cursors. Disparadors.
Contingut

Contingut
Capítol 1. SQL hostatjat........................................................................................3
1.1. Introducció.................................................................................................................... 3
1.2. PL/SQL......................................................................................................................... 3
1.2.1. Blocs PL/SQL .................................................................................................... 3
1.2.2. Tipus de blocs ................................................................................................... 4
1.3. Identificadors, variables i constants ............................................................................. 5
1.3.1. Identificadors ..................................................................................................... 5
1.3.2. Variables ........................................................................................................... 6
1.3.3. Constants .......................................................................................................... 7
1.3.4. Els atributs %TYPE i %ROWTYPE......................................................................... 7
1.3.5. Exemples de variables i constants.................................................................... 7
1.4. Operadors .................................................................................................................... 9
1.5. Instruccions de control de flux ..................................................................................... 9
1.5.1. Instrucció IF...................................................................................................... 9
1.5.2. Instrucció CASE ............................................................................................... 11
1.5.3. Instruccions iteratives...................................................................................... 12
1.5.4. Exemples......................................................................................................... 13
1.6. Cursors....................................................................................................................... 14
1.6.1. Introducció ....................................................................................................... 14
1.6.2. Processament de cursors................................................................................ 14
1.6.3. Declaració de cursors...................................................................................... 14
1.6.4. Obrir el cursor.................................................................................................. 14
1.6.5. Instrucció FETCH ............................................................................................. 14
1.6.6. Tancar el cursor .............................................................................................. 15
1.6.7. Atributs dels cursors........................................................................................ 15
1.6.8. Variables de registre ....................................................................................... 16
1.6.9. Cursors i registres ........................................................................................... 17
1.6.10. Utilització avançada de cursors .................................................................... 19
1.7. Excepcions................................................................................................................. 20
1.7.1. Introducció ....................................................................................................... 20
1.7.2. Captura d’excepcions...................................................................................... 20
1.7.3. Excepcions predefinides ................................................................................. 21
1.7.4. Excepcions sense definir................................................................................. 22
1.7.5. Funcions amb excepcions............................................................................... 23
1.7.6. Excepcions d’usuari ........................................................................................ 23
1.8. Subprogrames............................................................................................................ 23
1.8.1. Introducció ....................................................................................................... 23
1.8.2. Procediments .................................................................................................. 24
1.8.3. Funcions .......................................................................................................... 25
1.8.4. Eliminar funcions ............................................................................................. 27
Capítol 2. SQL hostatjat avançat (PL/SQL avançat).........................................28
2.1. Introducció.................................................................................................................. 28
2.2. Paquets ...................................................................................................................... 28
2.2.1. Parts d’un paquet ............................................................................................ 28
2.2.2. Creació de l’especificació d’un paquet............................................................ 28
2.2.3. Creació del cos d’un paquet............................................................................ 29
2.2.4. Avantatges dels paquets ................................................................................. 29
2.3. Triggers ...................................................................................................................... 29
2.3.1. Elements dels triggers..................................................................................... 31
2.3.2. Quan s’ha d’executar el trigger? ..................................................................... 31
2.3.3. Tipus de trigger ............................................................................................... 31
2.3.4. Triggers de fila................................................................................................. 32
2.3.5. Referències NEW i OLD.................................................................................. 32
2.3.6. IF INSERTING, IF UPDATING i IF DELETING............................................... 33
2.3.7. Triggers INSTEAD OF..................................................................................... 33
2.3.8. Exemples......................................................................................................... 35
2.3.9. Administració de triggers................................................................................. 36

ii
UD3. SQL hostatjat SQL hostatjat

Capítol 1. SQL hostatjat


1.1. Introducció

Fins ara hem estudiat i treballat amb la base de dades de forma interactiva, és a dir,
l’usuari introdueix una sentència SQL i el SGBD dóna la resposta de forma immediata.
Aquesta forma de treballar no és la millor, tot i que l’SQL és un llenguatge bastant senzill
de treballar, no tots els usuaris coneixen ni tenen perquè conèixer aquest llenguatge.
Per tant, el millor és programar les sentències SQL, utilitzant un llenguatge de
programació.
Així que, les sentències SQL que treballen de forma hostatjada (també es diu que es
treballa de forma integrada, immersa, etc.) utilitzen aquestes sentències en un programa
escrit en un llenguatge de programació.
Nosaltres estudiarem l’SQL immers amb Oracle, que incorpora un gestor PL/SQL
(Procedural Language Extension) en el servidor de la base de dades i en les principals
eines (Forms, Reports, etc.).
El llenguatge PL/SQL té totes les característiques pròpies dels llenguatges de tercera
generació: gestió de variables, estructura modular (procediments i funcions), estructures
de control (alternatives, iteratives, etc.), control d’excepcions, etc.
Els programes creats amb PL/SQL es poden emmagatzemar a la base de dades com
qualsevol altre objecte d’aquesta. D’aquesta manera es facilita a tots els usuaris
autoritzats de la base de dades que hi puguin accedir.
Hi ha un seguit d’avantatges quan es treballa amb PL/SQL:
 Facilitar la distribució del treball.
 La instal·lació i manteniment del programa.
 Reducció del cost de treball.

A més a més, cal destacar que els programes PL/SQL s’executen en el servidor.

1.2. PL/SQL

El llenguatge PL/SQL és un llenguatge procidemental dissenyat per Oracle per treballar


amb bases de dades.
Consideracions a tenir en compte dels programes PL/SQL:
 PL/SQL suporta les sentències DDL (llenguatge de definició de dades) i DML
(llenguatge de manipulació de dades), aportant al llenguatge SQL elements
propis dels llenguatges procedimentals de tercera generació (variables,
estructures de control, etc.).
 Quan es treballa amb PL/SQL, es fa amb blocs PL/SQL, que són un conjunt
de declaracions, instruccions i mecanismes per gestionar errors i excepcions.
 Amb PL/SQL es poden construir diferents tipus de programes, com ara
procediments, funcions, etc.

1.2.1. Blocs PL/SQL

Sintaxi:
[DECLARE
<declaracions>]

3
UD3. SQL hostatjat SQL hostatjat

BEGIN
<cos del bloc: instruccions >
[EXCEPCION
<gestió de les excepcions (errors) >]
END;

on:
 DECLARE  indica la zona de declaracions, és a dir, on es declaren els
objectes locals necessaris (variables, constants, etc.). És un paràmetre
opcional i a més a més de la clàusula DECLARE es poden utilitzar IS/AS, per
procediments i funcions.
 BEGIN  zona on hi ha el conjunt d’instruccions que s’han d’executar.
 EXCEPTION  zona opcional per tractar les excepcions que es produeixen
(errors).

Exemple: Creació d’un bloc PL/SQL que mostra un missatge.


BEGIN
DBMS_OUTPUT.PUT_LINE('HOLA');
DBMS_OUTPUT.PUT_LINE('Com anem?');
END;

Però com s’executa aquest bloc?


Abans d’executar res, cal activar la llibreria DBMS_OUTPUT. Per fer-ho, executem el
següent des de l’SQL Plus:
SQL> SET SERVEROUTPUT ON

1.2.2. Tipus de blocs

Amb PL/SQL hi ha tres tipus de blocs, que són:


ANÒNIM
Són sentències SQL. Només s’executen una vegada i no s’emmagatzemen al servidor.
És semblant a un script.

4
UD3. SQL hostatjat SQL hostatjat

Sintaxi:
[DECLARE
<declaracions>]
BEGIN
<cos del bloc: instruccions >
[EXCEPCION
<gestió de les excepcions (errors) >]
END;

PROCEDIMENT
Bloc que s’emmagatzema al servidor i s’executa cada vegada que s’invoca.
Sintaxi:
PROCEDURE nomProcediment [(par1, par2, ...)] IS
[<declaracions locals>]
BEGIN
<cos del bloc: instruccions >
[EXCEPCION
<gestió de les excepcions (errors) >]
END [nomProcediment];

FUNCIÓ
Similar a un procediment, amb la diferència de que es passa un paràmetre (com a
mínim) i retorna un valor.
Sintaxi:
FUNCTION nomFunció [(par1, par2, ...)] RETURN tipusDades IS
BEGIN

RETURN valor;
[EXCEPTION]
END;

1.3. Identificadors, variables i constants

1.3.1. Identificadors

Els identificadors s’utilitzen per donar nom als objectes que intervenen en un programa i
són: variables, constants, cursors, excepcions, procediments, funcions, etiquetes, etc.
Amb PL/SQL, els identificadors tenen les següents característiques:
 Poden tenir fins a 30 caràcters, començant sempre per una lletra i pot anar
seguida per més lletres, números, signe dòlar ($), coixinet (#) i el subguió (_).
 No es diferencia entre majúscules i minúscules.
 Es poden saltar algunes de les regles anteriors posant l’identificador entre
cometes.

5
UD3. SQL hostatjat SQL hostatjat

1.3.2. Variables

Amb PL/SQL es poden declarar variables i s’utilitzen entre altres coses per
emmagatzemar temporalment una dada i manipular valors emmagatzemats
anteriorment. Aquestes variables també es poden utilitzar amb SQL i sentències de
procediment.
Les variables PL/SQL s’han de declarar dins la secció corresponent i sempre abans de la
seva utilització, és a dir, dins la secció DECLARE.
Sintaxi:
nom_variable tipus [NOT NULL] [{:=|DEFAULT} valor]

on:
 nom_variable => identificador de la variable.
 tipus => el tipus de dades de la variable (els veurem més endavant).
 NOT NULL => força que la variable sempre tingui un valor. Sempre que es
declari una variable amb NOT NULL cal inicialitzar la variable. En general
però, hem d’inicialitzar totes les variables.

TIPUS DE DADES DE VARIABLES PL/SQL
ORACLE SQL Descripció
CHAR(n) Text de longitud fixa
VARCHAR2(n) Text de longitud variable
LONG Text de més de 32767 caràcters
NUMBER(p,s) Números decimals de coma fixa
BOOLEAN Emmagatzema els valor TRUE i
FALSE.
DATE Emmagatzema dates.
TIMESTAMP Emmagatzema dates i hores.
ROWID Emmagatzema identificadors de fila.

CLASSIFICACIÓ DE VARIABLES PL/SQL:


 ESCALAR => contenen un sol valor. Són els tipus més comuns que podem
trobar amb PL/SQL, com ara VARCHAR2, NUMBER, DATE, CHAR,
BOOLEAN, etc.
 COMPOSTA => s’utilitzen per definir i manipular grups de camps dins de blocs
PL/SQL. Són les taules PL/SQL i registres PL/SQL.
 REFERENCIADA => són les variables punters.
 LOB => contenen els valors anomenats localitzadors, que indiquen la ubicació
d’imatges gràfiques.

També hi ha variables NO PL/SQL, que poden ser variables declarades en programes
precompilats, camps de pantalla en aplicacions Forms i variables d’enllaç SQL*Plus.
Per fer referència a aquest últim tipus de variables, cal precedir la variable amb el símbol
dos punts (:).

6
UD3. SQL hostatjat SQL hostatjat

1.3.3. Constants

Sintaxi:
nom_constant CONSTANT tipus := valor

1.3.4. Els atributs %TYPE i %ROWTYPE

La finalitat d’utilitzar aquests atributs quan es declaren variables és per declarar variables
que siguin del mateix tipus que altres objectes que ja estan definits. És a dir, la variable
“hereda” el tipus i la longitud de l’objecte, però no els atributs NOT NULL, ni valors per
defecte.
%TYPE
Aquest atribut permet declarar una variable del mateix tipus que una altra, o que una
columna d’una taula. Per tant, declara una variable basada amb altres que ja han estat
declarades abans, o en la definició d’una columna d’una taula.
Per exemple, si volem declarar una variable anomenada var_nom que sigui del mateix
tipus de dades que el nom d’un empleat que tenim a la nostra base de dades,
concretament a la taula EMPL, llavors ho faríem com segueix:
...
var_nom empl.empl_nom%TYPE;
...

%ROWTYPE
Aquest atribut crea una variable de registre on els seus camps es corresponen amb les
columnes d’una taula o vista de la base de dades.
...
var_empl empl%ROWTYPE;
...

1.3.5. Exemples de variables i constants

A l’hora de declarar les variables cal tenir en compte on es declaren i com: si declarem la
variable local pel bloc on ha estat declarada i/o global per tots els blocs.
EXEMPLE 1: Declara una variable en un bloc pare i és accessible pel bloc fill.
DECLARE /* Bloc pare */
var1 NUMBER;
BEGIN
var1 := 10;
DBMS_OUTPUT.PUT_LINE('El valor de la variable 1 es '||var1);
DECLARE /* Bloc fill */
var2 NUMBER;
BEGIN
var2 := 20;
DBMS_OUTPUT.PUT_LINE('El valor de la variable 2 es '||var2);
var2 := var1;
DBMS_OUTPUT.PUT_LINE('Ara el valor de la variable 2 es'||var2);
END; /* FI bloc fill */
END; /* FI bloc pare */

EXEMPLE 2: Declara una variable en un bloc fill i no és accessible pel bloc pare.
DECLARE
var1 NUMBER;
BEGIN
var1 := 10;

7
UD3. SQL hostatjat SQL hostatjat

DBMS_OUTPUT.PUT_LINE('El valor de la variable 1 es '||var1);


DECLARE
var2 NUMBER;
BEGIN
var2 := var1;
DBMS_OUTPUT.PUT_LINE('El valor de la variable 2 es '||var2);
END;
var2:= var1; /* ERROR: var2 no es coneix en aquest àmbit, ja que es*/
/* local en el bloc fill i ha acabat. */
END;

EXEMPLE 3: Es vol tenir un identificador local que coincideixi amb un de global. Si no


s’indica res, sempre es referència al local. Hi ha mecanismes per desfer aquestes
ambigüitats: les etiquetes, que s’utilitzen en aquest exemple.
<<blocpare>> /* Etiqueta que identifica el bloc pare */
DECLARE
var1 NUMBER;
BEGIN
var1 := 10;
DBMS_OUTPUT.PUT_LINE('El valor de la variable 1 es '||var1);
DECLARE /* Bloc fill */
var1 NUMBER :=20;
BEGIN
var1 := blocpare.var1; /* s’assigna a una variable local */
/* (del bloc fill) una variable que */
/* es troba declarada en el bloc */
/* pare */
DBMS_OUTPUT.PUT_LINE('El valor de la variable 1 es '||var1);
END; /* FI bloc fill */
END; /* FI bloc pare */

EXEMPLE 4: Es declaren dues variables NO PL/SQL (nom i edat) i es declaren altres


dues variables dins el bloc PL/SQL, i se’ls hi assigna un valor. Aquest valor s’assignarà a
les variables no PL/SQL i posteriorment s’imprimeixen.
VARIABLE nom VARCHAR2(10)
VARIABLE edat NUMBER
DECLARE
var_nom VARCHAR2(10);
var_edat NUMBER;
BEGIN
var_nom := 'PERE PI';
var_edat := 20;
:nom := var_nom;
:edat := var_edat;
END;
/
print nom
print edat
/

EXEMPLE 5: Declaració de variables utilitzant l’atribut %TYPE. Es fa una consulta del


nom d’empleat, nom i salari que guanya un empleat concret. S’ha d’introduir el número o
codi d’empleat.
ACLARIMENTS
En aquest exemple s’accedeix a una de les taules d’una base de dades. Per tant
s’utilitza una sentència SQL en el cos del bloc PL/SQL. Cal tenir en compte que la
consulta només ha de retornar un registre.
La sintaxi d’una sentència SQL que fa una consulta sobre alguns camps d’una taula i
que posteriorment es volen utilitzar aquests valors, és:
SELECT camp1, camp2, … ,campN
INTO var_camp1, var_camp2, … var_campN
FROM taula
WHERE (condició);

8
UD3. SQL hostatjat SQL hostatjat

On:
 SELECT  selecciona els camps de la taula que volem consultar.
 INTO  guarda amb variables PL/SQL declarades prèviament, el valor dels
camps corresponents. Hi ha d’haver tantes variables com camps hi hagi en el
SELECT.
 FROM  nom de la taula a consultar.
 WHERE  clàusula que controla la condició o condicions que ha de complir
un registre d’una taula.

3. S’utilitza l’atribut %TYPE per declarar les variables PL/SQL corresponents; ja que han
de ser del mateix tipus de dades que els camps de la taula.
L’exemple, per tant és:
DECLARE
var_num empl.empl_num%TYPE;
var_nom empl.empl_nom%TYPE;
var_sal empl.empl_salari%TYPE;
codi NUMBER;
BEGIN
SELECT empl_num, empl_nom, empl_salari
INTO var_num, var_nom, var_sal
FROM empl
WHERE empl_num = &&codi;
DBMS_OUTPUT.PUT_LINE (' ');
DBMS_OUTPUT.PUT_LINE ('COD NOM SALARI');
DBMS_OUTPUT.PUT_LINE ('=============================');
DBMS_OUTPUT.PUT_LINE (var_num||' '||var_nom||' '||var_sal);
END;
/

1.4. Operadors

Amb PL/SQL es poden utilitzar tots els operadors de SQL: els aritmètics (+-*/),
condicionals (> < != <> >= <= OR AND NOT) i de concatenació (||).
3
A més amés, PL/SQL afegeix l’operador de potencia **. Exemple: 4**3 és 4 .

1.5. Instruccions de control de flux

1.5.1. Instrucció IF

IF SIMPLE
IF condició THEN
instruccions
END IF;

 condició és qualsevol expressió que retorni cert o fals.

Exemple:
IF departament = 134 THEN
salari := salari * 13;
departament := 123;
END IF;

9
UD3. SQL hostatjat SQL hostatjat

IF-THEN-ELSE
IF condició THEN
instruccions1
ELSE
instruccions2
END IF;

Exemple:
IF saldo>90 THEN
DBMS_OUTPUT.PUT_LINE(‘Saldo més gran del que s’esperava.’);
ELSE
IF saldo>0 THEN
DBMS_OUTPUT.PUT_LINE(‘Saldo menor del que s’esperava’);
ELSE
DBMS_OUTPUT.PUT_LINE(‘Saldo NEGATIU’);
END IF;
END IF;

Una alternativa a aquesta instrucció és:


IF condició1 THEN
instruccions1
ELSIF condició2 THEN
instruccions2
[ELSIF.... ]
ELSE
instruccionsElse
END IF;

10
UD3. SQL hostatjat SQL hostatjat

Exemple:
IF saldo>90 THEN
DBMS_OUTPUT.PUT_LINE(‘Saldo més gran del que s’esperava.’);
ELSIF saldo>0 THEN
DBMS_OUTPUT.PUT_LINE(‘Saldo menor del que s’esperava’
ELSE
DBMS_OUTPUT.PUT_LINE(‘Saldo NEGATIU’);
END IF;

1.5.2. Instrucció CASE

CASE variable
WHEN expressió1 THEN resultat1
WHEN expressió2 THEN resultat2
...
[ELSE resultatElse]
END;

Exemple:
text:= CASE actitut
WHEN 'A' THEN 'Molt bona'
WHEN 'B' THEN 'Bona'
WHEN 'C' THEN 'Normal'
WHEN 'D' THEN 'Dolenta'
ELSE 'Desconeguda'
END;

Cal tenir present que la instrucció CASE serveix per retornar un valor i no per executar
una instrucció.
Una altra possibilitat d’utilitzar el CASE és:
CASE
WHEN condició1 THEN resultat1
WHEN condició2 THEN resultat2
...
[ELSE resultatElse]
END;

Aquest segon format facilita l’escriptura de sentències CASE més complexes. Per
exemple:
aprovat:=CASE
WHEN actitut='A' AND nota>=4.5 THEN TRUE
WHEN nota>=5 AND (actitut='B' OR actitut='C') THEN TRUE
WHEN nota>=7 THEN TRUE
ELSE FALSE
END;

11
UD3. SQL hostatjat SQL hostatjat

1.5.3. Instruccions iteratives

BUCLE LOOP
Instrucció que conté instruccions que es repeteixen indefinidament (bucle infinit).
Comença amb la paraula LOOP i acaba amb END LOOP i dins hi ha les instruccions que
es repetiran.
Òbviament no té sentit utilitzar un bucle infinit. Per això hi ha la instrucció EXIT que
permet sortir el bucle. Quan Oracle troba aquesta instrucció, el programa continua a
partir de la següent instrucció després de l’END LOOP.
El més normal és col·locar EXIT dins d’una instrucció IF per tal d’establir una condició de
fi del bucle. També es pot utilitzar la instrucció EXIT juntament amb la instrucció WHEN
seguida d’una condició. Si la condició és certa, acaba el bucle, altrament es continua
iterant.

LOOP
instruccions
...
EXIT [WHEN condició]
END LOOP;

Exemple:
DECLARE
c NUMBER := 1;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE(c);
EXIT WHEN c = 10;
c := c + 1;
END LOOP;
END;

BUCLE WHILE
WHILE condició LOOP
instruccions
END LOOP;

Exemple:
DECLARE
c NUMBER :=1;
BEGIN
WHILE c <= 10 LOOP
DBMS_OUTPUT.PUT_LINE(c);
c := c + 1;
END LOOP;
END;

12
UD3. SQL hostatjat SQL hostatjat

BUCLE FOR
S’utilitza per bucles amb comptador, bucles que fan un recorregut un cert nombre de
vegades. S’utilitza una variable (comptador) que no ha d’estar declarada al DECLARE,
sinó que es declara automàticament en el mateix FOR i s’elimina quan acaba.
S’indica el valor inicial de la variable i el valor final (l’increment anirà d’un en un). Si s’usa
la clàusula REVERSE, llavors el comptador compte des del valor màxim fins al mínim
restant 1.
Sintaxi:
FOR comptador IN [REVERSE] mínim..màxim LOOP
instruccions
END LOOP;

Exemple:
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;

1.5.4. Exemples

Programar un script amb PL/SQL que escrigui tres vegades la paraula HOLA i deu
vegades la paraula ADÉU.
DECLARE
i NUMBER;
BEGIN
i:=1;
WHILE i<=13 LOOP
IF i<4 THEN
DBMS_OUTPUT.PUT_LINE(‘HOLA’);
ELSE
DBMS_OUTPUT.PUT_LINE(‘ADEU’);
END IF;
i:=i+1;
END LOOP;
END;
/

Programar un script amb PL/SQL que escrigui la taula de multiplicar d’un número entrat
per teclat.
DECLARE
inici NUMBER :=0;
fi NUMBER :=10;
resultat NUMBER :=0;
BEGIN
FOR i IN inici..fi LOOP
resultat := i * &&var_num;
DBMS_OUTPUT.PUT_LINE(i||' * ' || &&var_num || ' ='||resultat);
END LOOP;
END;
/

13
UD3. SQL hostatjat SQL hostatjat

1.6. Cursors

1.6.1. Introducció

Els cursors representen consultes SELECT SQL que retornen més d’un resultat i que
permeten l’accés a cada fila de la consulta. Això significa que el cursor sempre té un
punter a una de les files del SELECT que representa el cursor.

1.6.2. Processament de cursors

Es processen amb tres passes:


Obrir el cursor. Després d’obrir el cursor, aquest apuntarà a la primera fila (si n’hi ha).
Avançar el cursor. La instrucció FETCH permet recórrer el cursor registre a registre fins
que el punter arribi al final.
Tancar el cursor.

1.6.3. Declaració de cursors

Sintaxi:
CURSOR nom IS instruccióSELECT;

La instrucció SELECT indicada no pot tenir l’apartat INTO.


La definició d’un cursor es fa dins l’apartat DECLARE d’un bloc PL/SQL.
Exemple:
CURSOR cursorDepartaments IS
SELECT dept_nom, COUNT(*) AS “Empleats”
FROM dept, empl
WHERE empl_dept_num = dept_num
GROUP BY dept_nom;

1.6.4. Obrir el cursor

Sintaxi:
OPEN cursor;

Aquesta instrucció obre el cursor, la qual cosa significa:


Reservar memòria suficient pel cursor.
Executar la sentència SELECT que defineix el cursor.
Situar el punter a la primera fila.
Si la instrucció SELECT no retorna registres, Oracle no dóna cap error.

1.6.5. Instrucció FETCH

La instrucció FETCH és l’encarregada de recórrer el cursor i anar processant els valors:


FETCH cursor INTO (llistaDeVariables)

Aquesta instrucció emmagatzema el contingut de la fila a la que apunta actualment el


punter a la llista de variables indicada, que ha de tenir el mateix tipus i número que les

14
UD3. SQL hostatjat SQL hostatjat

columnes representades en el cursor. Després de ser executada, el punter avança a la


següent posició.
Aquesta instrucció s’acostuma a posar dins un bucle per tal d’anar processant cada fila
del cursor.
Exemple:
LOOP
FETCH cursorDepartaments INTO (v_nom, v_empleats);
EXIT WHEN... --aquí es posaria la condición de sortida
... --instruccions que processen les dades del cursor
END LOOP;

1.6.6. Tancar el cursor

Sintaxi:
CLOSE cursor;

Quan es tanca el cursor s’allibera la memòria que ocupa i s’impedeix que s’utilitzi.

1.6.7. Atributs dels cursors

Per poder processar de forma adient els cursors es poden utilitzar uns atributs que
retornen CERT o FALS segons la situació actual del cursor. S’utilitzen indicant el nom
del cursor i immediatament després el nom del cursor.
Exemple: cursorDepartaments%ISOPEN
%ISOPEN
Retorna CERT si el cursor ja està obert.
%NOTFOUND
Retorna CERT si la última instrucció FETCH no ha retornat cap fila.

15
UD3. SQL hostatjat SQL hostatjat

Exemple:
DECLARE
CURSOR cursorDepartaments IS
SELECT dept_nom, COUNT(*) AS “Empleats”
FROM dept, empl
WHERE empl_dept_num = dept_num
GROUP BY dept_nom;
v_nom DEPT.dept_nom%TYPE;
v_empleats NUMBER;
BEGIN
OPEN cursorDepartaments;
LOOP
FETCH cursorDepartaments INTO v_nom, v_empleats;
EXIT WHEN cursorDepartaments%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_nom || ‘,’ || v_empleats);
END LOOP;
CLOSE cursorDepartaments;
END;

%FOUND
Retorna CERT si la última instrucció FETCH ha retornat alguna fila.
%ROWCOUNT
Indica el número de files que s’han recorregut amb el cursor (inicialment val 0). És a dir,
indica quants FETCH s’han aplicat sobre el cursor.

1.6.8. Variables de registre

Els registres són una estructura estàtica de dades present en gairebé tots els
llenguatges clàssics de programació (amb C o C# seria un struct). Es tracta d’un tipus
de dades que es composa de dades més simples. Per exemple, els registre persona es
composaria de les dades simples nom, cognoms, adreça, data de naixement, etc.
Amb PL/SQL interessa aquest tipus de dades perquè cada fila d’una taula o vista es pot
interpretar com un registre. Els registres faciliten el treball amb cursors.
Per utilitzar registres, primer cal definir les dades que composen el registre. Després es
declara una variable de registre que sigui del tipus definit.
Sintaxi:
TYPE nomTipusRegistre IS RECORD(
camp1 tipusCamp1 [:= valorInicial],
camp2 tipusCamp2 [:= valorInicial],
...
campN tipusCampN [:= valorInicial]
)
nomVariableDeRegistre nomTipusRegistre;

NOTA: Recordar que per definir una variable de tipus registre també podem aprofitar l’ús
de l’atribut %ROWTYPE que hem vist en el punt 1.3.4.

16
UD3. SQL hostatjat SQL hostatjat

Exemple:
TYPE regPersona IS RECORD(
nom VARCHAR2(25),
cog1 VARCHAR2(25),
cog2 VARCHAR2(25),
data_naix DATE
);

pere regPersona;
maria regPersona;

UTILITZACIÓ DE REGISTRES
Per accedir als valors dels registres cal indicar el nom de la variable de registre seguida
d’un punt i el nom del camp:
maria.nom := ‘MARIA’;
maria.data_naix := TO_DATE(‘02/03/1990’);

1.6.9. Cursors i registres

UTILITZAR EL FETCH AMB REGISTRES


Un dels inconvenients d’utilitzar FETCH és que cal assignar tots els valors de cada fila
del cursor a una variable. Per tant, si una fila té 10 columnes, cal declarar 10 variables.
En lloc d’això es pot utilitzar una variable registre i assignar el resultat del FETCH a
aquesta variable.
Exemple:
DECLARE
CURSOR cursorDepartaments IS
SELECT dept_nom AS Nom, COUNT(*) AS Empleats
FROM dept, empl
WHERE empl_dept_num = dept_num
GROUP BY dept_nom;

rDep cursorDepartaments%ROWTYPE;
BEGIN
OPEN cursorDepartaments;
LOOP
FETCH cursorDepartaments INTO rDep;
EXIT WHEN cursorDepartaments%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(rDep.nom || ‘,’ || rDep.empleats);
END LOOP;
CLOSE cursorDepartaments;
END;

17
UD3. SQL hostatjat SQL hostatjat

BUCLE FOR PER RECÓRRER CURSORS


És la forma més normal de recórrer totes les files d’un cursor. És un bucle FOR que
s’encarrega de fer tres tasques:
Obre el cursor (fa l’OPEN abans de començar el bucle).
Recorre totes les files del cursor (a cada iteració es genera un FETCH implícit) i
emmagatzema el contingut de cada fila en una variable de registre (que no cal declarar a
la zona DECLARE).
Tanca el cursor (quan acaba el FOR).
Sintaxi:
FOR variableRegistre IN cursor LOOP
..instruccions
END LOOP;

Aquesta sintaxi és equivalent a:


OPEN cursor;
LOOP
FETCH cursor INTO variableRegistre;
EXIT WHEN cursor%NOTFOUND;
...instruccions
END LOOP;

Exemple:
DECLARE
CURSOR cursorDepartaments IS
SELECT dept_nom AS Nom, COUNT(*) AS Empleats
FROM dept, empl
WHERE empl_dept_num = dept_num
GROUP BY dept_nom;

rDep cursorDepartaments%ROWTYPE;
BEGIN
FOR rDep IN cursorDepartaments LOOP
DBMS_OUTPUT.PUT_LINE(rDep.nom || ‘,’ || rDep.empleats);
END LOOP;
END;

Exemple:
BEGIN
FOR cDep IN (SELECT dept_nom FROM dept WHERE dept_loc=’Girona’) LOOP
DBMS_OUTPUT.PUT_LINE(cDep.dept_nom);
END LOOP;
END;

18
UD3. SQL hostatjat SQL hostatjat

1.6.10. Utilització avançada de cursors

CURSORS AMB PARÀMETRES


És possible que es vulgui que el resultat d’un cursor depengui d’una variable. Per
exemple, al presentar una llista de personal, fer que aparegui el cursor d’un determinat
departament i lloc de treball.
Per fer que el cursor variï segons uns paràmetres, cal indicar-los en la declaració del
cursor. Per això es posa entre parèntesi el seu nom i tipus després del nom del cursor en
la declaració.
Exemple:
DECLARE
CURSOR curEmpleats(dep NUMBER, ofici VARCHAR2(20)) IS
SELECT empl_nom, empl_salari
FROM empl
WHERE empl_dept_num=dep AND empl_ofici=ofici;
BEGIN
OPEN curEmpleats(12,’ANALISTA’);
.....
CLOSE curEmpleats;
END

És quan s’obre el cursor quan s’indica el valor dels paràmetres, la qual cosa significa que
es pot obrir tantes vegades com es vulgui el cursor i que aquest tingui resultats diferents
en funció del valor dels paràmetres.
També es poden indicar els paràmetres en el bucle FOR.
Exemple:
DECLARE
CURSOR curEmpleats(dep NUMBER, ofici VARCHAR2(20)) IS
SELECT empl_nom, empl_salari
FROM empl
WHERE empl_dept_num=dep AND empl_ofici=ofici;
BEGIN
FOR r IN curEmpleats(12,’ANALISTA’) LOOP
.....
END LOOP;
END;

ACTUALITZACIONS EN RECÓRRER REGISTRES


Moltes vegades es fan operacions d’actualització de registres sobre el cursor que s’està
recorrent. Per evitar problemes s’han de bloquejar els registres del cursor per tal de
parar els processos que també volen modificar les dades.
Aquesta clàusula es col·loca al final de la sentència SELECT del cursor (aniria després
de l’ORDER BY). Opcionalment es pot col·locar el text NOWAIT perquè el programa no
es quedi esperant en cas de que la taula estigui bloquejada per un altre usuari. S’utilitza
el text OF seguit del nom del camp que es modificarà (no és necessari posar-ho però es
manté perquè el codi sigui més clar).
Sintaxi:
CURSOR ...
SELECT...
FOR UPDATE [OF camp] [NOWAIT]

Exemple:
DECLARE
CURSOR c_emp IS

19
UD3. SQL hostatjat SQL hostatjat

SELECT empl_num, empl_nom, empl_dept_num, empl_salari


FROM empl, dept
WHERE empl_dept_num=dept_num AND empl_dept_num=80
FOR UPDATE OF salari NOWAIT;

A continuació, a la instrucció UPDATE que modifica els registres, es pot utilitzar una
nova clàusula anomenada WHERE CURRENT OF seguida del nom d’un cursor, que fa
que es modifiqui el registre actual del cursor.
Exemple:
FOR r_emp IN c_emp LOOP
IF r_emp.empl_salari<1500 THEN
UPDATE empl SET empl_slari = empl_salari * 1.30
WHERE CURRENT OF c_emp;
END IF;
END LOOP;

1.7. Excepcions

1.7.1. Introducció

S’anomena excepció a una acció que li succeeix a un programa que provoca que la seva
execució acabi. Òbviament això causa que el programa acabi de forma anòmala.
Les excepcions es produeixen per:
 Que es produeixi un error detectat per Oracle (per exemple si un SELECT no
retorna dades es produeix l’error ORA-01403 també anomenat
NO_DATA_FOUND).
 Que el programador les provoqui (comandament RAISE).

Les excepcions es poden capturar pe tal que el programa no finalitzi de forma anòmala.

1.7.2. Captura d’excepcions

La captura es fa utilitzant el bloc EXCEPTION que és el bloc que està just abans de
l’END del bloc del programa. Quan hi ha una excepció, es comprova el bloc EXCEPTION
per veure si s’ha capturat, si no es captura, l’error es passa a Oracle que s’encarregarà
d’indicar l’error.
Tipus d’excepcions:
 Excepcions preestablertes d’Oracle. Ja tenen assignat un nom d’excepció.
 Excepcions d’Oracle sense definir. No tenen nom assignat però se’ls hi pot
assignar.
 Definides per l’usuari. Les ha de cridar el programador.

Sintaxi per capturar excepcions:
DECLARE
secció de declaracions
BEGIN
instruccions
EXCEPTION WHEN excepció1 [OR excepció2 ...] THEN
instruccions que s’executen si es produeixen
aquestes excepcions
[WHEN excepció3 [OR...] THEN
instruccions que s’executen si es produeixen
aquestes excepcions]
[WHEN OTHERS THEN]

20
UD3. SQL hostatjat SQL hostatjat

[instruccions que s’executen si es produeixen


altres excepcions]
END;

Quan hi ha una excepció, es comprova el primer WHEN per comprovar si el nom de


l’excepció que hi ha hagut coincideix amb el del WHEN; si és així s’executen les
instruccions, i si no es comprova el següent WHEN i així successivament.
Si hi ha clàusula WHEN OTHERS, llavors les excepcions que no estan en els apartats
WHEN executen les instruccions del WHEN OTHERS. Aquesta clàusula ha de ser
l’última.

1.7.3. Excepcions predefinides

Les més comuns són:


Nom Número Succeeix quan…
error
S’intenta assignar valors a
ORA-
ACCESS_INTO_NULL un objecte que no s’ha
06530
inicialitzat.
Cap opció WHEN d’una instrucció
CASE_NOT_FOUND ORA- CASE captura el valor, i no hi ha
06592 instrucció ELSE.

COLLECTION_IS_NULL ORA- S’intenta utilitzar un varray o una taula


06531 aniuada que no estava inicialitzada.

CURSOR_ALREADY_OPEN ORA- S’intenta obrir un cursor que ja s’havia


06511 obert.

DUP_VAL_ON_INDEX ORA- S’intenta afegir una fila que provoca


00001 que un índex únic repeteixi valors.

INVALID_CURSOR ORA- S’ha fet una operació no vàlida sobre


01001 un cursor

INVALID_NUMBER ORA- Falla la conversió de caràcter a


01722 número
S’intenta connectar amb Oracle
LOGIN_DEINED ORA- utilitzant un nom d’usuari i contrasenya
01017 no vàlids.

NO_DATA_FOUND ORA- El SELECT de fila única no ha retornat


01403 valors

PROGRAM_ERROR ORA- Error intern d’Oracle


06501
Hi ha incompatibilitat de tipus entre el
ROWTYPE_MISMATCH ORA- cursor i les variables a les que
06504 s’intenta assignar els seus valors.

STORAGE_ERROR ORA- No hi ha prou memòria


06500
Es fa referència a un element d’un
SUBSCRIPT_BEYOND_COUNT ORA- varray o una taula aniuada emprant un
06533 índex més gran que els elements que
té.
Es fa referència a un element d’un
SUBSCRIPT_OUTSIDE_LIMIT ORA- varray o una taula aniuada emprant un
06532 índex el valor del qual està fora del
rang permès.

SYS_INVALID_ROWID ORA- Es converteix un text amb un número


01410 d’identificació de fila (ROWID) y el text

21
UD3. SQL hostatjat SQL hostatjat

no és vàlid.

TIMEOUT_ON_RESOURCE ORA- S’ha acabat el temps màxim amb el


00051 que Oracle permet esperar al recurs.

TOO_MANY_ROWS ORA- El SELECT de fila única retorna més


01422 d’una fila.
Hi ha un error aritmètic, de conversió,
VALUE_ERROR ORA- d’arrodoniment o de mida en una
06502 operació.

ZERO_DIVIDE ORA- S’intenta dividir entre zero


01476

Exemple:
DECLARE
x NUMBER :=0;
y NUMBER := 3;
res NUMBER;
BEGIN
res:=y/x;
DBMS_OUTPUT.PUT_LINE(res);

EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('No es pot dividir per zero');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error no esperat’) ;
END;

1.7.4. Excepcions sense definir

Hi pot haver moltes més excepcions que no estan a la llista anterior. En aquest cas tot i
que no tenen un nom assignat, si que tenen un número. Aquest número és el que surt
quan Oracle mostra el missatge d’error després de la paraula ORA.
Per exemple, en un error per restricció d’integritat Oracle llança un missatge que
comença pel text: ORA-02292. Per tant, l’error d’integritat referencial és el -02292.
Si es volen capturar excepcions no definides cal:
Declarar un nom per l’excepció que es captura. Això es fa a l’apartat DECLARE.
Sintaxi:
nomExcepció EXCEPTION;

Associar aquest nom amb el número d’error corresponent amb la següent sintaxi dins el
DECLARE (després de la instrucció del pas 1):
PRAGMA EXCEPTION_INIT(nomExcepció, nºExcepció);

A l’apartat EXCEPTION capturar l’excepció.


Exemple:
DECLARE
e_integritat EXCEPTION;
PRAGMA EXCEPTION_INIT(e_integritat, -2292);
BEGIN
DELETE FROM dept WHERE dept_num = 2;
EXCEPTION
WHEN e_integritat THEN
DBMS_OUTPUT.PUT_LINE(‘No es pot esborrar aquest departament ‘ ||
‘ja que té empleats relacionats.’);
END;

22
UD3. SQL hostatjat SQL hostatjat

1.7.5. Funcions amb excepcions

S’acostuma a utilitzar dues funcions quan es treballa amb excepcions:


 SQLCODE. Retorna el codi d’error.
 SQLERRM. Retorna el missatge d’error d’Oracle associat a aquest número
d’error.

Exemple:
EXCEPTION
...
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Hi ha hagut un error ‘ || SQLCODE ||
‘missatge: ‘ || SQLERRM);
END;

1.7.6. Excepcions d’usuari

El programador pot llançar les seves pròpies excepcions simulant errors del programa.
Cal fer el següent:
Declarar un nom per l’excepció.
Utilitzar la instrucció RAISE per llançar l’excepció (dins el bloc BEGIN..END).
Capturar l’excepció a l’apartat EXCEPTION.

Una forma alternativa, més senzilla d’utilitzar, és la següent:


RAISE_APPLICATION_ERROR(nºError, missatge[,{TRUE|FALSE}]);

Aquesta instrucció es posa a la secció executable o a la d’excepcions i substitueix els


tres passos anteriors. El que fa és llançar un error on el número ha d’estar entre el -
20000 i el -20999 i fa que Oracle mostri el missatge indicat. El tercer paràmetre opcional
indica si l’error s’afegeix a la pila d’errors existents.
Exemple:
BEGIN
DELETE FROM dept WHERE dept_num = 26;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20001,‘No existeix aquest departament’)
END;
END;

Oracle mostrarà el missatge:


ORA-20001: No existeix aquest departament

1.8. Subprogrames

1.8.1. Introducció

Un subprograma, procediment emmagatzemat o stored procedure és un fragment de


programa que es troba emmagatzemat al servidor de la base de dades i permet la seva
execució per qualsevol usuari amb permisos i des de qualsevol ubicació amb connexió al
SGBD.
Els stored procedures poden ser:

23
UD3. SQL hostatjat SQL hostatjat

 Procediments: accions que no retornen cap valor.


 Funcions: funcions que retornen un valor.


1.8.2. Procediments

Un procediment és un bloc PL/SQL al que se li assigna un nom. Un procediment es crea


perquè faci una determinada tasca.
Els procediments es compilen i emmagatzemen a la base de dades. Gràcies a ells es pot
aconseguir fer una reutilització eficient del codi, ja que es pot invocar al procediment les
vegades que faci falta des d’un altre codi o des d’una eina de desenvolupament com pot
ser Oracle Developer. Un cop estan guardats també es poden modificar.
La seva sintaxi és:
CREATE [OR REPLACE]
PROCEDURE nom [(paràmetre1[, paràmetre2, ...])] IS|AS
seccióDeDeclaracions
BEGIN
instruccions
[EXCEPTION
controlDeExcepcions]
END[nom];

On, paràmetreN té la sintaxi:


<nomParàmetre> [IN | OUT | IN OUT] tipusDades [{:= |
DEFAULT} expr]

on:
 IN. Són els paràmetres que en altres llenguatges s’anomenen per valor. El
procediment rep una copia del valor o variable que s’utilitza com a paràmetre
al cridar el procediment. Aquests paràmetres poden ser: valors literals (18 per
exemple), variables (v_num per exemple) o expressions (com v_num+18). A
aquests paràmetres se’ls hi pot assignar un valor per defecte.
 OUT. Relacionats amb el pas per variable d’altres llenguatges. Només poden
ser variables i no poden tenir un valor per defecte. S’utilitzen perquè el
procediment hi guardi algun valor. És a dir, els paràmetres OUT són variables
que s’envien al procediment de manera que si en el procediment canvia el seu
valor, aquest valor es manté quan el procediment acaba.
 IN OUT. Són una combinació dels dos anteriors. Es tracta de variables on el
valor es pot utilitzar pel procediment que, a més a més, pot guardar-hi un
valor. No se’ls hi pot assignar un valor per defecte.

Si no s’especifica cap tipus de paràmetre sempre serà de tipus IN.
CREACIÓ DE PROCEDIMENTS
Els passos a seguir per crear procediments són:
Escriure el codi en un fitxer .sql des de qualsevol editor.
Carregar i compilar el codi mitjançant la línia de comandaments del SGBD (amb Oracle,
l’SQL*Plus).
Executar tants cops com sigui necessari el procediment creat. Amb SQL*Plus es fa
precedint el nom del procediment per la paraula EXECUTE.

24
UD3. SQL hostatjat SQL hostatjat

Exemple:
CREATE OR REPLACE PROCEDURE holaMon
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('HOLA MON’);
END holaMon;
/

Passos per carregar i executar el procediment:


SQL> @E:\holaMon.sql
(carrega i compila l’script, creant el procediment).
SQL> SHOW ERRORS
(per comprovar si hi ha hagut errors en la creació del proc.)
SQL> SET SERVEROUTPUT ON
(per activar la variable (DBMS_OUTPU.PUT_LINE) de l’entorn
SERVEROUTPUT).
SQL> EXECUTE holaMon;
(executa el procediment holaMon.).

Exemple:
CREATE OR REPLACE PROCEDURE consultarEmpleat
(v_Nom VARCHAR2, v_Num OUT NUMBER, v_ofici OUT VARCHAR2) IS
BEGIN
SELECT empl_num, empl_ofici INTO v_Num, v_ofici
FROM empl
WHERE empl_nom LIKE '%'||v_Nom||'%';
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No s’’han trobat dades');
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('Hi ha més d’una fila amb aquestes dades’);
END;

Un cop carregat el procediment, per cridar-lo s’hauria de fer de la següent forma:


DECLARE
v_c VARCHAR2(50);
v_d VARCHAR2(50);
BEGIN
consultarEmpleat('SANCHEZ',v_c,v_d);
DBMS_OUTPUT.PUT_LINE(v_c);
DBMS_OUTPUT.PUT_LINE(v_d);
END;
/

1.8.3. Funcions

Les funcions són un tipus especial de procediments que serveixen per calcular un
determinat valor. Tot el que s’ha comentat en l’apartat anterior és vàlid per les funcions,
la diferència està amb que aquestes només retornen un valor.

25
UD3. SQL hostatjat SQL hostatjat

Sintaxi:
CREATE [OR REPLACE]
FUNCTION nom [(paràmetre1[,paràmetre2 [,...]])] RETURN
tipusDades
IS|AS
seccióDeDeclaracions
BEGIN
instruccions
[EXCEPTION
controlDeExcepcions]
END[nom];

Un gran avantatge de les funcions és la possibilitat de utilitzar-les dins instruccions SQL.

Exemple:
CREATE OR REPLACE
FUNCTION salariMig RETURN NUMBER IS
v_salari NUMBER;
BEGIN
SELECT AVG(empl_salari) INTO v_salari
FROM empl;
RETURN v_salari;
END;

Aquesta funció retorna el salari mig dels empleats de la taula EMPL. Un cop compilada
la funció, es pot cridar des d’una instrucció SQL qualsevol.

Exemple:
SQL> SELECT empl_num, empl_nom, empl_salari
2 FROM empl
3 WHERE empl_salari < salariMig;

Cal tenir en compte que perquè les funcions es puguin cridar des d’SQL, han de complir
que :
 Les funcions han d’estar emmagatzemades.
 Només poden utilitzar paràmetres IN.
 Els seus paràmetres han de ser de tipus compatibles amb el llenguatge SQL
(no pot haver-hi paràmetres amb tipus específics de PL/SQL, com BOOLEAN).
 El tipus retornar ha de ser compatible amb SQL.
 No hi pot haver instruccions DML.
 Si una instrucció DML modifica una taula, en aquesta instrucció no es pot
cridar a una funció que faci consultes sobre la mateixa taula.
 No es poden utilitzar instruccions de transaccions (COMMIT,ROLLBACK).
 La funció no pot invocar una altra funció que se salti alguna de les regles
anteriors.

 Exemple:

CREATE OR REPLACE
FUNCTION edat(v_data DATE) RETURN NUMBER IS
v_edat NUMBER;
BEGIN
v_edat := TRUNC((SYSDATE-v_data)/365);
RETURN v_edat;
END;
/

26
UD3. SQL hostatjat SQL hostatjat

Ara podem utilitzar la funció dins una instrucció SELECT:


SELECT malalt_nom, malalt_dnaixa, EDAT(malalt_dnaixa)
FROM malalt;

1.8.4. Eliminar funcions

DROP FUNCTION nomFuncio;

27
UD3. SQL hostatjat SQL hostatjat avançat

Capítol 2. SQL hostatjat avançat (PL/SQL avançat)


2.1. Introducció

Després d’estudiar la introducció al PL/SQL, veient com es poden programar


procediments i funcions introduint sentencies SQL; ara farem un pas més i aprofundirem
la utilització del llenguatge PL/SQL, estudiant els paquets i els triggers (disparadors).
Tant els paquets com els triggers són blocs PL/SQL. La diferència és que els triggers
estan associats a una taula que es poden executar o disparar automàticament quan es
produeix un succés a la taula (insertar, esborrar o modificar files d’aquesta).

2.2. Paquets

Un paquet és una secció on s’hi poden definir procediments, funcions, cursors, tipus i
variables.
Els paquets no es poden cridar, parametritzar o eniuar.

2.2.1. Parts d’un paquet

Un paquet està format per dues parts: l’especificació i el cos o implementació.


L’especificació (o capçalera) del paquet, conté informació sobre el contingut del paquet.
No conté codi dels procediments.
El cos del paquet, és un objecte del diccionari de dades diferent de la capçalera. Aquest
cos no pot ser compilat sinó és que abans ja s’ha compilat la capçalera corresponent. El
cos conté el codi per les declaracions formals de subprogrames incloses dins la
capçalera.

2.2.2. Creació de l’especificació d’un paquet

Sintaxi:
CREATE [OR REPLACE] PACKAGE nomPaquet AS|IS
especificació_procediement | especificació_funció |
declaració_variable |
defició_tipus | declaració_excepció | declaració_cursor
END nomPaquet;

On:
especificació_procediement | especificació_funció | … són els elements del
paquet i són els mateixos que hi pot haver dins el DECLARE d’un bloc anònim.
Hi ha una sèrie de regles sintàctiques per la capçalera d’un paquet:
Els elements del paquet poder aparèixer en qualsevol ordre. De totes formes, un objecte
s’ha de declarar abans de poder-lo utilitzar. Per exemple, si tenim un cursor que dins el
WHERE utilitza una variable, aquesta s’ha de declarar abans que el cursor.
No és necessari incloure tots els tipus d’elements. Un paquet pot contenir només
especificacions de procediments i funcions, per exemple, sense declarar cap excepció ni
cap tipus.
Les declaracions de procediments i funcions han de ser declaracions formals, a
diferencia de la secció declarativa d’un bloc, que pot contenir tant declaracions formals
com el codi de procediments i funcions del paquet que es troba en el cos.

28
UD3. SQL hostatjat SQL hostatjat avançat

2.2.3. Creació del cos d’un paquet

Sintaxi:
CREATE [OR REPLACE] PACKAGE BODY nomPaquet AS | IS
declaracions | subprogrames PL/SQL
END nomPaquet;

2.2.4. Avantatges dels paquets

 Modularitat
 Facilitat del disseny de l’aplicació
 Informació oculta
 Funcionalitat afegida
 Millor rendiment
 Sobrecàrrega

Exemple: Crear un paquet que tingui un procediment anomenat salutacio. Aquest paquet
es dirà imprimir i els scripts on es guardarà el codi són :
Capçalera
CREATE OR REPLACE PACKAGE imprimir AS
PROCEDURE salutacio;
END imprimir;
/

Cos
CREATE OR REPLACE PACKAGE BODY imprimir AS
PROCEDURE salutacio IS
BEGIN
DBMS_OUTPUT.PUT_LINE('HOLA MON!!');
END salutacio;
END imprimir;
/

Després de compilar i executar els dos scripts, la crida es faria així:


SQL> EXEC imprimir.salutacio;
HOLA MON!!

Procedimiento PL/SQL terminado correctamente.

2.3. Triggers

Els triggers o disparadors de la base de dades són blocs PL/SQL emmagatzemats


associats a una taula que s’executen o es disparen automàticament quan es produeixen
certs esdeveniments o successos (inserció, esborrat o modificació de files) que afecten a
la taula.
Els disparadors s’assemblen als procediments i funcions, ja que són blocs PL/SQL amb
nom amb seccions declarativa, executable i de gestió d’excepcions.
Aquests disparadors s’emmagatzemen a la base de dades i no poden ser locals a un
bloc. A més a més, un disparador no admet paràmetres.
Però la principal pregunta que ens pot sorgir és perquè són necessaris els triggers?

29
UD3. SQL hostatjat SQL hostatjat avançat

 Per mantenir restriccions d’integritat complexes, que no és possible definir-les


en el moment de crear la taula.
 Portar un control sobre la informació que conté una taula, registrant els canvis
realitzats i/o qui ha fet els canvis i/o quan.
 Executar automàticament altres programes (procediments o funcions) en el
moment en que es fan canvis sobre les dades de la taula.

Sintaxi:
CREATE [OR REPLACE] TRIGGER nomTrigger
{BEFORE|AFTER|INSTEAD OF}
{DELETE|INSERT|UPDATE OF llistaCamps}
[OR {BEFORE|AFTER|INSTEAD OF}{DELETE|INSERT|UPDATE OF
llistaCamps}]
ON nomTaula
[FOR EACH {STATEMENT | ROW [WHEN (condició)]}]
instruccionsBlocPLSQL
[EXCEPTION
gestioExcepcions]
END;


30
UD3. SQL hostatjat SQL hostatjat avançat

2.3.1. Elements dels triggers

L’esdeveniment que executa el trigger (INSERT, UPDATE o DELETE).


Quan es tracta l’esdeveniment: BEFORE (abans), AFTER(després) o INSTEAD OF (en
lloc de).
Les vegades que s’executa el trigger: per cada instrucció o per cada fila.
El cos del trigger.

2.3.2. Quan s’ha d’executar el trigger?

 BEFORE. El codi del trigger s’executa just abans d’executar la instrucció DML
que ha provocat que s’activi el trigger.
 AFTER. El codi del trigger s’executa just després d’executar la instrucció DML
que ha provocat que s’activi el trigger.
 INSTEAD OF. El trigger substitueix a l’operació DML. S’utilitza per vistes que
no es poden modificar.


2.3.3. Tipus de trigger

Hi ha dos tipus de trigger:


 D’instrucció. El cos del trigger s’executa una única vegada per cada
esdeveniment que fa que s’activi el trigger. Aquesta és la opció per defecte. El
codi s’executa encara que la instrucció DML no afecti a cap fila.
 De fila. El codi s’executa una vegada per cada fila afectada per
l’esdeveniment. Per exemple, si una instrucció UPDATE que activa un trigger i
aquest UPDATE actualitza 10 files; si el trigger és de fila llavors s’executa una
vegada per cada fila.


Exemple: En aquest exemple s’activa el trigger de la taula EMPL cada vegada que
s’executa un INSERT sobre la taula, i genera una excepció en el cas que s’intenti
insertar un nou registre fora del període establert (entre les 9h i les 13h).
CREATE OR REPLACE TRIGGER tr_ins_empl
BEFORE INSERT ON empl
BEGIN
IF(TO_CHAR(SYSDATE,'HH24') NOT IN ('9','10','11','12','13')) THEN
RAISE_APPLICATION_ERROR(-20001,'Nomes es poden ' ||
' afegir empleats entre les 9:00 i les 13:59.');
END IF;
END;

31
UD3. SQL hostatjat SQL hostatjat avançat

2.3.4. Triggers de fila

Sintaxi:
CREATE [OR REPLACE] TRIGGER nomTrigger
clausulaDeTemps event1 [OR event2[,...]] ON taula
[REFERENCING {OLD AS nomVell | NEW AS nomNou}]
FOR EACH ROW [WHEN condició]
BEGIN
cos
END;

La diferència respecte als triggers d’instrucció és amb la instrucció REFERENCING i FOR


EACH ROW. Aquesta última és la que fa que la instrucció es repeteixi per cada registre
afectat per la instrucció DML.
L’apartat WHEN permet col·locar una condició que han de complir els registres perquè el
trigger s’executi. Només s’executa el trigger pels registres que compleixin aquesta
condició.
L’apartat REFERENCING és el que permet indicar un nom pels valors antic i un altre pels
nous.

2.3.5. Referències NEW i OLD

Quan s’executen instruccions UPDATE, cal tenir en compte que es modifiquen valors
antics (OLD) per canviar-los per valors nous (NEW). Les paraules NEW i OLD permeten
accedir als valors nous i antics respectivament.
L’apartat REFERENCING de la creació de triggers, permet assignar noms a les paraules
NEW i OLD (a la pràctica no sol utilitzar). Així, NEW.NOM faria referència al nou nom que
s’assigna a una determinada taula i OLD.NOM al vell.
A l’apartat d’instruccions del trigger ( a partir del BEGIN ) cal posar el símbol “:” davant
de les paraules NEW i OLD (per tant, tindríem :new.nom i :old.nom).
Exemple: Imaginem que volem fer una auditoria (enregistrar el que passa) sobre una
taula d’empleats. Aquesta taula és EMPL i conté les dades dels empleats d’una
empresa. Volem emmagatzemar en una altra taula diferent els canvis del salari que es fa
sobre els empleats, per la qual cosa creem la següent taula:
CREATE TABLE empl_audit(
empl_num NUMBER, -- codi empleat
salari_vell NUMBER(11,2), -- salari vell
salari_nou NUMBER(11,2), -- salari nou
data TIMESTAMP, -- data modificacio
usuari VARCHAR2(50), -- usuari que modifica
PRIMARY KEY(data,usuari)
);

32
UD3. SQL hostatjat SQL hostatjat avançat

Com que volem que la taula d’auditoria s’actualitzi automàticament, creem el següent
trigger:
CREATE OR REPLACE TRIGGER tr_audit_empl
BEFORE UPDATE OF EMPL_SALARI ON EMPL
FOR EACH ROW WHEN (OLD.empl_salari <> NEW.empl_salari)
BEGIN
INSERT INTO EMPL_AUDIT
VALUES(:NEW.empl_num,:OLD.empl_salari,:NEW.empl_salari,SYSTIMESTAMP,USER);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Error num. ‘|| SQLCODE);
DBMS_OUTPUT.PUT_LINE(‘Missatge error: ‘ || SQLERRM);
END;

Si s’executa la següent instrucció d’actualització sobre la taula EMPL:


SQL> UPDATE EMPL
2 SET EMPL_SALARI=200000
3 WHERE EMPL_SALARI<200000;

A la taula EMPL_AUDIT hi ha els següents registres (insertats amb el trigger):


SQL> SELECT * FROM EMPL_AUDIT;

EMPL_NUM SALARI_VELL SALARI_NOU DATA USUARI


---------- ----------- ---------- ------------------------ ------------------
7369 104000 200000 11/04/06 12:50:58,265000 MNICOLAU
7521 162500 200000 11/04/06 12:50:58,296000 MNICOLAU
7654 182000 200000 11/04/06 12:50:58,312000 MNICOLAU
7844 195000 200000 11/04/06 12:50:58,328000 MNICOLAU
7876 143000 200000 11/04/06 12:50:58,343000 MNICOLAU
7900 123500 200000 11/04/06 12:50:58,359000 MNICOLAU
7934 169000 200000 11/04/06 12:50:58,375000 MNICOLAU

2.3.6. IF INSERTING, IF UPDATING i IF DELETING

Són paraules que s’utilitzen per determinar la instrucció que s’estava fent quan s’ha
activat el trigger. Això s’utilitza amb triggers que s’activen per varies operacions (utilitzant
INSERT OR UPDATE, per exemple). En aquest cas s’utilitzen sentències IF seguides de
INSERTING, UPDATING o DELETING; aquestes paraules tornaran TRUE si estava fent
aquella operació.
Exemple:
CREATE OR REPLACE TRIGGER trigger1
BEFORE INSERT OR DELETE OR UPDATE OF camp1 ON taula
FOR EACH ROW
BEGIN
IF DELETING THEN
....
ELSIF INSERTING THEN
....
ELSE -- estarà actualitzant, UPDATING
...
ENDIF
END;

2.3.7. Triggers INSTEAD OF

Hi ha un tipus de trigger especial que s’anomena INSTEAD OF i que només s’utilitza amb
les vistes.

33
UD3. SQL hostatjat SQL hostatjat avançat

Exemple: Tenim una vista que mostra les dades d’empleats i del departament on estan
assignats.
CREATE VIEW empleats_i_departaments(num,nom,num_dept,departament) AS
SELECT empl_num, empl_nom, dept_num, dept_nom
FROM empl, dept
WHERE empl_dept_num = dept_num
ORDER BY empl_num;

Si s’executés aquesta instrucció, donaria error:


INSERT INTO empleats_i_departaments
VALUES(8000,'PERE PI',50,'Programacio');

indicant que aquesta operació no és vàlida en aquesta vista (ja que utilitza dues taules).
Aquesta situació la pot solucionar un trigger que insereixi primer a la taula de
departaments (només si no existeix a la taula DEPT) i llavors insereixi l’empleat.
Això ho permet fer un trigger INSTEAD OF, que substitueixi l’INSERT original pel que fa
el cos del trigger:
CREATE OR REPLACE TRIGGER trg_ins_empleats_i_departament
INSTEAD OF INSERT
ON empleats_i_departaments
DECLARE
nDepts NUMBER;
BEGIN
SELECT COUNT(*) INTO nDepts
FROM DEPT
WHERE dept_num = :NEW.num_dept;
IF nDepts=0 THEN
INSERT INTO DEPT(dept_num, dept_nom)
VALUES(:NEW.num_dept,:NEW.departament);
END IF;
INSERT INTO EMPL(empl_num,empl_nom,empl_dept_num)
VALUES(:NEW.num,:NEW.nom,:NEW.num_dept);
END;

Aquest trigger permet afegir a aquesta vista afegint els camps necessaris a les taules
relacionades a la vista. Es podria modificar el trigger per permetre actualitzar, eliminar o
esborrar dades directament des de la vista i així es podria utilitzar aquesta vista com si
fos una taula.

34
UD3. SQL hostatjat SQL hostatjat avançat

2.3.8. Exemples

Crear un trigger que controli que no es pugui inserir un departament sense indicar la
seva localització.
-- CREAR EL TRIGGER A NIVELL DE FILA (localitzacio NO NULL)
CREATE OR REPLACE TRIGGER trig_loc_no_nul
BEFORE INSERT ON DEPT
FOR EACH ROW
BEGIN
IF :NEW.dept_loc IS NULL THEN
RAISE_APPLICATION_ERROR (-20001,'ERROR: LOCALITZACIO DEL ' ||
' DEPARTAMENT TE VALOR NULL');
END IF;
END;
/

Crear un trigger que mostri el missatge correcte en funció de l’operació realitzada:


Quan s’insereix un registre ha de dir: S’HA AFEGIT UN REGISTRE.
Quan es modificar un registre ha de dir: S’HA MODIFICAT UN REGISTRE.
Quan s’esborri un registre i el nom del departament sigui Programacio ha de dir:
ESBORRAT EL DEPARTAMENT PROGRAMACIO. En els altres casos: S’HA ELIMINAT
UN REGISTRE.
Un cop fet això cal generar un script per comprovar que funciona el trigger, que ha de fer
el següent:
Inserir el registre (90,’Programacio’,’Barcelona’).
Modificar el camp dept_loc i posar-lo amb majúscules.
Esborrar el departament 90 i el departament 50.
El codi del trigger és:
CREATE OR REPLACE TRIGGER trg_departament
BEFORE INSERT OR DELETE OR UPDATE OF dept_loc ON dept
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS_OUTPUT.PUT_LINE('S´HA AFEGIT UN REGISTRE.');
ELSIF UPDATING THEN
DBMS_OUTPUT.PUT_LINE('S´HA MODIFICAT UN REGISTRE.');
ELSIF DELETING THEN
IF :OLD.dept_nom = UPPER('PROGRAMACIO') THEN
DBMS_OUTPUT.PUT_LINE('S´HA ESBORRAT EL ' ||
'DEPARTAMENT PROGRAMACIO.');
ELSE
DBMS_OUTPUT.PUT_LINE('S´HA ESBORRAT UN REGISTRE.');
END IF;
END IF;
END trg_departament;

I el codi de l’script per comprovar el funcionament del trigger és:


--AFEGIR UN DEPARTAMENT
INSERT INTO dept
VALUES(90,'Programacio','Barcelona');

--MODIFICAR
UPDATE dept
SET dept_loc = UPPER(dept_loc);

--ESBORRAR
DELETE FROM dept
WHERE dept_num=90;

35
UD3. SQL hostatjat SQL hostatjat avançat

DELETE FROM dept


WHERE dept_num=50;

2.3.9. Administració de triggers

ESBORRAR TRIGGERS
DROP TRIGGER nomTrigger;

DESACTIVAR UN TRIGGER
ALTER TRIGGER nomTrigger DISABLE;

ACTIVAR UN TRIGGER
ALTER TRIGGER nomTrigger ENABLE;

DESACTIVAR O ACTIVAR TOTS ELS TRIGGERS D’UNA TAULA


ALTER TABLE nomTaula {DISABLE | ENABLE} ALL TRIGGERS;

36
Àlgebra relacional
Operacions de l’àlgebra relacional. Relació amb
les operacions SQL.
Contingut

Contingut

Capítol 1. Introducció ...........................................................................................3


Capítol 2. Operació auxiliar..................................................................................4
2.1. Reanomenar ............................................................................................................. 4
Capítol 3. Operacions primitives .........................................................................5
3.1. Unió........................................................................................................................... 5
3.2. Diferència.................................................................................................................. 6
3.3. Producte cartesià ...................................................................................................... 7
3.4. Selecció .................................................................................................................... 9
3.5. Projecció ................................................................................................................... 9
Capítol 4. Operacions no primitives ..................................................................11
4.1. Intersecció............................................................................................................... 11
4.2. Combinació ............................................................................................................. 11
Capítol 5. Seqüències d’operacions de l’àlgebra relacional ...........................13

ii
UD4. Àlgebra relacional Introducció

Capítol 1. Introducció

Com ja s’ha comentat en l’apartat dedicat a les operacions del model relacional (UD1),
l’àlgebra relacional s’inspira en la teoria de conjunts per especificar consultes a una base
de dades relacional.
Per especificar una consulta amb àlgebra relacional, cal definir una o més passes que
serveixin per anar construint, mitjançant operacions de l’àlgebra relacional, una nova
relació que contingui les dades que responen a la consulta a partir de les relacions
emmagatzemades. Els llenguatges basats amb l’àlgebra relacional són procedimentals,
ja que les passes que formen la consulta descriuen un procediment.
La visió que es presenta aquí és la d’un llenguatge teòric i, per tant, s’inclouen només les
seves operacions fonamentals, i no les construccions que es podrien afegir a un
llenguatge comercial per facilitar tasques com per exemple l’ordre de presentació del
resultat, el càlcul de dades d’agregats, etc.
Una característica destacable de totes les operacions de l’àlgebra relacional és que tant
els operands com el resultat són relacions. Aquesta propietat s’anomena tancament
relacional.
Aquest fet té implicacions importants:
El resultat d’una operació pot actuar com operand d’una altra operació.
El resultat d’una operació complirà totes les característiques de les relacions.

Les operacions de l’àlgebra relacional es classifiquen segons varis criteris:


Segons es puguin expressar o no en termes d’altres operacions.
Operacions primitives: són les operacions a partir de les quals es poden definir la resta.
Aquestes operacions són la unió, la diferència, el producte cartesià, la selecció i la
projecció.
Operacions no primitives: la resta de les operacions de l’àlgebra relacional que no són
estrictament necessàries, perquè es poden descomposar amb primitives; no obstant, les
operacions no primitives permeten fer algunes consultes de forma més còmode. Hi ha
diferents versions de l’àlgebra relacional, segons les operacions no primitives que
s’inclouen. Nosaltres estudiarem les operacions no primitives que s’utilitzen més: la
intersecció i la combinació.
Segons el nombre de relacions que tenen com operands:
Operacions binàries: són les que tenen dos relacions com operands. Són binàries totes
les operacions, menys la selecció i la projecció.
Operacions unàries: són les que tenen una única relació com a operand. La selecció i la
projecció són unàries.
Segons s’assemblin o no a la teoria de conjunts:
Operacions de conjunts: les que s’assemblen a les de la teoria de conjunts. Són la unió,
la intersecció, la diferència i el producte cartesià.
Operacions específicament relacionals: la resta d’operacions; és a dir, la selecció, la
projecció i la combinació.

3
UD4. Àlgebra relacional Operació auxiliar

Capítol 2. Operació auxiliar

2.1. Reanomenar

L’operació reanomenar, que indicarem amb el símbol :=, permet assignar un nom R a la
relació resultant d’una operació de l’àlgebra relacional, i s’escriu així:
R := E
On E és l’expressió d’una operació de l’àlgebra relacional.
Cada operació de l’àlgebra relacional dóna un noms per defecte als atributs de
l’esquema de la relació resultat. En alguns casos potser interessa canviar aquests noms
per defecte per uns altres. Per aquest motiu, amb l’opció reanomenar també podrem
canviar el nom dels atributs d’una relació.
Utilitzarem també l’operació reanomenar per canviar l’esquema d’una relació. Si una
relació té l’esquema S(B1,B2,...,Bn) i el volem canviar per R(A1,A2,...,An), ho
farem de la següent manera:
R(A1,A2,...,An) := S(B1,B2,...,Bn)

4
UD4. Àlgebra relacional Operacions primitives

Capítol 3. Operacions primitives

3.1. Unió

Operació que, a partir de dues relacions, obté una nova relació formada per les tuples de
les dues relacions, sense repeticions.
La unió és una operació binària, i la unió de dues relacions r i s s’indica com a r ∪ s .
Per poder aplicar la unió a dues relacions, cal que les dues relacions siguin compatibles.
Direm que dues relacions r i s són relacions compatibles si:
Tenen el mateix grau.
Es pot establir una correspondència entre els atributs dels esquemes de relació R i de S
de tal manera que a cada atribut Ai de R li correspon un atribut Aj de S, de manera que
es compleixi que dom(Ai) = dom(Aj).

Els atributs de l’esquema de la relació resultant de R ∪ S coincideixen amb els atributs de


l’esquema de la relació R.
La relació resultant r ∪ s és el conjunt de tuples que pertanyen a la relació r, a la
relació s o a ambdues.
Gràficament, la unió es pot expressar de la següent manera:

Exemple 1:
Suposem que tenim les següents relacions:
EMPLEAT_ADM
DNI nom cognom edifici despatx
40175678 Pere Pi ED1 120
40347890 Josep Pujol ED1 120

EMPLEAT_PROD
DNI nomEmpl cognomEmpl edificiEmpl despatxEmpl
40175678 Pere Pi ED1 120
77900707 Anna Puig ED2 120
41234567 Manel Amat ED1 213
77232144 Jordi Soler NUL NUL
88999210 Marta Roca NUL NUL

Si volem obtenir una relació EMPLEAT que contingui tots els empleats de l’empresa, cal
fer la unió de les relacions EMPLEAT_ADM i EMPLEAT_PROD de la següent forma:
EMPLEAT := EMPLEAT _ ADM ∪ EMPLEAT _ PROD

5
UD4. Àlgebra relacional Operacions primitives

La relació resultant serà la que es mostra a la taula següent:


EMPLEAT
DNI nom cognom edificiEmpl despatxEmpl
40175678 Pere Pi ED1 120
77900707 Anna Puig ED2 120
41234567 Manel Amat ED1 213
77232144 Jordi Soler NUL NUL
88999210 Marta Roca NUL NUL
40347890 Josep Pujol ED1 120

Com es pot observar, s’ha agafat la convenció de que els atributs de la relació resultant
coincideixin amb els atributs de la relació que figura en primer lloc.

3.2. Diferència

La diferència és una operació que, a partir de dues relacions, obté una nova relació
formada per les tuples que estan a la primera relació i que no estan a la segona.
La diferència és una operació binària, i la diferència de dues relacions r i s s’indica com
a r −s .
Com en el cas de la unió i la intersecció, la diferència només es pot aplicar a relacions
que tinguin tuples similars. Per poder fer la diferència de dues relacions, cal que les
relacions siguin compatibles.
Els atributs de l’esquema de la relació resultant de R − S coincideixen amb els atributs
de l’esquema de la relació R.
La relació resultant r − s és el conjunt de tuples que pertanyen a la relació r, però no a
la relació s.

6
UD4. Àlgebra relacional Operacions primitives

Gràficament, la diferència es pot expressar de la següent manera:


R

Exemple 2:
Suposem que tenim les relacions de l’exemple 1. Si volem obtenir una relació
EMPLEAT_NOMES_ADM que contingui els empleats de l’empresa que treballen a
administració, però no a producció, farem la diferència de les relacions EMPLEAT_ADM i
EMPLEAT_PROD de la següent forma:
EMPLEAT _ NOMES _ ADM := EMPLEAT _ ADM − EMPLEAT _ PROD
La relació resultant serà la que es mostra a la taula següent:
EMPLEAT_NOMES_ADM
DNI nom cognom edificiEmpl despatxEmpl
40347890 Josep Pujol ED1 120

Com es pot observar, s’ha agafat la convenció de que els atributs de la relació resultant
coincideixin amb els atributs de la relació que figura en primer lloc.

3.3. Producte cartesià

El producte cartesià és una operació que, a partir de dues relacions, obté una nova
relació formada per totes les tuples que són el resultat de concatenar tuples de la
primera relació amb tuples de la segona.
El producte cartesià és una operació binària. Essent r i s dues relacions que compleixen
que els seus esquemes no tenen cap atribut comú, el producte cartesià de r i s s’indica
com a r × s .
Si es vol calcular el producte cartesià de dues relacions que tenen algun nom d’atribut
comú, només fa falta reanomenar abans els atributs necessaris en una de les dues
relacions.
Els atributs de l’esquema de la relació resultant de R × S són tots els atributs de R i tots
els atributs de S.
La relació resultant r × s és el conjunt de totes les tuples de la forma
<v1,v2,...,vn,w1,w2,...,wm> per les que es compleix que <v1,v2,...,vn> pertany
a la relació r i <w1,w2,...,wm> pertany a la relació s.
Gràficament, el producte cartesià es pot expressar de la següent manera:
a 1 a 1
b X 2 = a 2
c b 1
b 2
c 1
c 2

7
UD4. Àlgebra relacional Operacions primitives

Exemple 3:
Suposem que tenim la relació EMPLEAT_ADM i la següent relació:
DESPATX
edifici numDespatx superfície
ED1 120 10
ED1 230 20
Si volem fer el ED2 120 10 producte cartesià:
ED2 440 10
EMPL _ DESPATX := EMPLEAT _ ADM − DESPATX

La relació resultant serà la que es mostra a la taula següent:


EMPL_DESPATX
DNI nom cognom edificiEm despatxEm edifi numDespa superfic
pl pl ci tx ie
403478 Jos Puj ED1 120 ED1 120 10
90 ep ol
403478 Jos Puj ED1 120 ED1 230 20
90 ep ol
403478 Jos Puj ED1 120 ED2 120 10
90 ep ol
403478 Jos Puj ED1 120 ED2 440 10
90 ep ol
401756 Per Pi ED1 120 ED1 120 10
78 e
401756 Per Pi ED1 120 ED1 230 20
78 e
401756 Per Pi ED1 120 ED2 120 10
78 e
401756 Per Pi ED1 120 ED2 440 10
78 e

El producte cartesià és una operació que rarament s’utilitza de manera explícita, ja que
el resultat que dóna no acostuma a ser útil per resoldre consultes habituals.

8
UD4. Àlgebra relacional Operacions primitives

3.4. Selecció

Es defineix l’operació de selecció σ sobre una relació r amb uns criteris de selecció c,
com l’obtenció de les tuples de r que compleixen els criteris indicats a c, donant com a
resultat la nova relació S. S’escriu de la següent manera:
s := σ < c > (r )

En els criteris c es poden utilitzar els operadors de comparació ≥, ≤, <, >, =, ≠ i els lògics
I, O i NO.

Exemple 4: Suposem que tenim la següent relació:


ALUMNE
DNI nom cog1 cog2 poblacio
46676676 Pere Pujol Oriol Olot
70765432 Marc Pi Ferrer Besalú
40404040 Mireia Vila Vila Riudaura
42345678 Anna Juncà Vilanova Olot Es
vol obtenir les dades dels alumnes d’Olot:
σ
ALUMNES _ OLOT := poblacio = ' Olot' (ALUMNE )

Dóna com a resultat:


ALUMNES_OLOT
DNI nom cog1 cog2 poblacio
46676676 Pere Pujol Oriol Olot
42345678 Anna Juncà Vilanova Olot

3.5. Projecció

Es defineix l’operació de projecció П sobre una relació r com l’obtenció d’una nova

π
relació s que té un subconjunt dels atributs de r. S’escriu de la següent manera:
s := < A 1, A 2 ,..., Ai > (r )
On A1,A2,...,Ai és un subconjunt dels atributs de l’esquema de relació R.

9
UD4. Àlgebra relacional Operacions primitives

Exemple 5: Obtenir el DNI, nom i primer cognom dels alumnes:


π
ALUMNE 2 := DNI , nom , cog1(ALUMNE )

Dóna com a resultat:


ALUMNE2
DNI nom cog1
46676676 Pere Pujol
70765432 Marc Pi
40404040 Mireia Vila
42345678 Anna Juncà

10
UD4. Àlgebra relacional Operacions no primitives

Capítol 4. Operacions no primitives

4.1. Intersecció

La intersecció és una operació que, a partir de dues relacions, obté una nova relació
formada per les tuples que pertanyen a les dues relacions.
La intersecció és una operació binària, i la intersecció de dues relacions r i s s’indica
com a r ∩ s .
Com en el cas de la unió, la intersecció només es pot aplicar a relacions que tinguin
tuples similars. Per poder fer la intersecció de dues relacions, cal que les relacions siguin
compatibles.
Els atributs de l’esquema de la relació resultant de R ∩ S coincideixen amb els atributs de
l’esquema de la relació R.
La relació resultant r ∩ s és el conjunt de tuples que pertanyen a la relació r i a la
relació s.
Gràficament, la intersecció es pot expressar de la següent manera:

Exemple 6:
Suposem que tenim les relacions de l’exemple 1. Si volem obtenir una relació EMPLEAT
que contingui els empleats de l’empresa que treballen tant a administració com a
producció, farem la intersecció de les relacions EMPLEAT_ADM i EMPLEAT_PROD de
la següent forma:
EMPLEAT _ ADM _ PROD := EMPLEAT _ ADM ∩ EMPLEAT _ PROD
La relació resultant serà la que es mostra a la taula següent:
EMPLEAT_ADM_PROD
DNI nom cognom edificiEmpl despatxEmpl
40175678 Pere Pi ED1 120

Com es pot observar, s’ha agafat la convenció de que els atributs de la relació resultant
coincideixin amb els atributs de la relació que figura en primer lloc.

4.2. Combinació

11
UD4. Àlgebra relacional Operacions no primitives

És l’operació binària que permet seleccionar les tuples del producte cartesià entre dues
relacions r i S, les quals compleixen el/s criteri/s d’igualtat c en una o més parelles
d’atributs dels esquemes de relació de R i S. S’escriu de la següent manera:
t := rθ < c > s

π σ
Amb operacions fonamentals s’escriuria així:
t := rθ < c > s= (R ∪ S ) ( <c > (r × s))
Els atributs de la projecció poden ser de R i de S. Els criteris c de la selecció indiquen
quina és la condició.

Exemple 7: Tenim les següents relacions:


ALUMNE
DNI nom cog1 cog2 codPob
46676676 Pere Pujol Oriol 1
70765432 Marc Pi Ferrer 2
40404040 Mireia Vila Vila 3
42345678 Anna Juncà Vilanova 1
POBLACIO
codi nomPob
1 Olot
2 Besalú
3 Riudaura
4 La
Canya

ALUMNE3 := ALUMNEθcodPob = codiPOBLACIO =


π DNI , nom , cog 1, cog 2 , nomPob σ
( codPob = codi(ALUMNE × POBLACIO ))

ALUMNE3
DNI nom cog1 cog2 nomPob
46676676 Pere Pujol Oriol Olot
70765432 Marc Pi Ferrer Besalú
40404040 Mireia Vila Vila Riudaura
42345678 Anna Juncà Vilanova Olot

12
UD4. Àlgebra relacional Seqüències d’operacions de l’àlgebra relacional

Capítol 5. Seqüències d’operacions de l’àlgebra relacional

En molts casos, per formular una consulta utilitzant els operadors de l’àlgebra relacional
és necessari utilitzar varies operacions, que s’apliquen en un cert ordre.
Per fer-ho, hi ha dues maneres:
Utilitzar una única expressió de l’àlgebra que inclogui totes les operacions amb els
parèntesis necessaris per indicar l’ordre d’aplicació.
Descomposar l’expressió en varis passos on cada pas apliqui una única operació i
obtingui una relació intermitja que es pugui utilitzar en els passos següents.
Exemples:
ALUMNE
DNI nom cog1 cog2 codPob
46676676 Pere Pujol Oriol 1
70765432 Marc Pi Ferrer 2
40404040 Mireia Vila Vila 3
42345678 Anna Juncà Vilanova 1
POBLACIO
codi nomPob
1 Olot
2 Besalú
3 Riudaura
Obtenir el codi de la 4 La
poblacions de les quals no
hi ha cap alumne: Canya
π
P := codi(POBLACIO )
Obtenir el codi de les poblacions
π
P _ ALUM := codPob (ALUMNE )
Obtenir el codi de població de cada alumne
RES := P − P _ ALUM
RES conté els codi de poblacions que no són els codis de poblacions que apareixen a la
relació P_ALUM.

13
UD4. Àlgebra relacional Seqüències d’operacions de l’àlgebra relacional

Obtenir el nom de la poblacions de les quals no hi ha cap alumne:


π
P := codi(POBLACIO )
Obtenir el codi de les poblacions
π
P _ ALUM := codPob (ALUMNE )
Obtenir el codi de població de cada alumne
POB _ NO _ ALUM := P − P _ ALUM
POB_NO_ALUM conté els codi de poblacions que no són els codis de poblacions que
apareixen a la relació P_ALUM.
POB _ NO _ ALUM 2(codiPob ) := POB _ NO _ ALUM (codi)
Reanomenar l’esquema de relació POB_NO_ALUM(codi) per
POB_NO_ALUM2(codiPob)
COMB := POB _ NO _ ALUM 2θcodiPob = codiPOBLACIO
Combinar les dues relacions.
π
NOM _ POB := nomPob (COMB )
Obtenir el nom de les poblacions que no tenen cap alumne.
Obtenir el nom i cognoms dels alumnes d’Olot:
COMB := ALUMNEθcodPob = codiPOBLACIO
Combinar les relacions ALUMNE i POBLACIO.
σ
ALUM _ OLOT := nomPob = ' Olot' (COMB )
Seleccionar les tuples de relació COMB que tinguin per nom de població Olot.
π
NOM _ COG _ ALUM _ OLOT := nom , cog 1, cog 2(ALUM _ OLOT )
Obtenir el nom i cognoms de les tuples de ALUM_OLOT.

14
Annex I. SGBD
Oracle. Eines
Descripció del SGBDR Oracle i les eines que
permeten interactuar-hi.
Contingut

Contingut

Capítol 1. Notes prèvies ....................................................................................... 2


1.1. Simbologia ................................................................................................................ 2
Capítol 3. Oracle ................................................................................................... 3
3.1. Característiques........................................................................................................ 3
3.2. Estructura lògica i física............................................................................................ 3
3.3. Seguretat .................................................................................................................. 5
Capítol 4. SQL*Plus .............................................................................................. 6
4.1. Introducció ................................................................................................................ 6
4.2. El buffer .................................................................................................................... 6
4.3. SQL vs SQL*Plus ..................................................................................................... 6
4.4. Visió general de SQL*Plus ....................................................................................... 6
4.5. Connexió................................................................................................................... 7
4.6. Comandes ................................................................................................................ 8
4.6.1. Veure l’estructura d’una taula......................................................................... 8
4.6.2. Comandes d’edició ......................................................................................... 9
4.6.3. Comandes de fitxer ...................................................................................... 10
4.6.4. Altres comandes........................................................................................... 12
4.7. Paràmetres d’entorn ............................................................................................... 12

i
Annex I. SGBD Oracle. Eines Notes prèvies

Capítol 1. Notes prèvies

1.1. Simbologia

En aquest document s’utilitza una simbologia i formats específics per tal de simplificar-ne
la lectura i comprensió.
Quan es faci referència a la sintaxi d’alguna instrucció s’utilitzen els següents símbols:
[text], significa que el text és opcional.
{A|...|B}, significa alternativa, és a dir, que s’ha d’escollir una entre totes les opcions
que hi ha entre claus.
Text amb lletra Courier New: tot el text que forma part de la sintaxi d’alguna instrucció.
Text amb negreta: paraules clau que formen sempre part de la instrucció.
Text amb lletra Courier New i fons gris: indica una instrucció SQL.

2
Annex I. SGBD Oracle. Eines Oracle

Capítol 2. Oracle
2.1. Característiques

Oracle és un SGBD que suporta tant el model relacional com el objecte-relacional.


Les seves principals característiques són:
Entorn client/servidor.
Gestió de grans bases de dades: fins a 512 Peta Bytes (1 Peta Byte = 1024 D’arabites),
a la versió Oracle 9i
Usuaris concurrents: desenes de milers d’usuaris simultanis (Oracle 9i).
Alt rendiment en transaccions.
Disponibilitat controlada de les dades de les aplicacions.
Adaptació a estàndards, com SQL-92.
Gestió de la seguretat.
Autogestió de la integritat de les dades.
Opció distribuïda.
Portabilitat.

2.2. Estructura lògica i física

Oracle té una estructura dividida en dues parts:


Estructura lògica: indica com s’utilitza l’espai físic. Els principals components són:
Un o més tablespaces: àrea lògica d’emmagatzematge que s’utilitza per agrupar
estructures lògiques relacionades.
Els objectes dels diferents esquemes: col·leccions d’objectes de la base de dades.
Altres components de l’estructura lògica són:
Objectes de l’esquema: estructures lògiques que fan referència directa a les dades de la
base de dades (taules, vistes, seqüències, etc.)
Blocs de dades: estructures lògiques de més baix nivell. Una base de dades
s’emmagatzema en blocs de dades, que es corresponen amb un nombre determinat de
bytes d’espai de disc.
Extensió: nombre específic de blocs de dades contigus, que s’utilitza per emmagatzemar
un tipus determinat d’informació.

3
Annex I. SGBD Oracle. Eines Oracle

Segment: conjunt d’extensions reservades per una determinada estructura lògica


(segments de dades, segments d’índexs, etc.)
Els objectes de l’esquema i les relacions entre ells formen el disseny relacional de la
base de dades.
Estructura física: formada pels fitxers físics que formen la base de dades. Tota base de
dades Oracle consta de tres tipus de fitxers:
Un o més fitxers de dades: contenen les dades de la base de dades. Les
característiques d’aquests fitxers són:
Un fitxer només pot estar vinculat a una base de dades.
Tenen atributs que permeten reservar de forma automàtica extensions quan s’acaba
l’espai.
Un o més fitxers de dades formen la unitat lògica d’emmagatzematge tablespace.
Un o més fitxers de redo log.
Emmagatzemen tots els canvis fets a la base de dades.
S’utilitzen en cas d’error crític de la base de dades per recuperar-la.

4
Annex I. SGBD Oracle. Eines Oracle

Un o més fitxers de control. Contenen:


El nom de la base de dades.
Els noms i ubicació dels fitxers de la base de dades i dels fitxers log.
Data de creació de la base de dades.
Informació de sincronització per el procés de recuperació de la base de dades.

2.3. Seguretat

El servidor Oracle proporciona un control d’accessos restringint la informació mitjançant


privilegis.
La seguretat de la base de dades es gestiona amb:
Usuaris i esquemes de la base de dades.
Privilegis.
Rols.
Ajustaments de rendiment i quotes.
Límits sobre els recursos.
Auditoria.
Cada usuari té un domini de seguretat:
Accions (privilegis i rols) disponibles per l’usuari.
Quotes sobre tablespaces.
Límits en els recursos del sistema.

5
Annex I. SGBD Oracle. Eines SQL*Plus

Capítol 3. SQL*Plus
3.1. Introducció

SQL*Plus és una aplicació d’Oracle que reconeix i envia sentències SQL i PL/SQL
(extensió d’ SQL) al servidor Oracle perquè aquest els executi. Bàsicament, es tracta
d’un intèrpret SQL amb algunes opcions d’edició i formatació de resultats.
Quan un usuari escriu un comandament dins SQL*Plus, aquest comprova que estigui
ben escrita.

3.2. El buffer

Cada vegada que l’usuari introdueix una sentència SQL, aquesta es guarda a una part
de la memòria anomenada buffer SQL fins que s’entra una nova sentència SQL. Si la
sentència acaba amb punt i coma (;), s’executa immediatament. Un cop dins el buffer, la
sentència es pot editar i executar tantes vegades com es vulgui.
El comandament run (r) llista el contingut del buffer i, tot seguit, executa la sentència. El
comandament / executa la sentència del buffer, sense llistar-la abans.
El buffer guarda una única sentència SQL a la vegada, de tal manera que se sobreescriu
cada vegada que s’introdueix una nova sentència.

3.3. SQL vs SQL*Plus

Cal saber distingir entre sentències SQL i comandes SQL*Plus. Per això es mostra la
següent taula comparativa:
SQL SQL*Plus
És un llenguatge per comunicar-se Reconeix les sentències SQL i les
amb el SGBDR i accedir a les envia al servidor
dades.
És un estàndard ANSI És propietat d’Oracle
Permet manipular dades i No permet la manipulació de valors
definicions d’objectes de la base de de la base de dades
dades
Les sentències SQL s’introdueixen Els comandaments SQL*Plus no es
en el buffer SQL en una o més guarden al buffer.
línies.
Utilitza un caràcter de fi per No necessita caràcter de fi.
executar les sentències
immediatament.
Les paraules clau no es poden Les paraules clau es poden abreujar
abreujar

3.4. Visió general de SQL*Plus

SQL*Plus és un entorn en el que es pot fer el següent:

6
Annex I. SGBD Oracle. Eines SQL*Plus

Executar sentències SQL per recuperar, modificar, afegir i eliminar dades de la base de
dades.
Formatar, fer càlculs, emmagatzemar i imprimir resultats de consulta en forma
d’informes.
Crear fitxers de comandes per guardar sentències SQL i poder-les utilitzar posteriorment.
Les comandes SQL*Plus es poden dividir en les següents categories:
Categoria Objectiu
Entorn Canviar el comportament general de les sentències SQL
per la sessió de treball.
Format Formatar resultats de consulta
Manipulació de Guardar, carregar i executar fitxers de comandes
fitxers
Execució Enviar sentències SQL del buffer SQL al servidor Oracle
Edició Modificar sentències SQL en el buffer
Interacció Crear i transferir variables a sentències SQL, imprimir
valors de variables i imprimir missatges per pantalla
Altres Connectar-se a la base de dades, manipular l’entorn
SQL*Plus i mostrar definicions de columna.

3.5. Connexió

SQL*Plus és una aplicació que es troba instal·lada a l’ordinador client (el que es
connecta amb el servidor Oracle). Però no n’hi ha prou amb que estigui instal·lada sinó
que també cal que estigui ben configurada.
La primera configuració que cal fer, és la del fitxer tnsnames.ora (que es troba dins el
subdirectori /network/admin, dins el directori d’instal·lació del client d’Oracle). En
aquest fitxer s’hi troba la informació de les diferents connexions a servidors Oracle que
es poden fer amb SQL*Plus.
Un exemple del contingut d’aquest fitxer és:
XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)

BCOMAXE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oraserver)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
Contingut d’un fitxer tnsnames.ora
Com es pot observar, en aquest fitxer hi ha dues configuracions: XE i ORASI2. Aquests
són els noms de les connexions que es podran indicar des de SQL*Plus. Si ens hi fixem
podem veure com en el primer cas, la connexió es fa sobre la mateixa màquina on hi ha
SQL*Plus instal·lat (ja que la IP del HOST és 127.0.0.1). A més a més, s’indica que la
connexió s’estableix utilitzant el protocol TCP i pel port 1521 (que és el port per defecte
d’Oracle). El valor del port es pot canviar si la instal·lació en el port es fa en un de

7
Annex I. SGBD Oracle. Eines SQL*Plus

diferent. Finalment, hi ha la secció CONNECT_DATA, amb dos atributs: SERVER i


SERVICE_NAME. SERVER indica el tipus de servidor i SERVICE_NAME, el nom que té la
instal·lació del servei a la màquina indicada. Es poden configurar altres paràmetres i
atributs, però no hi entrarem en detall.
Si ens fixem en l’altra connexió, ORASI2, podem veure que és igual que en la primera,
però el HOST és un de diferent.
Si s’ha configurat bé la connexió, quan s’accedeixi al servidor Oracle amb aquest
programa sempre demanarà l’usuari i la contrasenya. Aquestes dades les ha de
proporcionar l’administrador (DBA) als usuaris.
Per connectar amb l’SQL*Plus podem anar a la línia de comandaments del sistema
operatiu i escriure:
sqlplus usuari[/contrasenya]@cadenaConnexióBD
Exemples:
sqlplus usuari1/1234@oraxe
sqlplus usuari1@oraxe

En el segon cas demanaria la contrasenya a continuació.


Si la connexió ha estat correcta, tot seguit apareix el següent:
Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL>

Darrera aquest “prompt” podem escriure les instruccions SQL i/o SQL*Plus. Cal tenir en
compte que el símbol SQL> pot canviar per un símbol amb números 1, 2, 3, etc., la qual
cosa indica que la instrucció no ha acabat (possiblement falti el ; final) indicant la línia en
la que estem.

3.6. Comandes

3.6.1. Veure l’estructura d’una taula

Per veure l’estructura d’una taula amb SQL*Plus s’utilitza la comanda DESCRIBE. El
resultat d’executar aquesta comanda és que mostra els noms de columna i tipus de
dades de la taula. També mostra si la columna de la taula ha de tenir dades
obligatòriament o no.
Sintaxi:
DESC[RIBE] nomTaula

(la part entre [] és opcional)


Exemple: mostrar la descripció de la taula dept
SQL> DESC dept
Nombre ┐Nulo? Tipo
----------------------------------------- -------- -----------------
DEPT_NUM NOT NULL NUMBER(2)
DEPT_NOM VARCHAR2(14)
DEPT_LOC VARCHAR2(13)

En el resultat es pot veure:


Nulo? Indica si la columna ha de tenir dades; NOT NULL indica que la
columna ha de tenir dades.

8
Annex I. SGBD Oracle. Eines SQL*Plus

Tipo mostra el tipus de dades d’una columna.

3.6.2. Comandes d’edició

La sentència guardada al buffer es pot editar utilitzant un senzill editor de línies, que té
les següents comandes:
Comanda Descripció
A[PPEND] text Afegeix text al final de la línia actual.
C[HANGE]/vella/nova Canvia el text vella per nova a la línia actual.
C[HANGE].vella.nova
C[HANGE]/text/ Suprimeix text de la línia actual.
C[HANGE].text.
CL[EAR] BUFF[ER] Esborra totes les línies del buffer.
CL[EAR] SCR[EEN] Neteja la pantalla
DEL Esborra la línia actual
DEL n Esborra la línia n
DEL m n Esborra des de la línia m fins la n, ambdues
incloses
I[NPUT] Insereix un número indefinit de línies.
I[NPUT] text Insereix una línia que conté text
L[IST] Mostra totes les línies del buffer
L[IST] n Mostra una línia (la indicada per n)
L[IST] n Mostra un rang de línies: de m a n, ambdues
incloses
R[UN] Mostra i executa la sentència actual del buffer
/ Executa sense mostrar la sentència actual del buffer
n Mostra la línia n del buffer
n text Substitueix la línia n per text
0 text Insereix una línia abans de la línia 1

9
Annex I. SGBD Oracle. Eines SQL*Plus

A tenir en compte:
Si es prem [INTRO] abans d’acabar una comanda SQL*Plus demanarà un número de
línia.
El buffer SQL s’acaba introduint un dels caràcters de fi (punt i coma o /) o prement
[INTRO] dues vegades.
Exemples:
SQL> LIST
1 SELECT dept_nom
2* FROM dept

El símbol * de la línia 2 del buffer indica que la línia 2 és l’actual.


SQL> 1
1* SELECT dept_nom

Ara la línia actual és la 1.


SQL> A , dept_loc
1* SELECT dept_nom, dept_loc

S’ha afegit el text “, dept_loc” a la línia actual.


SQL> L
1 SELECT dept_nom, dept_loc
2* FROM dept

Mostrar el buffer.
SQL> L
1* SELECT * FROM empl

Mostrar el buffer.
SQL> C/empl/dept
1* SELECT * FROM dept

Canviar el nom de la taula.

3.6.3. Comandes de fitxer

Comanda Descripció
SAV[E] fitxer[.ext] Guarda el contingut actual del buffer SQL a un
[REP[LACE] APP[END]] fitxer. Es pot utilitzar APPEND per afegir a un
fitxer que ja existeix, o REPLACE per
sobreescriure un fitxer. L’extensió per defecte
del fitxer és .sql
GET fitxer[.ext] Carrega el contingut del fitxer nomFitxer al
buffer SQL.
STA[RT] fitxer[.ext] Executa un fitxer de comandes guardat
prèviament.
@nomFitxer Igual que START
ED[IT] Obre l’editor i guarda el contingut del buffer a
un fitxer anomenat afiedt.buf
ED[IT] [fitxer[.ext]] Obre l’editor per editar el contingut del fitxer
indicat

SPO[OL] Guarda els resultats de consulta a un fitxer.


[fitxer[.ext]|OFF|OUT] OFF tanca el fitxer de spool. OUT tanca el fitxer

10
Annex I. SGBD Oracle. Eines SQL*Plus

de spool i envia els resultats del fitxer a la


impressora del sistema.
EXIT Surt de SQL*Plus

Exemples:
SQL> L
1 SELECT empl_nom, empl_dir, empl_dept_num
2* FROM empl
SQL> SAVE laMevaConsulta
Creado file laMevaConsulta.sql

Guarda la sentència SQL del buffer al fitxer laMevaConsulta.sql


SQL> START laMevaConsulta

EMPL_NOM EMPL_DIR EMPL_DEPT_NUM


---------------- ---------- -------------
SANCHEZ 7902 20
ARROYO 7698 30
SALA 698 30
...
14 filas seleccionadas.

Executa les comandes del fitxer laMevaConsulta.sql. S’obté el mateix resultat amb
@laMevaConsulta
SQL> ED laMevaConsulta

Obre l’editor amb el contingut del fitxer de comandes indicat.


SQL> L
1 SELECT *
2* FROM dept
SQL> ED
Escrito file afiedt.buf

Crea el fitxer de buffer afiedt.buf i l’obre amb l’editor.

Exemple: obtenir un llistat de tot el que es fa amb SQL Plus


SQL> SPOOL fitxerSessio
SQL> ...
SQL> SPOOL OFF

Tot el que es mostri entre SPOOL i SPOOL OFF quedarà emmagatzemat al fitxer
fitxerSessio.

11
Annex I. SGBD Oracle. Eines SQL*Plus

3.6.4. Altres comandes

Exemple: executar comandes del sistema operatiu


SQL> HOST dir

Executa la comanda dir, pròpia de sistemes operatius de la família Windows.


Exemple: mostrar ajuda d’una paraula clau de SQL Plus
SQL> help run

RUN
---

Lists and executes the most recently executed SQL command or


PL/SQL block which is stored in the SQL buffer. The buffer has
no command history list and does not record SQL*Plus commands.

R[UN]

help index mostra l’índex de l’ajuda.

Hi ha moltes més comandes que es poden consultar als manuals oficials d’Oracle.

3.7. Paràmetres d’entorn

SQL*Plus torna i formata les dades retornades per la sentència SQL per mostrar-les a
l’usuari per pantalla. El format com ho mostra de tipus llistat tabulat. Les comandes de
SQL*Plus que permeten formatar la sortida no es guarden al buffer i són efectives fins
que es canvien o es tanca la sessió de treball. Algunes d’aquestes comandes
s’estableixen mitjançant els paràmetres d’entorn.
Cada paràmetre d’entorn es guarda com una variable global i té un valor per defecte. La
comanda SET defineix els valors de varies variables SQL*Plus, les quals es poden veure
amb la comanda SHO[W].
A continuació es mostra com es poden configurar aquestes variables i el seu significat:

Variable Descripció
SET LINESIZE n Fixar el nombre màxim de caràcters per línia a
n (per defecte és 80)
SET PAGESIZE n Fixar el nombre de línies de la sortida abans de
començar una nova pàgina (per defecte és 14).
SET HEADING {ON|OFF} Activa i desactiva les capçaleres de columna
SET NULL “text” Indica quin text es mostra quan hi ha nuls (per
defecte no apareix cap text)
SET FEEDBACK Defineix el número mínim de files recuperades
{n|ON|OFF} per una consulta perquè mostri el missatge “n
files seleccionades” (per defecte és 6 i
ON)
SET PAUSE {ON|OFF} Controla el scroll (paginat) de la pantalla; amb
ON es fa una pausa abans de cada pàgina;
prement INTRO s’obté la següent pàgina.

Hi ha molts més paràmetres que es poden consultar als manuals oficials d’Oracle.

12
Annex I. SGBD Oracle. Eines SQL*Plus

Per no haver de configurar a cada inici de sessió els paràmetres d’entorn, hi ha dos
fitxers que poden ajudar a configurar automàticament aquests valors. Són els fitxers
glogin.sql i login.sql.
glogin.sql
Quan es carrega SQL*Plus, busca el fitxer glogin.sql dins el directori
$ORACLE_HOME/sqlplus/admin. Si el troba, el llegeix i executa les comandes que
conté. Això permet guardar els paràmetres d’entorn (com per exemple linesize) per totes
les sessions SQL*PLUS.
login.sql
Desprès de llegir el fitxer glogin.sql, SQL*Plus, busca el fitxer login.sql dins el directori on
s’ha iniciat el programa i també dins el directori indicat per la variable d’entorn del
sistema operatiu SQLPATH.
Cal tenir en compte que la configuració del fitxer login.sql té preferència sobre glogin.sql.

Exemple: una línia del fitxer glogin.sql o login.sql pot ser:


set sqlprompt "&_user> "

El que fa en aquest cas és canviar el símbol del “prompt” fent que mostri el nom d’usuari
seguit de “>”.

3.8. Taula DUAL

La taula DUAL és una taula creada automàticament per Oracle i és molt útil per fer consultes
amb constants.
La taula DUAL es troba a l’esquema de l’usuari SYS i és accessible per tots els usuaris.
Només té una columna, DUMMY, definida com a VARCHAR2(1), i conté una fila amb el
valor ’X’. Com que DUAL només té una fila, el valor constant és retornat només una
vegada. També es pot seleccionar una constant fent la selecció a qualsevol taula, però
en aquest cas el valor es retornarà tantes vegades com files tingui la taula.
Exemple:
SQL> SELECT 'hola, això és un exemple' AS MISSATGE
2 FROM dual;

MISSATGE
------------------------
hola, això és un exemple

Exemple:
SQL> SELECT 'hola, això és un exemple' AS MISSATGE
2 FROM dept;

MISSATGE
------------------------

Amb la taula dual també podem utilitzar funcions (que les veurem al següent apartat).
Exemple:
SQL> SELECT SYSDATE
2 FROM dual;

SYSDATE
--------
28/11/05

13
Annex I. SGBD Oracle. Eines SQL*Plus

14
Annex II. Dades de
treball
Dades de la base de dades de treball.
Annex II. Dades de treball Notes prèvies

Capítol 1. Simbologia
En aquest document s’utilitza una simbologia i formats específics per tal de simplificar-ne
la lectura i comprensió.
Quan es faci referència a la sintaxi d’alguna instrucció s’utilitzen els següents símbols:
[text], significa que el text és opcional.
|, significa alternativa.
Text amb lletra Courier New: tot el text que forma part de la sintaxi d’alguna instrucció.
Text amb negreta: paraules clau que formen sempre part de la instrucció.
Text amb lletra Courier New i fons gris: indica una instrucció SQL.

2
Capítol 2. Taules i dades d’exemple
En aquest document es mostren molts exemples de consultes sobre les següents taules:

DEPT
CAMP TIPUS RESTRICCIONS
dept_num number(2) primary key
dept_nom varchar2(14)
dept_loc varchar2(13)
EMPL
CAMP TIPUS RESTRICCIONS
empl_num number(4) primary key
empl_nom varchar2(16)
empl_ofici varchar2(10)
foreign key (a la taula
empl_dir number(4)
empl)
empl_datalt date
empl_salari number(11,2)
empl_comissio number(11,2)
MALALT foreign key (a la taula
empl_dept_num number(2)
CAMP TIPUS dept)
RESTRICCIONS
malalt_num number(5) primary key
malalt_nom varchar2(12)
malalt_adreca varchar2(20)
malalt_dnaixa date
malalt_sexe varchar2(1)
malalt_nss number(9)
HOSPITAL
CAMP TIPUS RESTRICCIONS
hospital_codi number(2) primary key
hospital_nom varchar2(12)
hospital_adreca varchar2(20)
hospital_telefon varchar2(8)
hospital_nllits number(4)
SALA
CAMP TIPUS RESTRICCIONS
sala_codi number(2) primary key
primary key, foreign
sala_hospital_codi number(2) key (a la taula
hospital)
sala_nom varchar2(20)
PLANTILLA
sala_nllits number(4)
CAMP TIPUS RESTRICCIONS
plantilla_empleat_num number(4) primary key
plantilla_hospital_codi number(2) foreign key (a la
plantilla_sala_codi number(2) taula sala)
plantilla_nom varchar2(16)
plantilla_funcio varchar2(10)
plantilla_torn varchar2(1)
plantilla_salari number(11,2)
DOCTOR
CAMP TIPUS RESTRICCIONS
doctor_codi number(3) primary key
foreign key (a la
doctor_hospital_codi number(2)
taula hospital)
doctor_nom varchar2(16)
doctor_especialitat varchar2(16)

You might also like