Bonjour,
je bute sur un petit problème :::
je vais essayer d'expliquer clairement mon problème et son contexte.
Je veux mettre à jour une table (de gestion) à partir des données d'une autre table (Temporaire réceptrice d'un flux).
Bien sur le nom des colonnes dans les deux tables ne sont pas systématiquement les mêmes, ni les tailles ....
Du coup, dans un package PL/SQL j'ai :
- une fonction qui me renvoie une table PL/SQL (T_Asso) de record avec :
- - le nom (T_Asso(Num_lign).Col_Membre) et la taille de colonne de table d'origine,
- - le nom et la taille de colonne de table de destination,
- - la différence de taille entre les deux colonnes (origine - destination)
- une procédure d'intégration qui :
- récupère la table PL/SQL de correspondance entre les colonnes des tables d'origine et de destination
- lit les valeurs de la table d'origine via un curseur
- et (je voudrais, mais je peux point ...) pour chaque ligne lue de la table d'origine,
Tronquer les valeurs trop longues à la taille de la colonne de la table de destination.
Voici le petit algo que j'ai imaginé pour détecter et tronquer les valeurs trop longues :
je lis le tableau de correspondance
pour chaque ligne lue,
- Si la différence de taille des colonnes d'origine et destination est positive, alors
Si la longueur (nombre de caractère) de la valeur d'origine est supérieure à la taille de la colonne d'origine et destination
Alors je tronque la valeur
Sinon touv a bien , je fais rien !
Là où je butte, c'est comment "sélectionner" la colonne du curseur (contenant les valeurs d'origine) en fonction de la ligne de ma table PL/SQL.
en gros arriver à exécuter un ordre PL/SQL semblable à :
avec :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 If length(trim(Rec_Membre_Courant.' || T_Asso(Num_lign).Col_Membre ||' )) > Table_Asso(Num_lign).Dim_P Then -- I2 Rec_Membre_Courant.' || T_Asso(Num_lign).Col_Membre ||' := Substr(trim(Rec_Membre_Courant. ' || T_Asso(Num_lign).Col_Membre ||') , 1, Table_Asso(Num_lign).Dim_P ) ; End If ;
définition de la table Pl/SQL d'association :
procédure d'initialisation du tableau :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 -- pour associer les colonnes de MEMBRE_TEMP à PERSONNE Type Asso_RecTYP Is Record (Col_Membre Varchar2(255), Col_Personne Varchar2(255) , dim_M Integer, dim_P Integer, diff_lng Integer) ; Type Table_Asso_TYP Is Table Of Asso_RecTYP Index By Binary_Integer ; -- Tableau de correspondance entre MEMBRE_TEMP à PERSONNE T_Asso Table_Asso_TYP ; -- Indice des lignes du tableau Table_Asso Num_lign integer ;
et extrait de procédure d'intégration :
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 Function genere_table_ASSO Return Table_Asso_TYP Is -- Tableau de correspondance entre MEMBRE_TEMP (origine) à PERSONNE (destination) Table_Asso Table_Asso_TYP ; -- Indice des lignes du tableau Table_Asso Num_lign integer ; Begin dbms_output.disable ; dbms_output.enable (50000000) ; -- Initialialisation coorespondance entre la table MEMBRE_TEMP et a tabe PERSONNE Table_Asso(2).Col_Membre := 'memcn_num' ; Table_Asso(2).Col_PERSONNE := 'memcn_num' ; Table_Asso(3).Col_Membre := 'matricule' ; Table_Asso(3).Col_PERSONNE := 'matricule' ; Table_Asso(6).Col_Membre := 'civilite' ; Table_Asso(6).Col_PERSONNE := 'sigle' ; Table_Asso(7).Col_Membre := 'nomusuel' ; Table_Asso(7).Col_PERSONNE := 'nomusuel' ; Table_Asso(8).Col_Membre := 'nom_patro' ; Table_Asso(8).Col_PERSONNE := 'nom_patro' ; Table_Asso(9).Col_Membre := 'prenom' ; Table_Asso(9).Col_PERSONNE := 'prenom' ; Table_Asso(10).Col_Membre := 'datnaiss' ; Table_Asso(10).Col_PERSONNE := 'datnaiss' ; Num_lign := Table_Asso.first ; While Num_lign <= Table_Asso.last Loop -- on récupère les tailles des colonnes via le dictionnaire de données Oracle Begin Select DATA_LENGTH Into Table_Asso(Num_lign).Dim_M From User_Tab_Columns Where TABLE_NAME = 'MEMBRE_TEMP' And COLUMN_NAME = UPPER(Table_Asso(Num_lign).Col_Membre) ; Select DATA_LENGTH Into Table_Asso(Num_lign).Dim_P From User_Tab_Columns Where TABLE_NAME = 'PERSONNE' And COLUMN_NAME = UPPER(Table_Asso(Num_lign).Col_PERSONNE) ; -- on calcule la différence de taille entre les colonnes d'origine et de destination Table_Asso(Num_lign).diff_lng := Table_Asso(Num_lign).Dim_M - Table_Asso(Num_lign).Dim_P ; Num_lign := Table_Asso.next(Num_lign) ; Exception When no_data_found Then dbms_output.put_line ('données non trouvées pour nb_ligne = ' || Num_lign ) ; Num_lign := Table_Asso.next(Num_lign) ; End ; End Loop ; /* -- pour tets unitaire seulement dbms_output.put_line ('Vérif. résulata final' ) ; Num_lign := Table_Asso.first ; While Num_lign <= Table_Asso.last Loop dbms_output.put_line ('ligne ' || Num_lign || ' ; MEMBRE.' || Table_Asso(Num_lign).Col_Membre || ' ' || Table_Asso(Num_lign).Dim_M || ' ; Personne.' || Table_Asso(Num_lign).Col_PERSONNE || ' ' || Table_Asso(Num_lign).Dim_P || ' ; diff de longueur ' || Table_Asso(Num_lign).diff_lng) ; Num_lign := Table_Asso.next(Num_lign) ; End Loop ; */ Return Table_Asso ; End genere_table_ASSO ;
Vous pouvez les voir les différents essais que j'ai fais en SQL dynamique, mais aucun de fonctionne....
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
63
64 Procedure Maj_Personne(Dat_Ref Date) Is --Pour stocker le numéro de personne à insérer v_Max_Personne Personne.Num_Personne%Type; -- Liste des personnes être importés Cursor Cur_Membres Is Select Distinct Me.* From Membre_Temp Me -- on ne prend en compte que les données du flux du jour Where Trunc(Met_Timestamp, 'dd') = Trunc(Dat_Ref, 'dd') ; --Ligne du curseur CUR_MEMBRE : représente un membre à importer Rec_Membre_Courant Cur_Membres%Rowtype; -- identifiant de la personne à mettre à jour Id_Personne Personne.Num_Personne%Type; -- Tableau de correspondance entre MEMBRE_TEMP à PERSONNE T_Asso Table_Asso_TYP ; -- Indice des lignes du tableau Table_Asso Num_lign integer ; Block_PL Varchar2(4000) ; val Varchar2(500) ; Lng Integer ; Begin -- Initialisation correspondance entre la table MEMBRE_TEMP (origine) et la table PERSONNE (destination) T_Asso := pck_import_ambre.genere_table_asso; --Parcours de la table MEMBRE_TEMP (origine) For Rec_Membre_Courant In Cur_Membres -- Boucle1 Loop -- parcours cur_membres Begin -- traitement des valeurs trop grande Num_lign := T_Asso.first ; While Num_lign <= T_Asso.last Loop If T_Asso(Num_lign).diff_lng > 0 Then -- I1 /* Block_PL := ' Begin If length(trim(Rec_Membre_Courant.' || T_Asso(Num_lign).Col_Membre ||' )) > Table_Asso(Num_lign).Dim_P Then -- I2 Rec_Membre_Courant.' || T_Asso(Num_lign).Col_Membre ||' := Substr(trim(Rec_Membre_Courant. ' || T_Asso(Num_lign).Col_Membre ||') , 1, Table_Asso(Num_lign).Dim_P ) ; End If ; --I2 END ; ' ; Execute Immediate Block_PL ; */ Block_pl := ' :Val := :Rec ; ' ; Execute Immediate Block_PL Using In Out VAL , 'Rec_Membre_Courant.' || T_Asso(Num_lign).Col_Membre ; lng := length (Trim (val)) ; End if ; --I1 Num_lign := T_Asso.next(Num_lign) ; End Loop ; -- traitement des enregistrements et MAJ de la table de destination ...... End; -- Bloc1 End Loop; -- parcours cur_membres -- boucle1 End Maj_Personne; -- BlocP
Donc si quelqu'un à une idée....
..je suis preneur.
En vous remerciant d'avance.
Partager