2009-10-13 5 views
1

Je suis nouveau à Oracle PL/SQL et j'ai de la difficulté à conceptualiser les collections en ce qui concerne les enregistrements.Collections PLSQL - pour créer une collection d'enregistrements ou non?

J'ai le problème suivant: Je souhaite comparer différents champs d'un enregistrement de la table client aux différents champs d'un enregistrement de la table de personnes. par exemple, LName, FName, Soc. (Malheureusement, il n'y a pas d'identifiant pour lier facilement les deux).

Pour la table client, je prévois de créer un curseur et de le récupérer dans un enregistrement (et en boucle), puisque pour chaque enregistrement de la table client, je veux regarder tous les enregistrements de personne et voir s'il est un meilleur match. S'il y a 100 clients, il ne devrait pas y avoir plus de 100 correspondances.

C'est là où je ne suis pas sûr si je dois:

  • A) Utiliser une collection d'enregistrements pour la table personne ou
  • B) Utilisez une collection pour LName, une collection pour FName, une collection pour Soc.

Si j'utilise A, comment puis-je référencer une colonne spécifique dans l'enregistrement? C'est ainsi que je procédais avec le code, mais je me perds un peu.

Si j'utilise B, existe-t-il un moyen de vérifier que je compare des colonnes avec le même enregistrement? Par exemple, si je compare l'enregistrement client pour John Doe 111-222-3333, je veux m'assurer que si j'obtiens une correspondance qui provient d'un seul enregistrement, et non pas enregistrer 10 FName = John, enregistrer 200 LNAME = Doe, enregistrer 5000 Soc = 111-222-3333.

Réponses avec la syntaxe Oracle PL/SQL sont très appréciés, comme je suis encore à apprendre et seront trop facilement confondus par d'autres langues ... Voici le début de mon code ...

Merci!

DECLARE 
    CURSOR client_cur IS 
    SELECT id_client, nm_client_last, nm_client_first, nbr_client_ssn, 
     cd_client_gender, dt_client_birth 
    FROM client 
    WHERE yr_service_fiscal BETWEEN 2007 AND 2009 
ORDER BY nm_client_last, 
     nm_client_first, 
     nbr_client_ssn, 
     cd_client_gender, 
     dt_client_birth; 

    CURSOR person_cur IS 
    SELECT id_person, nm_person_last, nm_person_first, nbr_person_id_number, 
     cd_person_sex, dt_person_birth 
    FROM person 
    WHERE EXTRACT (YEAR FROM dt_last_update) >= 2007 
    AND nm_person_full != 'Employee,Conversion' 
ORDER BY nm_person_last, 
     nm_person_first, 
     nbr_person_id_number, 
     cd_person_sex, 
     dt_person_birth; 

-- Record for client and person data 
client_rec client_cur%ROWTYPE; 
person_rec person_cur%ROWTYPE;  

-- Record for client_match and person_match 
client_match_rec client_cur%ROWTYPE; 
person_match_rec person_cur%ROWTYPE; 

-- For person data collection- create "table of records" (index-by table type collection) 
TYPE person_t IS TABLE OF person_rec%ROWTYPE INDEX BY BINARY_INTEGER; 
person_tab person_t; 

-- For best client and person matches collections- create "table of records" (index-by table type collection) 
TYPE client_best_matches_t IS TABLE OF client_match_rec%ROWTYPE INDEX BY BINARY_INTEGER; 
client_matches_tab client_best_matches_t; 

TYPE person_best_matches_t IS TABLE OF person_match_rec%ROWTYPE INDEX BY BINARY_INTEGER; 
person_matches_tab person_best_matches_t; 


-- Variables 
v_match_score number DEFAULT 0 
v_temp_score number DEFAULT 0 
v_match_threshold number DEFAULT 0 

BEGIN 

-- Populate the person collection by processing the person cursor rows into the person records 
OPEN person_cur; 
LOOP 
    FETCH person_cur INTO person_rec; 
    EXIT WHEN person_cur%NOTFOUND; 
    person_tab (person_cur%ROWCOUNT) := person_rec; 
    END LOOP; 

-- Process the client cursor rows into the client records 
OPEN client_cur; 
LOOP 
    FETCH client_cur INTO client_rec; 
    EXIT WHEN client_cur%NOTFOUND; 

/* 
Inner loop compares one record in client to each record in person collection 
Save match score in v_temp_score 
Compare v_temp_score to v_match_score to see if this is the best match yet 
If so, save records in best_match_client and best_match_person and save match score in v_match_score 
*/ 
    IF person_tab IS NOT NULL 
    THEN 
    i := person_tab.FIRST; 
    WHILE (i IS NOT NULL) 
    LOOP 
     (case when client_cur.nbr_client_ssn = person_tab.--HOW TO REFERENCE PERSON_TAB.SSN? 
     then) 

     i:= person_tab.NEXT (i); 
     END LOOP; 
    END IF; 

/* 
If a match exists, add it to the collection for match results 
Initialize the records and variables 
*/ 

-- End outer loop 

END LOOP; 

END; 
+0

Pour référence 'PERSON_TAB.SSN', vous devez mettre à jour le curseur' person_cur' pour l'exposer. Vous avez match_score/temp_score/etc mais vous ne les utilisez pas. Mon impression initiale est que vous n'avez pas besoin de tous les types que vous avez définis ... –

+0

Je ne suis pas sûr de ce que cela signifie - "vous devez mettre à jour le curseur person_cur pour l'exposer." J'ai défini match_score/temp_score etc. parce que je pense que je vais avoir besoin d'eux pour effectuer les comparaisons (mes objectifs sont expliqués dans la section commentaires avant la boucle interne), mais encore une fois c'était les débuts de mon code, et ils sont juste à présent.S'il y a un moyen de le faire sans définir d'enregistrements supplémentaires, je vais essayer. – Julie

Répondre

2

Vous avez demandé:

person_tab .-- COMMENT RÉFÉRENCE PERSON_TAB.SSN?

Comme ceci:

person_tab(i).ssn 
+0

Merci, cela a directement répondu à ma question. Je suppose que cela signifie que je n'ai pas besoin de spécifier l'enregistrement, car la table (loop_index) pointera vers la "ligne" correcte. – Julie

+0

C'est vrai - person_tab (i) EST un enregistrement de type person_rec% ROWTYPE. –

+0

Merci! Cela aide beaucoup. Combiné avec la suggestion des meilleures pratiques de David ci-dessus, je pense que je devrais être en mesure de comprendre cela. – Julie

2

La meilleure pratique ici serait d'utiliser une seule instruction SQL si cela est possible. Ne faites jamais en PL/SQL ce que vous pouvez faire en SQL.

Dans tous les cas, évitez les curseurs explicites si vous pouvez le faire et utiliser la syntaxe implicite à la place:

For x in (select table_name from user_tables) 
Loop 
    other_variable = x.table_name; 
    etc. ..... 
End Loop; 
+0

Si j'utilise ce qui précède pour définir le curseur implicite, dois-je encore définir un enregistrement? Ou est-ce que j'utilise simplement la table (loop_index)? Quand définissez-vous les enregistrements par rapport aux tables si vous pouvez référencer l'enregistrement d'une table à l'aide de la table (loop_index)? – Julie

+0

Avec cette syntaxe de curseur implicite, vous allez simplement parcourir chaque ligne de l'enregistrement. Je suggère de parcourir les docs pour obtenir plus d'informations sur les attributs, mais vous n'avez pas besoin de créer un enregistrement pour sélectionner. –

Questions connexes