Fonctions Analytiques ROW_NUMBER et DENSE_RANK

Les fonctions analytiques sont très puissantes et très utiles, elles permettent d’alléger les requêtes SQL d’une façon élégante et performante.
Une fonction que j’ai utilisée récemment est la fonction ROW_NUMBER, elle permette de donner un ordre numérique pour les lignes, la pseudo-colonne ROWNUM existe mais son utilisation nécessite l’écriture de plus d’instruction.
Voila un exemple qui illustre l’utilité de cette fonction ; supposons que vous voulez faire un ordre sur la colonne salaire de la table EMP du schéma SCOTT :   

SQL> select EMPNO,ENAME,SAL
  2  from scotty.emp order by SAL;
     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             800
      7900 JAMES             950
      7876 ADAMS            1100
      7521 WARD             1250
      7654 MARTIN           1250
      7934 MILLER           1300
      7844 TURNER           1500
      7499 ALLEN            1600
      7782 CLARK            2450
      7698 BLAKE            2850
      7566 JONES            2975
     EMPNO ENAME             SAL
---------- ---------- ----------
      7788 SCOTT            3000
      7902 FORD             3000
      7839 KING             5000
14 ligne(s) selectionnee(s).

Ajoutons une colonne pour le classement de ces lignes selon le salaire, si on utilise directement ROWNUM ça marcherai pas :
SQL> select EMPNO,ENAME,SAL, rownum classement from scotty.emp order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950         12       7876 ADAMS            1100         11       7521 WARD             1250          3       7654 MARTIN           1250          5       7934 MILLER           1300         14       7844 TURNER           1500         10       7499 ALLEN            1600          2       7782 CLARK            2450          7       7698 BLAKE            2850          6       7566 JONES            2975          4
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000          8       7902 FORD             3000         13       7839 KING             5000          9
14 ligne(s) selectionnee(s).

Certes il a classé les donner mais c’est donne l’ordre de l’extraction des lignes mais pas dans l’ordre des valeurs des salaires, pour corriger ça  il faut écrire :
SQL> select EMPNO,ENAME,SAL,rownum classement from 
 2 (select EMPNO,ENAME,SAL from scotty.emp order by SAL) ;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          5       7934 MILLER           1300          6       7844 TURNER           1500          7       7499 ALLEN            1600          8       7782 CLARK            2450          9       7698 BLAKE            2850         10       7566 JONES            2975         11
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         12       7902 FORD             3000         13       7839 KING             5000         14
14 ligne(s) selectionnee(s).

C’est la que devienne l’utilisation des fonctions analytiques intéressante,  voila le même résultat en utilisant ROW_NUMBER :
SQL> select EMPNO,ENAME,SAL, row_number() over(order by SAL) classement
  2  from scotty.emp
  3  order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          5       7934 MILLER           1300          6       7844 TURNER           1500          7       7499 ALLEN            1600          8       7782 CLARK            2450          9       7698 BLAKE            2850         10       7566 JONES            2975         11
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         12       7902 FORD             3000         13       7839 KING             5000         14
14 ligne(s) selectionnee(s).

Le résultat est bien trier selon les valeurs des salaires et il est classé mais il y a un problème sur les salaires égaux  (par exemple SCOTT et FORD) ont le même salaire mais un classement différent, la aussi c’est les fonctions analytiques qui viennent  au secours :
SQL>  select EMPNO,ENAME,SAL, DENSE_RANK() over(order by SAL) classement
  2  from scotty.emp
  3  order by SAL;
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7369 SMITH             800          1       7900 JAMES             950          2       7876 ADAMS            1100          3       7521 WARD             1250          4       7654 MARTIN           1250          4       7934 MILLER           1300          5       7844 TURNER           1500          6       7499 ALLEN            1600          7       7782 CLARK            2450          8       7698 BLAKE            2850          9       7566 JONES            2975         10
     EMPNO ENAME             SAL CLASSEMENT ---------- ---------- ---------- ----------       7788 SCOTT            3000         11       7902 FORD             3000         11       7839 KING             5000         12
14 ligne(s) selectionnee(s).

La fonction DENSE_RANK permet de donner le même classement pour les mêmes valeurs dans un résultat trié.
Chaque fois que vous écrivez des instructions SQL ou des blocs PL/SQL afin d’analyser les données, jeter un coup d’œil sur les fonctions analytiques vous pouvez y trouver un contournement.

WebSphere : JDWP error in VM_INIT: TransportException

J’ai reçu l’erreur suivant en essayant de redémarrer un serveur applicatif en Websphere .
L’erreur s’affiche dans SystemErr.log, dans SystemOut.log rien d’indicatif :

08:43:21.820 ERROR: [Agent.cpp:164] JDWP error in VM_INIT: TransportException [510/201] binding to port failed (error code: -212


En cherchant un peu cela vient de l’échec de Websphere d’obtenir le port renseigné dans  server.xml, en particulier celui de debug JVM  - c’est ce qui est indiqué par le code message JDWP – j’ai fait un grep sur la valeur debugArgs :

grep -i debugArgs ./config/cells/aix61devNode01Cell/nodes/aix61devNode01/servers/server1/server.xml
  < services xmi:type="debugservice:DebugService" xmi:id="DebugService_1319801562654" enable="true" jvmDebugPort="7777" jvmDebugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7777" BSFDebugPort="4444" BSFLoggingLevel="0"/ >
    < jvmEntries xmi:id="JavaVirtualMachine_1183122130078" verboseModeClass="false" verboseModeGarbageCollection="false" verboseModeJNI="false" runHProf="false" hprofArguments="" debugMode="true" debugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7777" genericJvmArguments="" >


Apparemment il cherche à allouer le port 7777 c’est le port par défaut pour le debugging JVM en Websphere , je fait un recherche sur le port voulu et effectivement il est déjà allouer par un autre serveur :
lsof -Pnl +M -i4 | grep 7777  

je modifie le fichier server.xml pour lui indiqué un autre port libre et voila que cela redémarre :

    < jvmEntries xmi:id="JavaVirtualMachine_1183122130078" verboseModeClass="false" verboseModeGarbageCollection="false" verboseModeJNI="false" runHProf="false" hprofArguments="" debugMode="true" debugArgs="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7788" genericJvmArguments="" >
      < systemProperties xmi:id="Property_1" name="com.ibm.security.jgss.debug" value="off" required="false"/ >

La modification peut aussi se faire au niveau console :

Un peu plus bas :

Souvenez-vous qu’en activant certains options sur WebSphere cela peut activer l’utilisation de certains ports qui ne sont pas forcement libres ou autorisé par le par-feu.

Le parametre DDL_LOCK_TIMEOUT

A partir de la version 11g d’oracle un nouveau paramètre permettant de contrôler le timeout sur l’instruction DDL qui sont en attente des verrous DML ; ce parametre est par défaut à zero qui est le comportement existant dans les version 10g et avant, il s’agit de  ddl_lock_timeout voila un cas expliquant sont comportement :
L’état de ce parametre avant modification :

SQL> show parameter ddl
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
ddl_lock_timeout                     integer     0
enable_ddl_logging                   boolean     FALSE

SQL>-- créons maintenant un table de test  et simulons une modification :

SQL> create table usr(name varchar2(10),tr number(4));
Table creee.
SQL> insert into usr values('polo',20);
1 ligne creee.
SQL> insert into usr values('folo',30);
1 ligne creee.
SQL> insert into usr values('solo',40);
1 ligne creee.
SQL> commit;
Validation effectuee.
SQL> --
SQL> update usr set name='lolo' where name='folo';
1 ligne mise a jour.

On ouvre une autre session et on simule une suppression de la table, la première tentative  renvoi le message d’erreur sur le champ :
[oracle@sysagvm ~]$ sqlplus "/as sysdba"
SQL*Plus: Release 11.2.0.1.0 Production on Mon Nov 7 04:58:18 2011
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
Connecte a : Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options
SQL> SQL> SQL> set tim on 04:58:31 SQL> drop table usr; drop table usr            * ERREUR a la ligne 1 : ORA-00054: ressource occupee et acquisition avec NOWAIT ou temporisation indique

On modifie le paramètre au niveau session à 10 secondes, et on réessaye cette fois en attend la période spécifier dans le paramètre avant qu’Oracle nous renvoi le message d’erreur :
04:58:32 SQL> alter session set ddl_lock_timeout=10;
Session modifiee.
04:58:40 SQL> 04:58:41 SQL> drop table usr; drop table usr            * ERREUR a la ligne 1 : ORA-00054: ressource occupee et acquisition avec NOWAIT ou temporisation indique
04:58:53 SQL>

La valeur maximale de ce paramètre est  1000000 secondes ce qui signifie une attente infinie.

Did not find JAVA_HOME under the WebSphere installer directory

Lors de l’installation du Websphere j’ai rencontré l’erreur suivante :

root@AIX53:/tmp/inst_ihs/IHS>./install

Did not find JAVA_HOME under the WebSphere installer directory.
Exiting

Cela vient du fait que l’installateur de Websphere ne trouve pas les binaires JAVA. Pour contourner ce problème il suffit juste de mettre un SDK compatible dans le répertoire parent du répertoire de l’installation dans mon cas : /tmp/inst_ihs/.

IHS : Installation IBM HTTP Server 7.0 sous AIX 5.3

L’installation est effectué sur un system AIX 5.3 64bits , pré requis pour cette installation sont les suivants :
Ø  Service Pack 5300-07-01 (recommandé mais pas nécessaire).
Ø  2Go de libre dans /tmp ou nous allons  extraire les archives d’installation.
Ø  700 Mo de libre dans le FS de l’installation.
Ø  Une version SDK compatible dans niveau supérieur du répertoire d’installation.
Ø  Les archives de l’Install.

On decompresses les archives :



root@AIX53:/tmp/inst_ihs> ls -l
total 836448
-rw-r--r--    1 root     system    173557760 Nov 22 09:20 JDk.tar
-rw-r--r--    1 root     system    181483520 Nov 22 09:52 ihs.tar
root@AIX53:/tmp/inst_ihs> tar –xvf  JDk.tar
root@AIX53:/tmp/inst_ihs> tar –xvf  ihs.tar
root@AIX53:/tmp/inst_ihs> ls -l
total 836448
dr-xr-xr-x   12 root     system         4096 Sep  1 2008  IHS
drwxr-xr-x    3 root     system          256 Sep  1 2008  JDK
-rw-r--r--    1 root     system    173557760 Nov 22 09:20 JDk.tar
-rw-r--r--    1 root     system    181483520 Nov 22 09:52 ihs.tar


Lancer un serveur X depuis le poste ou vous allez effectuer l’installation (Xming, Xmanager), et exporter l’affichage vers la machine en question :
root@AIX53:/tmp/inst_ihs> export DISPLAY=10.100.136.249 :0.0

Et en lance l’installation depuis :

root@AIX53:/tmp/inst_ihs/IHS> ./install
Voila les différentes étapes de l’installation :


L’avertissement concerne le patch recommandé :







Casser les mots de passe Oracle

Il existe plusieurs utilitaires pour casser les mots de passe Oracle ; un des plus rapides est woraauthbf téléchargeable sur le site Soonerorlater .
J’ai fait un petit test et ça fonctionne rapidement tant que le mot de passe ne depasse pas les six caractères, voila l’exemple que j’ai fait sur un poste avec un processeur Core2 Duo 3Ghz cela à donner une vitesse de 2,5 million de mot de passe par seconde :
SQL> create user user1 identified by PLM0RT;

Utilisateur cree.

SQL> select u.name||':'||u.password||':'||substr(u.spare4,3,63)||':'||d.name||':'||
      sys_context('USERENV','SERVER_HOST')||':'
      from sys.user$ u, sys.V_$DATABASE d where u.type#=1;
...
USER1:B033B534947A8CCF:F2A24D8B1AA518827F9721561BD9970492684425AACD4465B86C1AA646B3:DB11GR2:sysagvm:
...

On lance la session en specifiant le caracteset "alphanum" et le type de l'algoritme - ça depend selon la version de la base - 11g10g; pour les differents arguments et option consulter le fichier README.

C:\woraauthbf_0.22R2\woraauthbf_0.22R2\woraauthbf.exe -p C:\woraauthbf_0.22R2\woraauthbf_0.22R2\pfile.txt -c "alphanum" -t "11g10g"
Usernames will be permuted!
The number of processors: 2
Number of pwds to check: 2238976116
Number of pwds to check by thread: 1119488058
Password file: C:\woraauthbf_0.22R2\woraauthbf_0.22R2\pfile.txt, charset: alphanum, maximum length: 6, type: 11g10g
Could not open default.txt file! Deafult passwords will not be checked!
Start array thread with 1 number of passwords!
Start: 0 End: 1119488058
Start: 1119488058 End: 2238976116
Elpased time: 37s Checked passwords: 93950368 Speed: 2539199/s
Writing session files...
Writing session files...
Elpased time: 127s Checked passwords: 318483485 Speed: 2507743/s
Writing session files...
Elpased time: 235s Checked passwords: 588187535 Speed: 2502925/s
Writing session files...
Writing session files...
Elpased time: 333s Checked passwords: 832099138 Speed: 2498796/s
Writing session files...
Writing session files...
Writing session files...
Elpased time: 507s Checked passwords: 1262426203 Speed: 2489992/s
Writing session files...
Writing session files...
Elpased time: 657s Checked passwords: 1634275841 Speed: 2487482/s
Writing session files...
Writing session files...
Elpased time: 757s Checked passwords: 1885363683 Speed: 2490572/s
Writing session files...
Password found: USER1:PLM0RT:DB11GR2:sysagvm
Elpased time: 794s
Checked passwords: 1978225547
Password / Second: 2491467

Presque deux milliards de mots de passe essayer en 794 seconde ; si vous avez une machine avec plus de puissance CPU cela va minimiser le temps. Une version pour linux existe aussi.

ORA-01555 lors d'un Export - Corruption des données LOB

Aujourd’hui j’ai rencontré une erreur  un peu particulière  lors d’un export d’une base 8.1.7 , voila un extrait :

. . exporting table PLFRQRS

EXP-00056: ORACLE error 1555 encountered

ORA-01555: snapshot too old: rollback segment number with name "" too small

ORA-22924: snapshot too old


A première vue j’ai soupçonné les RBS de la base j’ai ajouté un grand Rollback Segment (2 Go) et j’ai réessayé l’export en surveillant l’état d’utilisation des segments d’annulation, mais bizarrement rien ne se passe après un certain temps la taille utilisée sur les segments reste la même. Et l’erreur est la même.

En vérifiant l’erreur je remarque que le message d’erreur ne comporte aucun nom du segment d’annulation !! . charchant un peu sur Metalink je trouve la note suivante:

Export Fails With ORA-2354 ORA-1555 ORA-22924 and How To Confirm LOB Segment Corruption Using Export Utility? [ID 833635.1]

Et effectivement il y a bien une corruption dans la table, en lançant les scripts suivants :


declare
error_1555 exception;
pragma exception_init(error_1555,-1555);
num number;
begin
for cursor_lob in (select rowid r, &&lob_column from &table_owner.&table_with_lob) loop
begin
num := dbms_lob.instr (cursor_lob.&&lob_column, hextoraw ('889911')) ;
exception
when error_1555 then
insert into corrupted_lob_data values (cursor_lob.r);
commit;
end;
end loop;
end;
/

Enter value for lob_column : PLFCLOB
Enter value for table_owner : PLF
Enter value for table_with_LOB: PLFRQRS

SQL> select * from corrupted_lob_data;

CORRUPTED_ROWID
--------------------------------
AAABBvAAIAAA39VAAE

J’ai pu faire l’export en supprimant la ligne, une mise à jour de la colonne aurait suffit mais dans mon cas j’ai déjà cette ligne sur une autre table.

SEC_SENSITIVE_LOGON dans Oracle 11g

Dans Oracle 11g les mots de passe utilisateurs sont par défaut sensibles à la casse sauf s'il s'agit d'une mise à niveau et cela tant qu'une instruction ALTER USER n'est pas utilisé ce qui restaure le comportement èar défaut, mais les noms utiliateurs ne sont pas concerné.
on peut desactiver la sensibilte à la casse on utilisant le nouveau parametere SEC_CASE_SENSITIVE_LOGON , par exemple :

SQL>alter system set SEC_SENSITIVE_LOGON = FALSE;

mais Oracle recommande de garder le comportement par défaut puisque la desactivation augmente les risques des attaques de type brute force contre les mots de passe non sensibles à la casse.

Oracle : Activer la trace du Listener

Parfois pour identifier un problème de connexion à la base de données on à besoin d'activer la trace de listener, pour cela on ajoute les lignes suivantes au fichier listtener.ora :

TRACE_DIRECTORY_LISTENER = C:\oracle\product\10.2.0\db_1\NETWORK\trace
TRACE_FILE_LISTENER = listener.trc
TRACE_LEVEL_LISTENER = support

Les deux premières lignes indique l'emplacement et e nom de fichier de trace, le troisième paramètre TRACE_LEVEL_LISTENER spécifie le niveau de trace, il y a quatre niveau de trace :
0 ou OFF est le niveau par défaut pas de trace.
4 ou USER est un niveau pour détecter les erreurs utilisateur.
6 ou ADMIN pour détecter des problèmes d'installation ou de configuration d'Oracle Net Services.
16 ou SUPPORT c'est le niveau le plus exhaustif il est destiné au support ORACLE.

On recharge le fichier avec :
c:\>lsnrctl reload

La sortie de fichier trace semble à quelque chose comme :
[31-JANV.-2010 17:56:04:500] nsopen: opening transport...
[31-JANV.-2010 17:56:04:500] nttcnp: getting sockname
[31-JANV.-2010 17:56:04:500] nttcnp: getting peername
[31-JANV.-2010 17:56:04:500] nttcnr: waiting to accept a connection.
[31-JANV.-2010 17:56:04:500] nttcnr: getting sockname
[31-JANV.-2010 17:56:04:500] snlinGetNameInfo: Using numeric form of host's address 127.0.0.1
[31-JANV.-2010 17:56:04:500] nttcnr: connected on ipaddr 127.0.0.1
[31-JANV.-2010 17:56:04:500] nttcon: set TCP_NODELAY on 228
[31-JANV.-2010 17:56:04:500] nsopen: transport is open
[31-JANV.-2010 17:56:04:500] nsnainit: inf->nsinfflg[0]: 0xd inf->nsinfflg[1]: 0xd
[31-JANV.-2010 17:56:04:500] nsopen: global context check-in (to slot 5) complete
[31-JANV.-2010 17:56:04:500] nsanswer: deferring connect attempt; at stage 5
[31-JANV.-2010 17:56:04:500] ntt2err: soc 228 error - operation=5, ntresnt[0]=524, ntresnt[1]=997, ntresnt[2]=0
[31-JANV.-2010 17:56:04:500] snttcallback: op = 5, bytes = 87, err = 0
......

la méthode de modification du fichier listener.ora n'est qu'une méthode parmi d'autres, on peut faire la même chose avec les commandes SET TRC_DIRECTORY, SET TRC_FILE, and SET TRC_LEVEL de l'utilitaire lsnrctl, ou à travers l'OEM.

SQL : Group BY ROLLUP

Une fonction bien pratique dans ORACLE depuis la version 9i est la fonction ROLLUP, cette fonction permet d'avoir des agrégations a certain niveaux que group by ne permet pas; analysons l'instruction suivante :
SQL> select deptno,job,sum(sal)
2 from emp group by deptno,job
3 order by deptno;

DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600

9 ligne(s) sélectionnée(s).
L'agrégation avec GROUP BY dans l'instruction précédente n'est utile que si on veut la somme en fonction des deux colonnes DEPTNO et JOB, si on veut aussi la somme en fonction de chaque DEPTNO nous auront deux choses soit faire une interrogation a part et la joindre avec un l'operateur UNION, soit utilisé la fonction ROLLUP :

SQL> select deptno,job,sum(sal)
2 from emp group by rollup(deptno,job)
3 order by deptno;

DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10
8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20
10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30
9400


29025

13 ligne(s) sélectionnée(s).

Remarquer aussi que la fonction ROLLUP permet de donner un total global de tous les départements, l'utilisation de ROLLUP est équivalent a group by() union group by deptno union group by deptno,job :

SQL> select deptno,job,sum(sal)
2 from emp group by deptno,job
3 union
4 select deptno,to_char(null),sum(sal)
5 from emp group by deptno
6 union
7 select to_number(null),to_char(null),sum(sal)
8 from emp;

DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10
8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20
10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30
9400


29025

13 ligne(s) sélectionnée(s).

Une autre fonction utile est la fonction CUBE.

DATA PUMP : Les paramétres REMAP_* dans

Une des fonctionnalités intéressantes de SQL loader c'est qu'il permet de charger des données à partir d'un schéma utilisateur vers un autre schéma utilisateur grâce aux paramètres fromuser et touser, mais avec DATA PUMP dans oracle 11g, c'est encore plus puissant avec les paramètres du genre REMAP_*.

Un équivalent de fromuser touser est le paramètre REMAP_SCHEMA, d'abord un export du schéma HR :

C:\>impdp system/sbd11 DIRECTORY=dpump_dir DUMPFILE=hr.dmp

Puis un import avec le paramètre REMAP_SCHEMA=hr:oe pour charger les objets du schéma HR vers le schéma Scott:

C:\>impdp system/sbd11 DIRECTORY=dpump_dir DUMPFILE=hr.dmp REMAP_SCHEMA=hr:scott

Autre fonctionnalité avec les paramètres de la famille REMAP est REMAP_DATA, et oui un mappage aux niveaux donnés; cela s'avère utile lors d'un chargement des données du prod vers une plateforme de test, voila un exemple :

C:\>expdp hr/hr tables=departments directory=dpump_DIR dumpfile=hrdept.dmp logfile=expdept.log
remap_data:departments.location:remap_pkg.map_loc
remap_data:departments.department_id:remap_pkg.map_id

L'exemple précédent montre un changement les valeurs de colonnes location et departement_id par des valeurs arbitraires (mais de même type!) retournées par des fonctions utilisateur.
Il y a aussi REMAP_TABLE, REMAP_DATAFILE ET REMAP_TABLESPACE

Oracle : Limter l'accés à la base avec le listener

Lorsque on veut limiter les machine à partir de laquelle on veut se connecter, généralement on deux choix soit en le fait avec un déclencheur sur l'événement DATABASE LOGON, soit en le fait au niveau listener est c'est plus simple à implémenter.
On ajoute les deux lignes suivantes dans le fichier sqlnet.ora :

tcp.validnode_checking=YES
tcp.invited_nodes= (hosta1,10.130.1.54,cronix,servpl)

La première ligne active la vérification de la source de connexion, la deuxième spécifie les machines à partir de quelles la connexion est autorisée, vous devez recharger le listener pour que ca prend effet :

C:\>lsnrctl reload

LSNRCTL for 32-bit Windows: Version 10.2.0.1.0 - Production on 31-JANV.-2010 16:43:13

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

Connexion à (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
La commande a réussi

Si vous essayez la connexion à partir d'une autre machine vous aurez le message suivant :
ERROR:
ORA-12537: TNS:connection closed

SQL : Foncion Cube

La fonction CUBE est comme sa petite sœur ROLLUP est une fonction d'agrégation qui permet d'avoir tout les combinaisons entre les composants d'une agrégation, un exemple :
SQL> select deptno,job,sum(sal)
2 from emp group by cube(deptno,job)
3 order by deptno;

DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10
8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20
10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30
9400

ANALYST 6000

CLERK 4150

MANAGER 8275

PRESIDENT 5000

SALESMAN 5600


29025

18 ligne(s) sélectionnée(s).

Le résultat montre quatre agrégations par les deux colonnes (deptno,job), par deptno seulement, par job seulement et le total dans toute la table ce que revient à faire mais avec quatre passages de la table emp alors que la précédente le fait dans un seule passage :
SQL> select deptno,job,sum(sal) from emp group by deptno,job
2 union
3 select to_number(null),job,sum(sal) from emp group by job
4 union
5 select deptno,to_char(null),sum (sal) from emp group by deptno
6 union
7 select to_number(null),to_char(null),sum(sal) from emp;

DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10
8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20
10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30
9400

ANALYST 6000

CLERK 4150

MANAGER 8275

PRESIDENT 5000

SALESMAN 5600


29025
18 ligne(s) sélectionnée(s).

Le nombre d'agrégation de CUBE est 2^nombre de colonnes dans le select, par contre avec ROLLUP on seulement n+1 ou n est le nombre de colonnes dans le select.