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.