Exécuter des ordres PL/SQL dynamiquement ?
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,
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 à :
Code:
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 ; |
avec :
définition de la table Pl/SQL d'association :
Code:
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 ; |
procédure d'initialisation du tableau :
Code:
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 ; |
et extrait de procédure d'intégration :
Code:
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 |
Vous pouvez les voir les différents essais que j'ai fais en SQL dynamique, mais aucun de fonctionne....
Donc si quelqu'un à une idée....
..je suis preneur.
En vous remerciant d'avance.