Bonjour,

Nous avons activé l'audit trail Oracle sur une base de données.

Nous souhaitons à partir de la colonne SQLTEXT de la table SYS.AUD$ qui contient les query des utilisateurs, extraire pour chaque requête le nom des db_link utilisaient.

J'avais créé la fonction ci-dessous qui fonctionnait correctement dans mon environnement de TEST.
Seulement on est en train de réaliser un POC et la procédure d'extraction est tombée sur une requête d'un utilisateur qui fait 9000 caractères.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
CREATE OR REPLACE FUNCTION SYS.F_CHU_GET_DB_LINK_NAME (v_query IN VARCHAR2, v_username IN VARCHAR2) RETURN VARCHAR2 IS
    -- Variable pour la query en VARCHAR2
    v_query_char    VARCHAR2(32000);
    -- Variable INDEX pour parcourir la requete
    j_num           NUMBER;
    i_num           NUMBER;
    -- Variable pour formatter le retour liste des db_link
    v_db_link_name  VARCHAR2(500);
    v_db_link_lst   VARCHAR2(500);
    -- Pour compter si db_link existe
    v_count         INTEGER;
    -- Variable requete SQL
    v_sql           VARCHAR2(2200);
BEGIN
    -- Venant d'un CLOB il est possible qu'il y ait des retour chariot, on les supprime
    v_query_char := replace(v_query,chr(10),'');
    -- Verification si un @ se trouve dans la requete
    IF UPPER(v_query_char) LIKE '%@%' THEN
        i_num:= 1;
        -- On separe avec le @
        FOR I IN (SELECT REGEXP_SUBSTR(UPPER(v_query_char),'(.*?)(@|$)', 1, LEVEL, NULL, 1 ) AS value FROM DUAL CONNECT BY LEVEL <= regexp_count(UPPER(v_query_char), '@')+1)
        LOOP
            -- On ne prend pas le premier qui est avant le premier @
            IF i_num <> 1 THEN
                j_num:= 1;
                -- On split avec un espace
                FOR J IN (SELECT REGEXP_SUBSTR(UPPER(i.value),'(.*?)([[:space:]]|$)', 1, LEVEL, NULL, 1 ) AS value FROM DUAL CONNECT BY LEVEL <= regexp_count(UPPER(i.value), '[[:space:]]')+1)
                LOOP
                    IF j_num = 1 THEN
                        -- On supprime les virgules
                        v_db_link_name := REPLACE (j.value, ',','');
 
                        -- Verification si la chaine recuperee correspond bien a un db_link qui existe dans la base courante
                        v_sql := 'SELECT COUNT(*) FROM DBA_DB_LINKS WHERE DB_LINK = :v_db_link_name AND OWNER IN (''PUBLIC'', :v_username)';
                        EXECUTE IMMEDIATE v_sql INTO v_count USING v_db_link_name,v_username;
 
                        -- SI v_count different de 0 c'est que le db_link existe dans la base source
                        IF( v_count != 0 ) THEN
                            v_db_link_lst := v_db_link_lst || v_db_link_name || ',';                      
                        END IF;
                    END IF;
                    j_num := j_num +1;
                END LOOP;
            END IF;
            i_num := i_num +1;
        END LOOP;
    ELSE
        -- Pas de @ dans le SQL_TEXT donc pas de db_link dans la requete
        v_db_link_lst := 'UNKNOWN';
    END IF;
 
    IF v_db_link_lst LIKE '%,' THEN
        -- Remove de la derniere virgule
        v_db_link_lst := SUBSTR(v_db_link_lst, 0, LENGTH(v_db_link_lst) - 1);
    ELSIF v_db_link_lst LIKE '' THEN
        v_db_link_lst := 'UNKNOWN';
    END IF;
 
    -- Retour de la variable
    return v_db_link_lst;
END;
/
J'obtiens cette erreur à l'exécution de cette fonction sur la requête volumineuse.
Rapport d'erreur -
ORA-01460: demande d'une conversion non implémentée ou irréaliste
01460. 00000 - "unimplemented or unreasonable conversion requested"
L'erreur est générée sur la première boucle FOR.

Pour le moment je n'arrive pas à trouver de solution à mon problème.
Surement que ma fonction n'est pas optimisé du tout ... (mais ça ce n'est pas très grave, dans ce cas il faut juste extraire les données pour les traiter ensuite sur un autre modèle de données).

Avez-vous une idée s'il vous plait ?

Merci d'avance pour votre aide,

Matt