Les + du SQL de la 9i
Transcription
Les + du SQL de la 9i
Les + du SQL de la 9i
Ce document liste quelques nouvelles fonctionalités du SQL des versions 8i et 9i d'Oracle vues du coté
developpement.
Toutes les nouveautés ne sont pas abordées mais seulement celles dont le rapport efficacité/mise en oeuvre
semble le plus interessant.
Beaucoup de composant du SQL découlent de la prise en charge de la norme SQL 1999 et de ce fait certaines
expressions sont redondantes par rapport à des synthaxes qui existaient déjà.
Remarques :
Toutes les commandes listées dans ce document ont été testées.
Ce document a été crée avec la suite libre OpenOffice.
Sommaire
1 - Types de données ...............................................................................................................................................1
2 - Fonctions SQL (intéressantes)............................................................................................................................2
3 - DDL....................................................................................................................................................................4
4 - DSL (Select) .......................................................................................................................................................8
5 - DSL : Fonctions analytiques...............................................................................................................................9
6 - DML..................................................................................................................................................................13
1 - Types de données
Les types classiques sont maintenus avec des améliorations (varchar2 peut contenir jusqu'à 4000 octets).
Le type LONG ne devra plus être utilisé mais remplace par CLOB (jusqu'à 4G) pour contenir des données non
structurées du type texte word, image, video...
A noter que la plupart des fonctions de traitement de caractères ne fonctionnent pas sur les champs de type
LONG ou LOB. Il y a également d'autres restrictions qui conduisent à penser que ce type de champ devra être
utilisé seulement quand la limite de VARCHAR2 est atteinte.
De même LONG RAW est remplace par BLOB pour stocker du binaire.
BFILE sert a stocker un pointeur sur un fichier du serveur.
TIMESTAMP est une extension du type date comportant notament les fractions de secondes et la gestion des
fuseaux horaire (clause WITH TIME ZONE ).
Enfin la 8i a introduit la notion de type qui permet à chacun de créer ses propres types.
Nous ne parlerons pas ici de ces extentions objets utilisées principalement par les logiciels Oracle.
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
2 - Fonctions SQL (intéressantes)
Expression CASE
SELECT VILLE,CASE NOVILLE
WHEN 10 THEN 'AIX-EN-PROVENCE'
ELSE VILLE
END AS "APELLATION OFFICIELLE"
FROM HABITE
est équivalent à :
select ville, decode(noville,10,'Aix-en-Provence',ville) "Apellation officielle" from
habite
mais c'est plus clair...
La clause WHEN peut être suivie d'un prédicat et cette synthaxe apporte plus :
SELECT ENAME,CASE
WHEN ENAME LIKE 'J%' THEN 'SDF'
ELSE (SELECT VILLE FROM HABITE A WHERE
END AS "DOMICILE"
FROM EMP B
B.NOVILLE = A.NOVILLE)
bien sûr cette requête est équivalente à :
SELECT ENAME, NVL(VILLE,'SDF') "DOMICILE" FROM EMP NATURAL LEFT JOIN HABITE
Autre exemple :
SELECT SAL, CASE WHEN
WHEN
WHEN
ELSE
END
FROM EMP
SAL < 2000 THEN 'PAUVRE'
SAL < 3000 THEN 'MOYEN'
SAL < 4000 THEN 'RICHE'
'BILL'
NULLIF : exemple
SQL> set null 'GROS NUL'
SQL> SELECT NULLIF('A EST EGAL A B','A ET B') FROM DUAL;
NULLIF('AESTEG
-------------A est egal a B
Le premier parametre de la fonction nullif n'est pas egal au second donc il est retourné.
SQL> SELECT NULLIF('A EST EGAL A B','A EST EGAL A B') FROM DUAL;
NULLIF('AESTEG
-------------GROS NUL
Les 2 parametres sont égaux, c'est null qui est retouné.
COALESCE = NVL
SELECT COALESCE(NULL,'BIEN NUL')
FROM DUAL;
COALESCE
-------BIEN NUL
(compatibilité norme SQL)
NVL2
plus interessante que nvl qui n'avait que 2 arguments, NVL2 en a 3 mais retourne toujours du varchar2
EXEMPLE > SELECT NVL2(COMM,'RIEN','BEAUCOUP') FROM EMP;
NVL2(COM
-------beaucoup
Rien
Rien
beaucoup
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
current_date et current_timestamp,systimestamp
EXEMPLE > SELECT CURRENT_DATE FROM DUAL;
CURRENT_D
--------05-OCT-04
Exemple > select current_timestamp
from dual;
CURRENT_TIMESTAMP
--------------------------------------------------------------------------05-OCT-04 04.02.33.152885 PM +02:00
Exemple > select systimestamp from dual;
SYSTIMESTAMP
--------------------------------------------------------------------------05-OCT-04 04.52.00.443615 PM +02:00
extract
Cette fonction permet de remplacer la fonction to_char mais avec une synthaxe plus facile.
EXEMPLE > SELECT EXTRACT(MONTH FROM SYSDATE) FROM DUAL;
EXTRACT(MONTHFROMSYSDATE)
------------------------10
Exemple > select extract(year from sysdate) from dual;
EXTRACT(YEARFROMSYSDATE)
-----------------------2004
sys_context
Cette fonction remplace userenv et elle est beaucoup plus riche :
EXEMPLE > SELECT SYS_CONTEXT('USERENV','IP_ADDRESS') "@IP"
FROM DUAL;
@ip
10.1.100.32
Exemple > select sys_context('USERENV','LANG') Language
from dual;
LANGUAGE
US
select sys_context('USERENV','DB_NAME') "Nom de la base" from dual;
Nom de la base
devde
Exemple > select sys_context('USERENV','HOST') "Client" from dual;
Client
cmenaldo.dsi-hd13
Exemple > select sys_context('USERENV','OS_USER') "OS_USER" from dual;
OS_USER
cmenaldo
Plein d'autres arguments sont acceptés en paramêtre. Voir la doc.
Trim
Combinaison de RTRIM et LTRIM
SELECT TRIM('
LIBELLE
')
AS LIB FROM DUAL;
LIB
------libelle
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
Ou nouvelle synthaxe :
SQL> select trim(leading '=' from '=============libelle==========')
as lib from dual;
LIB
----------------libelle==========
SQL> select trim(both '='
from '=============libelle==========')
as lib from dual;
LIB
------libelle
3 - DDL
Colonnes
Renomage d'une colonne :
ALTER TABLE HABITE RENAME COLUMN NOVILLE
TO NVILLE;
Cet ordre a pour conséquence d'invalider les triggers, procédures, fonctions... et autres vues portant sur la
colonne concernée. Cette remarque s'applque aussi pour la commande suivante.
Suppression d'une colonne :
ALTER TABLE HABITE2 DROP COLUMN MAJ;
Renommage d'une constrainte :
ALTER TABLE HABITE RENAME CONSTRAINT NO_VILLE TO PK_HABITE;
index explicite
Jusqu'à présent :
CREATE TABLE "CHM"."HABITE2"
(
"NOVILLE" NUMBER,
"VILLE" VARCHAR2(50),
"REGION" VARCHAR2(10),
CONSTRAINT "NO_VILLE2" PRIMARY KEY ("NOVILLE")
USING INDEX PK_HABITE2)
donnait :
CREATE TABLE "CHM"."HABITE2"
*
ERREUR a la ligne 1 :
ORA-01418: specified index does not exist
En enlevant le nom de l'index la commande devient valide mais l'index resultant de cette commande se nome
comme la contrainte.
CREATE TABLE "CHM"."HABITE2"
(
"NOVILLE" NUMBER,
"VILLE" VARCHAR2(50),
"REGION" VARCHAR2(10),
CONSTRAINT "NO_VILLE2" PRIMARY KEY ("NOVILLE")
USING INDEX (CREATE INDEX IDX_NOVILLE ON HABITE2(NOVILLE)))
Maintenant le nom de l'index et celui de la contrainte sont différents et de plus on peut utiliser la synthaxe
habituelle du create index pour appliquer les clauses comme tablespace, parallel...
autre exemple plus interessant :
CREATE TABLE "CHM"."HABITE2"
(
"NOVILLE" NUMBER,
"VILLE" VARCHAR2(50),
"REGION" VARCHAR2(10),
CONSTRAINT "NO_VILLE2" PRIMARY KEY ("NOVILLE")
USING INDEX (CREATE INDEX IDX_NOVILLE ON HABITE2(NOVILLE,REGION)));
La commande suivante permet de dropper l'index en même temps que la contrainte :
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
ALTER TABLE HABITE2 DROP CONSTRAINT NO_VILLE2 DROP INDEX;
Le drop peut être remplacé par KEEP alors l'index n'est pas supprimé.
Tables temporaires
Ce sont des tables qui ne vivent (au plus) que le temps d'une session. Elle sont vidées à la fin de chaque session
ou a chaque fin de transaction si la clause on commit preserve rows n'est pas spécifiée.
Une session concurente voit la table mais uniquement les lignes qu'elle a créée elle même.
Elle peuvent donc être tres utililes pour contenir des données propre à chaque sessions.
SQL> CREATE GLOBAL TEMPORARY TABLE TEMPO
2 ON COMMIT PRESERVE ROWS
3 AS SELECT ENAME FROM EMP;
Table created.
SQL>
SQL> select count(*) from tempo;
COUNT(*)
---------14
SQL> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
SQL> connect chm/chm@devde
Connected.
SQL> /
COUNT(*)
---------0
IOT : tables organisées en index
Cette nouvelle fonctionalité permet d'économiser la place d'un index quand celui-ci par exemple s'appuie sur
toutes les colonnes de la table. Cette fonctionalité a été présentée par Oracle comme améliorant les temps
d'accés. Les tests que j'ai pu faire ainsi que quelques discussions sur le net tendent à prouver le contraire.
De plus il n'y a aucun apport fonctionnel.
Contrainte : il faut que la table ait une clé primaire.
SQL> set timing on
SQL> CREATE TABLE IOT (INSTANCE , UTIL_OS, NBTOT ,PRIMARY KEY (INSTANCE,UTIL_OS))
ORGANIZATION INDEX
AS (SELECT INSTANCE,UTIL_OS,SUM(NBRE) NBTOT FROM CONNEXIONS GROUP BY
INSTANCE,UTIL_OS) ;
Table created.
Elapsed: 00:00:00.30
SQL> create table non_iot (INSTANCE , UTIL_OS, NBTOT ,primary key (instance,util_os))
2 as (select instance,util_os,sum(nbre) nbtot from connexions group by
instance,util_os);
Table created.
Elapsed: 00:00:00.46
SQL> select count(*) from iot;
COUNT(*)
---------1334
Elapsed: 00:00:00.03
SQL> select count(*) from non_iot;
COUNT(*)
---------1334
Elapsed: 00:00:00.03
SQL> select count(*) from iot where instance='PRDUN' and util_os like 'cme%';
COUNT(*)
----------
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
1
Elapsed: 00:00:00.01
SQL> select count(*) from non_iot where instance='PRDUN' and util_os like 'cme%';
COUNT(*)
---------1
Elapsed: 00:00:00.01
SQL> select nbtot from iot where instance='PRDUN' and util_os like 'cme%';
NBTOT
---------770
Elapsed: 00:00:00.01
SQL> select nbtot from non_iot where instance='PRDUN' and util_os like 'cme%';
NBTOT
---------770
Elapsed: 00:00:00.01
Tables externes
On peut désormais déclarer une tables « externe » c'est à dire un fichier qui est sur le serveur sur lequel tourne la
base. Pour mémoire le package PL/SQL UTL_FILE permet lui aussi le traitement des fichiers (lecture+écriture).
La synthaxe de declaration est analogue à celle de SQL*Loader et seule la lecture est permise sur ces tables.
Exemple :
Creation du fichier (sur le serveur) :
cd /tmp
cat >tabext
7369,SMITH,CLERK,20
7499,ALLEN,SALESMAN,30
7521,WARD,SALESMAN,30
7566,JONES,MANAGER,20
7654,MARTIN,SALESMAN,30
Déclaration de la « directory » et des droits (effectué par l'administrateur ) :
SQL> CREATE OR REPLACE DIRECTORY ext AS '/tmp';
Directory created.
GRANT READ ON DIRECTORY ext TO scott;
GRANT WRITE ON DIRECTORY ext TO scott;
(Malgré ce privilège, la table extene ne sera utilisable qu'en lecture.)
Creation de la table externe (par l'utilisateur) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14*
CREATE TABLE EXT_TAB (
EMPNO CHAR(4),
ENAME CHAR(20),
JOB CHAR(20),
DEPTNO CHAR(2))
ORGANIZATION EXTERNAL
(TYPE ORACLE_LOADER
DEFAULT DIRECTORY EXT
ACCESS PARAMETERS
(FIELDS TERMINATED BY ','
MISSING FIELD VALUES ARE NULL
(EMPNO, ENAME, JOB, DEPTNO))
LOCATION ('TABEXT')
)
Table created.
SQL> select TABLE_NAME, DEFAULT_DIRECTORY_NAME
from user_external_tables;
TABLE_NAME
DEFAULT_DIRECTORY_NAME
------------------------------ -----------------------------EXT_TAB
EXT
SQL> select ename from ext_tab;
ENAME
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
-------------------SMITH
ALLEN
WARD
JONES
MARTIN
SQL> desc ext_tab;
Name
Null?
----------------------------------------- -------EMPNO
ENAME
JOB
DEPTNO
Type
---------------------------CHAR(4)
CHAR(20)
CHAR(20)
CHAR(2)
SQL> update ext_tab set deptno=null;
update ext_tab set deptno=null
*
ERROR at line 1:
ORA-30657: operation not supported on external organized table
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
4 - DSL (Select)
Sous-interrogation scalaire
Integration d'une requête à la place d'un champ.
La commande suivante
SELECT DNAME DEPARTEMENT,
(SELECT COUNT(*)
FROM EMP
FROM DEPT D;
E WHERE E.DEPTNO=D.DEPTNO) AS "NOMBRE D'EMPLOYES"
est équivalente à :
select dname as departement, nvl(nb,0) as "Nombre d'employes"
from dept d, (select deptno, count(*) nb from emp group by deptno) e
where e.deptno(+)=d.deptno;
Nouvelle synthaxe du select : clause JOIN
Produit cartésien (à utiliser avec modération !) :
select * from emp,dept
devient :
SELECT * FROM EMP CROSS JOIN DEPT
Equijointure
select a.deptno,a.ename from emp a,dept b where a.deptno = b.deptno
devient :
SELECT DEPTNO,ENAME FROM EMP
JOIN DEPT USING (DEPTNO)
Contrainte : les 2 tables ont en commun le même nom de champ
autre exemple :
select deptno,ename from emp
join dept using (deptno) where deptno = 10
remplace :
SELECT A.DEPTNO,A.ENAME FROM EMP A,DEPT B WHERE A.DEPTNO = B.DEPTNO AND A.DEPTNO = 10
Nouvelle synthaxe : clause ON
Elle sépare les prédicats de jointure des autres :
SELECT A.DEPTNO,A.ENAME
FROM EMP A JOIN DEPT B ON A.DEPTNO = B.DEPTNO
WHERE A.DEPTNO = 10
Cette requête est equivalente à la précédente mais plus lisible.
La synthaxe peut paraître équivalente à celle de la clause USING. La différence est que la il y a prédicat (donc
présence d'un opérateur) alors qu'avec USING on mentionne seulement le nom de la colonne.
Ce type de synthaxe s'étend à plusieurs tables :
Préparation :
create table habite (noville number, ville varchar2(50));
alter table emp add (noville number);
insert into habite values (10 , 'AIX')
insert into habite values (20 , 'Marseille')
insert into habite values (30 , 'La Ciotat')
update emp set noville = mod(rownum*10,30)+10
commit;
requête :
SELECT DEPTNO,ENAME,VILLE FROM EMP
(NOVILLE)
JOIN DEPT USING (DEPTNO)
JOIN HABITE USING
Jointures naturelles :
SELECT DNAME
,ENAME,
VILLE FROM EMP NATURAL JOIN DEPT NATURAL JOIN HABITE
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
La conditionn nécéssaire est que les noms de colonnes sur lesquels reposent les jointures soient les identiques et
de même type.
Jointures externes :
update emp set noville = null where ename like 'J%'
Jones et James n'ont plus de noville.
Avec la requête suivante ils apparaissent quand même :
SELECT ENAME, DNAME , VILLE FROM EMP NATURAL JOIN DEPT NATURAL LEFT JOIN HABITE ORDER
BY 1
Ainsi les mot-clés left, right et full remplacent les (+) qui étaient fastidieux à positionner.
insert into habite values (40,'Aubagne')
SELECT ENAME, VILLE FROM EMP NATURAL RIGHT JOIN HABITE ORDER BY 1
ramène la ligne « Aubagne » mais pas « Jones » ni « James »
SELECT ENAME, VILLE FROM EMP
NATURAL FULL JOIN HABITE ORDER BY 1
ramène toutes les lignes des 2 tables.
Clause WITH
Elle permet de n'executer qu'une seule fois une sous-requête dans une interrogation :
exemple :
Pour trouver dans le mois le jour ou il y a le plus et le moins de connexions :
WITH SOMME AS (SELECT TO_CHAR(DATE_CONN,'DD') JOUR , SUM(NBRE) NOMBRE
FROM CONNEXIONS GROUP BY TO_CHAR(DATE_CONN,'DD'))
SELECT 'MINI ',JOUR
,A.NB
FROM (SELECT MIN(NOMBRE) NB FROM SOMME) A ,SOMME B
WHERE A.NB = B.NOMBRE
UNION
SELECT 'MOYENNE PAR JOUR','DU MOIS ' , ROUND(AVG(NOMBRE))
FROM SOMME
UNION
SELECT 'MAX',JOUR ,A.NB
FROM (SELECT MAX(NOMBRE) NB FROM SOMME) A ,SOMME B
WHERE A.NB = B.NOMBRE
avant la 9i , qu'aurais-je écrit et surtout comment cela ce serait-il passé au niveau de l'optimiseur ?
Insert multitable
Permet d'inserer des lignes dans différentes tables à partir d'une requête. Bien sur cet ordre ne gère pas les
doubles sur la clé primaire.
préparation :
create table utilHD13 as select util_os,resolution_ip from connexions where 1 =2
create table util_hors_HD13 as select util_os,resolution_ip from connexions where 1 =2
INSERT WHEN INSTR(RESOLUTION_IP,'HD13') <> 0 THEN INTO UTILHD13
ELSE INTO UTIL_HORS_HD13
SELECT UTIL_OS,RESOLUTION_IP FROM CONNEXIONS WHERE ROWNUM < 1000
Ici on insère dans 2 tables différentes suivant que la colonne RESOLUTION_IP contient ou non 'hd13'.
On peut indiquer à la place du else une autre condition.
Cet ordre semble interessant pour créer plusieurs tables simultanéement en ne faisant qu'une lecture de la table
d'origine. Celle-ci peut d'ailleurs être une table externe. Par contre il faudra faire attention aux contraintes des
tables cibles et notament celles de clé primaires.
5 - DSL : Fonctions analytiques
Un certain nombre de fonctions statistiques sont aparues en 8i et 9i pour completer celles qui existaient déjà.
Elles ont pour but d'offrir de meilleures performances aux outils décisionnels d'Oracle mais peuvent aussi être
utilisées par le sqlman moyen. Nous verrons ici que les plus simples...
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
WITH_BUCKET
permet d'affecter un intervalle auquel le resultat d'une expression d'entrée est affectée apres son evaluation
Soit la table connexions (pres de 20000 lignes)
SQL> desc connexions
Name
Null?
----------------------------------------- -------DATE_CONN
INSTANCE
UTIL_OS
RESOLUTION_IP
PROGRAMME
NBRE
Type
---------------------------DATE
VARCHAR2(12)
VARCHAR2(50)
VARCHAR2(50)
VARCHAR2(100)
NUMBER
SELECT INSTANCE, SUM(NBRE) NB, WIDTH_BUCKET (SUM(NBRE),1000,20000,5) INTER FROM
CONNEXIONS GROUP BY INSTANCE;
Résultat:
INSTANCE
NB
INTER
------------ ---------- ---------DEVUN
9475
3
FORTR
1150
1
INFUN
13823
4
PPRDE
3922
1
PPRQU
795
0
PPRTR
909
0
PPRUN
858
0
PRDUN
16547
5
PROCI
22981
6
PROQU
14453
4
PROTR
22036
6
INSTANCE
NB
INTER
------------ ---------- ---------TESQU
553
0
TESUN
5951
2
WWWUN
1697
1
14 rows selected.
Cette fonction permet d'affecter un poids à chaque ligne :
Le premier caractère indique le champs sur lequel s'applique la fonction, puis la limite inférieure, la limite
supérieure et le nombre de «tranches».
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
Regroupement d'ensemble
En une seule requête, il est possible de faire plus et plus performant qu'avec la clause group by.
Ex : clause group by simple
SQL> select instance,util_os,programme,sum(nbre)from connexions where nbre >100
by instance,util_os,programme;
INSTANCE
-----------DEVUN
...
INFUN
PRDUN
PROCI
PROCI
...
PROCI
PROCI
PROQU
TESUN
TESUN
TESUN
group
UTIL_OS
PROGRAMME
SUM(NBRE)
------------------ ------------------ ---------SYSTEM
php.exe
1593
intranet
CRAVIN
VATEND
MBALLY
NFIGORITO
LIEGBIGO
intranet
GAT1
ZOWNIAKO
ZOWNIAKO
lims.exe
spdinstr.exe
spdinstr.exe
spdinstr.exe
spdinstr.exe
ifrun60.exe
ifcmp60.exe
rwcon60.exe
9788
240
431
369
108
134
6032
359
217
616
21 rows selected.
Clause group by rollup : permet d'avoir les sous-totaux dans une clause group by pour chaque niveau de rupture
ainsi qu'un total général. Cela est donc pratique pour generer des tableaux avec total par ligne et par colonne.
SQL>
SQL>
2
3
set NULL "Total ==>"
select instance,util_os,programme,sum(nbre)from connexions where nbre >100
group by rollup (instance,util_os,programme)
/
INSTANCE
-----------DEVUN
DEVUN
DEVUN
DEVUN
DEVUN
DEVUN
DEVUN
...
TESUN
TESUN
TESUN
Total ==>
UTIL_OS
-----------------SYSTEM
SYSTEM
JTIERS
JTIERS
TestNT4
TestNT4
Total ==>
PROGRAMME
SUM(NBRE)
------------------ ---------php.exe
1593
Total ==>
1593
vb.exe
101
Total ==>
101
apache.exe
164
Total ==>
164
Total ==>
1858
ZOWNIAKO
ZOWNIAKO
Total ==>
Total ==>
rwcon60.exe
Total ==>
Total ==>
Total ==>
616
833
1192
22149
48 rows selected.
Note : ici on ne fait pas de différence entre la valeur nulle située dans les données et celle renvoyée par la
clause ROLLUP. Il existe la fonction GROUPING qui permet de faire cette différence.Elle renvoie la valeur 1 si
le null est le résultat de la fonction.
Ainsi la requête aurrait pu s'écrire :
SELECT DECODE(GROUPING(INSTANCE),1,'TOTAL INSTANCE',INSTANCE) INSTANCE,
DECODE(GROUPING(UTIL_OS),1,'TOTAL USER',UTIL_OS) UTILISATEUR,
DECODE(GROUPING(PROGRAMME),1,'TOTAL PRG',PROGRAMME) PRG,
SUM(NBRE)
FROM CONNEXIONS WHERE NBRE >100
GROUP BY ROLLUP (INSTANCE,UTIL_OS,PROGRAMME)
...
TESUN
TESUN
GAT1
ZOWNIAKO
Total prg
ifcmp60.exe
INSTANCE
-------------TESUN
TESUN
TESUN
Total instance
UTILISATEUR
-----------------ZOWNIAKO
ZOWNIAKO
Total User
Total User
PRG
SUM(NBRE)
------------------ ---------rwcon60.exe
616
Total prg
833
Total prg
1192
Total prg
22149
359
217
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
48 rows selected.
Group by CUBE :
Cette clause permet de calculer tous les sous-totaux pour chaque combinaison possible de colonne :
SQL> select instance,util_os,programme,sum(nbre)from connexions where nbre >100
2 group by cube (instance,util_os,programme)
3 /
INSTANCE
-----------Total ==>
...
Total ==>
Total ==>
UTIL_OS
PROGRAMME
SUM(NBRE)
------------------ ------------------ ---------Total ==>
Total ==>
22149
Total ==>
Total ==>
rwcon60.exe
spdinstr.exe
INSTANCE
-----------Total ==>
Total ==>
...
DEVUN
DEVUN
UTIL_OS
-----------------GAT1
GAT1
PROGRAMME
SUM(NBRE)
------------------ ---------Total ==>
359
ifrun60.exe
359
Total ==>
SYSTEM
apache.exe
Total ==>
616
2786
164
1593
INSTANCE
UTIL_OS
PROGRAMME
SUM(NBRE)
------------ ------------------ ------------------ ---------DEVUN
SYSTEM
php.exe
1593
...
INSTANCE
-----------TESUN
TESUN
TESUN
TESUN
TESUN
TESUN
TESUN
TESUN
TESUN
UTIL_OS
-----------------Total ==>
Total ==>
Total ==>
Total ==>
GAT1
GAT1
ZOWNIAKO
ZOWNIAKO
ZOWNIAKO
PROGRAMME
SUM(NBRE)
------------------ ---------Total ==>
1192
ifcmp60.exe
217
ifrun60.exe
359
rwcon60.exe
616
Total ==>
359
ifrun60.exe
359
Total ==>
833
ifcmp60.exe
217
rwcon60.exe
616
108 rows selected.
La nouvelle clause GROUPING SET permet d'identifier que les groupes interessants :
SQL> select instance,util_os,programme,sum(nbre)from connexions where nbre >100
2 group by grouping sets (instance,util_os,programme);
INSTANCE
-----------DEVUN
...
TESUN
Total ==>
...
Total ==>
Total ==>
Total ==>
...
Total ==>
Total ==>
UTIL_OS
PROGRAMME
SUM(NBRE)
------------------ ------------------ ---------Total ==>
Total ==>
1858
Total ==>
ZOWNIAKO
Total ==>
Total ==>
1192
833
Total ==>
Total ==>
Total ==>
apache.exe
ifcmp60.exe
15820
164
217
Total ==>
Total ==>
spdinstr.exe
vb.exe
2786
101
35 rows selected.
Ou encore :
SQL> select instance,util_os,programme,sum(nbre)from connexions where nbre >100
2
group by grouping sets (instance,util_os,programme)
3
, (util_os,programme);
INSTANCE
-----------TESUN
PROCI
PROCI
...
PROCI
UTIL_OS
-----------------GAT1
VATEND
MBALLY
LIEGBIGO
PROGRAMME
SUM(NBRE)
------------------ ---------ifrun60.exe
359
spdinstr.exe
431
spdinstr.exe
369
spdinstr.exe
134
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
Total ==>
GAT1
...
Total ==>
Total ==>
NFIGORITO
LIEGBIGO
ifrun60.exe
359
spdinstr.exe
spdinstr.exe
108
134
61 rows selected.
Les différentes clauses peuvent être combinées entre elles :
SQL>
1
2
3
4*
SQL>
l
select instance,util_os,programme,sum(nbre)from connexions where nbre >100
group by instance,
cube (util_os),
rollup(programme)
/
INSTANCE
-----------DEVUN
DEVUN
DEVUN
INFUN
INFUN
PRDUN
PROCI
...
PROCI
PROQU
TESUN
TESUN
TESUN
DEVUN
...
DEVUN
INFUN
INFUN
PRDUN
PROCI
PROQU
TESUN
TESUN
TESUN
DEVUN
...
DEVUN
INFUN
INFUN
INFUN
PRDUN
PRDUN
PROCI
...
PROCI
PROCI
PROQU
PROQU
INSTANCE
-----------TESUN
TESUN
TESUN
UTIL_OS
PROGRAMME
SUM(NBRE)
------------------ ------------------ ---------JTIERS
vb.exe
101
SYSTEM
php.exe
1593
TestNT4
apache.exe
164
intranet
9788
SAISIE2
pel.exe
253
CRAVIN
lims.exe
240
VATEND
spdinstr.exe
431
LIEGBIGO
intranet
ZOWNIAKO
GAT1
ZOWNIAKO
Total ==>
spdinstr.exe
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
SYSTEM
apache.exe
ifcmp60.exe
ifrun60.exe
rwcon60.exe
vb.exe
pel.exe
lims.exe
spdinstr.exe
ifcmp60.exe
ifrun60.exe
rwcon60.exe
Total ==>
134
6032
217
359
616
101
164
9788
253
240
2786
6032
217
359
616
1593
Total ==>
SAISIE2
intranet
Total ==>
CRAVIN
Total ==>
VATEND
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
1858
253
9788
10041
240
240
431
LIEGBIGO
Total ==>
intranet
Total ==>
Total ==>
Total ==>
Total ==>
Total ==>
134
2786
6032
6032
UTIL_OS
-----------------GAT1
ZOWNIAKO
Total ==>
PROGRAMME
SUM(NBRE)
------------------ ---------Total ==>
359
Total ==>
833
Total ==>
1192
58 rows selected.
De nombreuses autres fonctions analytiques existent dans Oracle mais elles s'adressent à des spécialistes.
6 - DML
Mot clé « DEFAULT » dans Update.
alter table habite add (region varchar2(10) default 'Paca')
UPDATE HABITE SET REGION = DEFAULT
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques
MERGE
Permet de faire de la mise à jour de table ou de la création avec un seul ordre SQL...à essayer !
Preparation :
alter table habite add (constraint no_ville primary key ( noville))
create table habite2 as select * from habite where noville < 30
alter table habite2 add (constraint no_ville2 primary key ( noville));
alter table habite add (maj varchar2(3) default 'Ok')
Ordre :
MERGE INTO HABITE2 A USING HABITE B ON ( A.NOVILLE = B.NOVILLE)
WHEN MATCHED THEN UPDATE SET A.VILLE = B.VILLE
WHEN NOT MATCHED THEN INSERT (A.NOVILLE,A.VILLE,A.REGION ) VALUES
(B.NOVILLE,B.VILLE,B.REGION);
Contraintes :
Les 2 tables doivent avoir une clé primaire sur la colonne utilisée dans la clause ON.
Les 2 clauses WHEN sont obligatoires.
Pour chaque ligne de la table HABITE la ligne correspondante est recherchée sur HABITE2 via la clause on.
En fonction de la correspondance l'une des clauses when est executée.
La table HABITE peut être une table externe.
Pour plus de précisions, voir la doc Oracle9i SQL
DSIT/SASE/DBA - Les + de la 9i – Chme Nov 2004 – version 1.0.a.0.1 page Numéro de page/Statistiques