0
votes

I am trying to dispatch data from from a temporary table into target tables. The code is already written by third party developers, but never tested before they left.

I managed to rectify other errors, and now the very first line gives me the following errors :

ORA-06502: PL/SQL: numeric or value error: NULL index table key value.

 DECLARE
  -- in-memory cache table type
  TYPE CODE_ID_MAP IS TABLE OF NUMBER(20) INDEX BY VARCHAR2(1200);

  -- in-memory chache tables
  magasins_map CODE_ID_MAP;
  type_canal_map CODE_ID_MAP;
  partenaires_map CODE_ID_MAP;
  types_adresses_map CODE_ID_MAP;
  types_magasins_map CODE_ID_MAP;
  statut_donnees_partenaire_map CODE_ID_MAP;

  -- cursor on input data
  CURSOR imp_cur IS
    SELECT
      extern.*,
      c.id     AS idcarteu, -- correspond a "extern.numero_carte"

      m0.id    AS old_membres_id0,
      m0.idrxp AS idrxp0,
      c0.id    AS idcarteu0,

      m1.id    AS old_membres_id1,
      m1.idrxp AS idrxp1,
      c1.id    AS idcarteu1,

      m2.id    AS old_membres_id2,
      m2.idrxp AS idrxp2,
      c2.id    AS idcarteu2

    FROM batch_rxp2bmc extern

    LEFT JOIN donnees_carteu c  ON extern.numero_carte = c.numero_carte

    LEFT JOIN membres m0        ON extern.membre_idrxp0 = m0.idrxp
    LEFT JOIN donnees_carteu c0 ON m0.donnees_carteu_id = c0.id

    LEFT JOIN membres m1        ON extern.membre_idrxp1 = m1.idrxp
    LEFT JOIN donnees_carteu c1 ON m1.donnees_carteu_id = c1.id

    LEFT JOIN membres m2        ON extern.membre_idrxp2 = m2.idrxp
    LEFT JOIN donnees_carteu c2 ON m2.donnees_carteu_id = c2.id;

  TYPE IMP_TBL_TYPE IS TABLE OF imp_cur%ROWTYPE;
  imp_row imp_cur%ROWTYPE;
  imp_tbl IMP_TBL_TYPE;
  imp_cur_max PLS_INTEGER := 5000;

  PROCEDURE log (level VARCHAR2, lino NUMBER, msg VARCHAR2) IS BEGIN
    dbms_output.put_line('[' || level || '][#' || lino || '] ' || msg);
  END log;


  PROCEDURE update_membre (
    lino NUMBER,                    -- numero de ligne
    m imp_cur%ROWTYPE,              -- donnees deversees
    old_membres_id membres.id%TYPE, -- sujet de la mise-a-jour
    old_carteu_id donnees_carteu.id%TYPE -- carte-u du sujet de la mise-a-jour
  )
  IS
    new_carteu_id donnees_carteu.id%TYPE;
  BEGIN
    log('INFO', lino, 'mise-a-jour du membre ' || m.membre_identifiant);

    -- rendre l'id variable -- imp_row "m" est en lecture seule
    new_carteu_id := m.idcarteu;

    -- insertion de la carte si elle n'existe pas
    IF new_carteu_id IS NULL THEN
      new_carteu_id := seq_donnees_carteu_id.nextval;
      INSERT INTO donnees_carteu (id, numero_carte) VALUES (new_carteu_id, m.numero_carte);
    END IF;

    -- alerte si le client change de carte-u car l'ancienne
    -- n'est pas supprime en cascade et devient orphelin.
    IF new_carteu_id != old_carteu_id THEN
      log('WARN', lino,
        m.membre_identifiant || ' change de carte-u : ' ||
        'la ' || new_carteu_id || ' remplace la ' || old_carteu_id || ' devenant orphelin'
      );
    END IF;

    -- mise-a-jour du membre
    UPDATE membres SET
      idrxp = m.membre_idrxp0, -- on ecrase tjrs l'id historique
      email = m.membre_email,
      identifiant = m.membre_identifiant,
      civilite = m.membre_civilite,
      nom = m.membre_nom,
      prenom = m.membre_prenom,
      naissancedate = m.membre_naissance,
      profession = m.membre_profession,
      telfixe = m.membre_tel_fixe,
      telmobile = m.membre_tel_mobile,
      situationfamiliale = m.membre_situ_fam,
      carteutypeporteur = m.membre_type_porteur,
      carteu_porteur_principal = m.membre_porteur_principal,
      donnees_carteu_id = new_carteu_id
    WHERE id = old_membres_id;

    -- mise-a-jour/insertion de l'adresse de domicile
    MERGE INTO donnees_adresses trg
      USING (
        SELECT
          old_membres_id AS membres_id,
          types_adresses_map(m.adresse_type) AS types_adresses_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.types_adresses_id = src.types_adresses_id)
    WHEN MATCHED THEN
      UPDATE SET
        adresse = m.adresse_street,
        complement_adresse = m.adresse_complement,
        code_postal = m.adresse_code_postal,
        ville = m.adresse_ville,
        pays = m.adresse_pays
    WHEN NOT MATCHED THEN
      INSERT (
        membres_id,
        types_adresses_id,
        adresse,
        complement_adresse,
        code_postal,
        ville,
        pays
      )
      VALUES (
        old_membres_id,
        types_adresses_map(m.adresse_type),
        m.adresse_street,
        m.adresse_complement,
        m.adresse_code_postal,
        m.adresse_ville,
        m.adresse_pays
      );

    -- mise-a-jour/insertion des souscriptions sms, email, courrier
    MERGE INTO donnees_communication trg
      USING (
        SELECT
          old_membres_id AS membres_id,
          type_canal_map(m.optin_sms_canal) AS canal_communication_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.canal_communication_id = src.canal_communication_id)
    WHEN MATCHED THEN
      UPDATE SET
        accepte_canal = m.optin_sms,
        date_derniere_maj = m.optin_sms_date,
        source_maj = m.optin_sms_source
      WHERE accepte_canal != m.optin_sms -- mise-a-jour si ca change qqc
    WHEN NOT MATCHED THEN
      INSERT (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      )
      VALUES (
        old_membres_id,
        m.optin_sms,
        m.optin_sms_date,
        m.optin_sms_source,
        type_canal_map(m.optin_sms_canal)
      );

    MERGE INTO donnees_communication trg
      USING (
        SELECT
          old_membres_id AS membres_id,
          type_canal_map(m.optin_email_canal) AS canal_communication_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.canal_communication_id = src.canal_communication_id)
    WHEN MATCHED THEN
      UPDATE SET
        accepte_canal = m.optin_email,
        date_derniere_maj = m.optin_email_date,
        source_maj = m.optin_email_source
      WHERE accepte_canal != m.optin_email -- mise-a-jour si ca change qqc
    WHEN NOT MATCHED THEN
      INSERT (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      )
      VALUES (
        old_membres_id,
        m.optin_email,
        m.optin_email_date,
        m.optin_email_source,
        type_canal_map(m.optin_email_canal)
      );

    MERGE INTO donnees_communication trg
      USING (
        SELECT
          old_membres_id AS membres_id,
          type_canal_map(m.optin_courrier_canal) AS canal_communication_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.canal_communication_id = src.canal_communication_id)
    WHEN MATCHED THEN
      UPDATE SET
        accepte_canal = m.optin_courrier,
        date_derniere_maj = m.optin_courrier_date,
        source_maj = m.optin_courrier_source
      WHERE accepte_canal != m.optin_courrier -- mise-a-jour si ca change qqc
    WHEN NOT MATCHED THEN
      INSERT (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      )
      VALUES (
        old_membres_id,
        m.optin_courrier,
        m.optin_courrier_date,
        m.optin_courrier_source,
        type_canal_map(m.optin_courrier_canal)
      );

    -- remplacement des enfants (nous sommes pas en mesure de faire le lien entre
    -- des enfant deja en base et ceux qui sont deverses)
    DELETE membre_enfants WHERE membre_id = old_membres_id;
    INSERT ALL
      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_1_prenom, m.enfant_1_sexe, m.enfant_1_naissance)

      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_2_prenom, m.enfant_2_sexe, m.enfant_2_naissance)

      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_3_prenom, m.enfant_3_sexe, m.enfant_3_naissance)

      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_4_prenom, m.enfant_4_sexe, m.enfant_4_naissance)

      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_5_prenom, m.enfant_5_sexe, m.enfant_5_naissance)

      INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (old_membres_id, m.enfant_6_prenom, m.enfant_6_sexe, m.enfant_6_naissance)
    SELECT * FROM dual;

    -- mise-a-jour/insertion des magasins favorites
    MERGE INTO membres_types_magasins trg
      USING (
      SELECT
        old_membres_id AS membres_id,
        magasins_map(m.fav_magasinsu) AS magasins_id,
        types_magasins_map(m.fav_magasinsu_type) AS types_magasins_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.types_magasins_id = src.types_magasins_id)
    WHEN MATCHED THEN
      UPDATE SET
        magasins_id = src.magasins_id
      WHERE magasins_id != src.magasins_id
    WHEN NOT MATCHED THEN
      INSERT (membres_id, magasins_id, types_magasins_id)
      VALUES (src.membres_id, src.magasins_id, src.types_magasins_id);

    MERGE INTO membres_types_magasins trg
      USING (
        SELECT
        old_membres_id AS membres_id,
        magasins_map(m.fav_mobileapp) AS magasins_id,
        types_magasins_map(m.fav_mobileapp_type) AS types_magasins_id
        FROM dual
      ) src
      ON (trg.membres_id = src.membres_id AND trg.types_magasins_id = src.types_magasins_id)
    WHEN MATCHED THEN
      UPDATE SET
        magasins_id = src.magasins_id
      WHERE magasins_id != src.magasins_id
    WHEN NOT MATCHED THEN
      INSERT (membres_id, magasins_id, types_magasins_id)
      VALUES (src.membres_id, src.magasins_id, src.types_magasins_id);

    -- suppression du consentement s'il n'est pas renseigne
    IF m.consentement_date IS NULL THEN
      DELETE membre_consentement WHERE id_membre = old_membres_id;

    -- creation du consentement s'il n'existe pas encore
    ELSE
      MERGE INTO membre_consentement trg
        USING (
        SELECT
          old_membres_id AS id_membre,
          m.consentement_date AS date_consentement,
          partenaires_map(m.consentement_partenaire) AS id_source_consentement
        FROM dual
        ) src
        ON (trg.id_membre = src.id_membre)
      WHEN NOT MATCHED THEN
        INSERT (id_membre, date_consentement, id_source_consentement)
        VALUES (src.id_membre, src.date_consentement, src.id_source_consentement);
    END IF;

    -- point de vigilence : munissez-vous d'un schema de la BMC
    --   la relation entre MEMBRES et DONNEES_PARTENAIRE et de cardinalite
    --   one-to-many et non many-to-many comme le sugere le tableau intermediare
    --   MEMBRES_DONNEES_PARTENAIRE. une adhesion membre-service (representee
    --   par DONNEES_PARTENAIRE) ne peut pas etre partage entre plusieurs membres.
    --   c'est une erreur dans la conception de la bdd.

    DECLARE
      donnees_partenaire_id donnees_partenaire.id%TYPE;
    BEGIN
      SELECT dp.id INTO donnees_partenaire_id FROM donnees_partenaire dp
      INNER JOIN membres_donnees_partenaire mdp
      ON mdp.donnees_partenaire_id = dp.id
      WHERE mdp.membres_id = old_membres_id
      AND dp.partenaires_id = partenaires_map(m.adhesion_magasinsu_partenaire);

      UPDATE donnees_partenaire dp
      SET statut_donnees_partenaire_id = statut_donnees_partenaire_map(m.adhesion_magasinsu_statut)
      WHERE id = donnees_partenaire_id;

    EXCEPTION 
      WHEN NO_DATA_FOUND THEN
        log('ERROR', lino, m.membre_identifiant || ' n''est pas associe a magasins-u');
    END;

    DECLARE
      donnees_partenaire_id donnees_partenaire.id%TYPE;
    BEGIN
      SELECT dp.id INTO donnees_partenaire_id FROM donnees_partenaire dp
      INNER JOIN membres_donnees_partenaire mdp
      ON mdp.donnees_partenaire_id = dp.id
      WHERE mdp.membres_id = old_membres_id
      AND dp.partenaires_id = partenaires_map(m.adhesion_mobileapp_partenaire);

      UPDATE donnees_partenaire dp
      SET statut_donnees_partenaire_id = statut_donnees_partenaire_map(m.adhesion_mobileapp_statut)
      WHERE id = donnees_partenaire_id;

    EXCEPTION 
      WHEN NO_DATA_FOUND THEN
        donnees_partenaire_id := seq_donnees_part_id.nextval;

        INSERT INTO donnees_partenaire (
          id,
          statut_donnees_partenaire_id,
          partenaires_id
        ) VALUES (
          donnees_partenaire_id,
          statut_donnees_partenaire_map(m.adhesion_magasinsu_statut),
          partenaires_map(m.adhesion_magasinsu_partenaire)
        );

        INSERT INTO membres_donnees_partenaire (
          membres_id,
          donnees_partenaire_id
        ) VALUES (
          old_membres_id,
          donnees_partenaire_id
        );
    END;

  END update_membre;


   PROCEDURE create_membre (
    lino NUMBER,                    -- numero de ligne versee
    m imp_cur%ROWTYPE              -- donnees derversees
   ) AS
   idcarteu donnees_carteu.id%TYPE; -- id de la carte associe au numero deverse
    membres_id membres.id%TYPE;     -- cle primaire du nouveau membre
    donnees_partenaire_id donnees_partenaire.id%TYPE; -- cle primaire des adhesions appli du client
  BEGIN
    log('WARN', lino, m.membre_identifiant || ' est nouvellement cree. l''utilisateur n''a pas de mdp.');

    -- insertion de la carte-u si elle n'existe pas encore
    IF idcarteu IS NULL THEN
      idcarteu := seq_donnees_carteu_id.nextval;
      INSERT INTO donnees_carteu (id, numero_carte)
      VALUES (idcarteu, m.numero_carte);
    END IF;

    -- cle primaire du nouveau membre est cle etrangere pour les infos associees
    membres_id := seq_membres_id.nextval;

    -- insertion du client lui-meme
    INSERT INTO membres (
      id,
      idrxp,
      email,
      identifiant,
      civilite,
      nom,
      prenom,
      naissancedate,
      profession,
      telfixe,
      telmobile,
      situationfamiliale,
      carteutypeporteur,
      carteu_porteur_principal,
      donnees_carteu_id
    ) VALUES (
      membres_id,
      m.membre_idrxp0,
      m.membre_email,
      m.membre_identifiant,
      m.membre_civilite,
      m.membre_nom,
      m.membre_prenom,
      m.membre_naissance,
      m.membre_profession,
      m.membre_tel_fixe,
      m.membre_tel_mobile,
      m.membre_situ_fam,
      m.membre_type_porteur,
      m.membre_porteur_principal,
      idcarteu
    );


      -- insertion de l'adresse domicile
      INSERT INTO donnees_adresses (
        membres_id,
        types_adresses_id,
        adresse,
        complement_adresse,
        code_postal,
        ville,
        pays
      ) VALUES (
        membres_id,
        types_adresses_map(m.adresse_type),
        m.adresse_street,
        m.adresse_complement,
        m.adresse_code_postal,
        m.adresse_ville,
        m.adresse_pays
      );

      -- insertion des souscriptions aux animations commerciales du client
      INSERT INTO donnees_communication (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      ) VALUES (
        membres_id,
        m.optin_sms,
        m.optin_sms_date,
        m.optin_sms_source,
        type_canal_map(m.optin_sms_canal)
      );

      INSERT INTO donnees_communication (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      ) VALUES (
        membres_id,
        m.optin_email,
        m.optin_email_date,
        m.optin_email_source,
        type_canal_map(m.optin_email_canal)
      );

      INSERT INTO donnees_communication (
        membres_id,
        accepte_canal,
        date_derniere_maj,
        source_maj,
        canal_communication_id
      ) VALUES (
        membres_id,
        m.optin_courrier,
        m.optin_courrier_date,
        m.optin_courrier_source,
        type_canal_map(m.optin_courrier_canal)
      );


    -- insertion des enfants
    IF m.enfant_1_prenom    IS NOT NULL OR
       m.enfant_1_sexe      IS NOT NULL OR
       m.enfant_1_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_1_prenom, m.enfant_1_sexe, m.enfant_1_naissance);
    END IF;

    IF m.enfant_2_prenom    IS NOT NULL OR
       m.enfant_2_sexe      IS NOT NULL OR
       m.enfant_2_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_2_prenom, m.enfant_2_sexe, m.enfant_2_naissance);
    END IF;

    IF m.enfant_3_prenom    IS NOT NULL OR
       m.enfant_3_sexe      IS NOT NULL OR
       m.enfant_3_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_3_prenom, m.enfant_3_sexe, m.enfant_3_naissance);
    END IF;

    IF m.enfant_4_prenom    IS NOT NULL OR
       m.enfant_4_sexe      IS NOT NULL OR
       m.enfant_4_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_4_prenom, m.enfant_4_sexe, m.enfant_4_naissance);
    END IF;

    IF m.enfant_5_prenom    IS NOT NULL OR
       m.enfant_5_sexe      IS NOT NULL OR
       m.enfant_5_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_5_prenom, m.enfant_5_sexe, m.enfant_5_naissance);
    END IF;

    IF m.enfant_6_prenom    IS NOT NULL OR
       m.enfant_6_sexe      IS NOT NULL OR
       m.enfant_6_naissance IS NOT NULL
    THEN
      INSERT INTO membre_enfants (membre_id, prenom, sexe, naissancedate)
      VALUES (membres_id, m.enfant_6_prenom, m.enfant_6_sexe, m.enfant_6_naissance);
    END IF;

    -- insertion des magasins favorites
    IF m.fav_magasinsu IS NOT NULL THEN
      INSERT INTO membres_types_magasins (membres_id, magasins_id, types_magasins_id)
      VALUES (membres_id, magasins_map(m.fav_magasinsu), types_magasins_map(m.fav_magasinsu_type));
    END IF;

    IF m.fav_mobileapp IS NOT NULL THEN
      INSERT INTO membres_types_magasins (membres_id, magasins_id, types_magasins_id)
      VALUES (membres_id, magasins_map(m.fav_mobileapp), types_magasins_map(m.fav_mobileapp_type));
    END IF;

    -- insertion du consentement transfert hors UE de donnees du client
    IF m.consentement_date IS NOT NULL THEN
      INSERT INTO membre_consentement (id_membre, date_consentement, id_source_consentement)
      VALUES (membres_id, m.consentement_date, partenaires_map(m.consentement_partenaire));
    END IF;

    -- insertion des inscriptions aux differentes applications
    IF m.adhesion_magasinsu_statut IS NOT NULL THEN
      donnees_partenaire_id := seq_donnees_part_id.nextval;

      INSERT INTO donnees_partenaire (
        id,
        statut_donnees_partenaire_id,
        partenaires_id
      ) VALUES (
        donnees_partenaire_id,
        statut_donnees_partenaire_map(m.adhesion_magasinsu_statut),
        partenaires_map(m.adhesion_magasinsu_partenaire)
      );

      INSERT INTO membres_donnees_partenaire (
        membres_id,
        donnees_partenaire_id
      ) VALUES (
        membres_id,
        donnees_partenaire_id
      );
    END IF;

    IF m.adhesion_mobileapp_statut IS NOT NULL THEN
      donnees_partenaire_id := seq_donnees_part_id.nextval;

      INSERT INTO donnees_partenaire (
        id,
        statut_donnees_partenaire_id,
        partenaires_id
      ) VALUES (
        donnees_partenaire_id,
        statut_donnees_partenaire_map(m.adhesion_mobileapp_statut),
        partenaires_map(m.adhesion_mobileapp_partenaire)
      );

      INSERT INTO membres_donnees_partenaire (
        membres_id,
        donnees_partenaire_id
      ) VALUES (
        membres_id,
        donnees_partenaire_id
      );
    END IF;

  END;

  PROCEDURE delete_membre (lino NUMBER, m imp_cur%ROWTYPE) IS BEGIN
    log('INFO', lino, m.membre_identifiant || ' est supprime par fusion');
    DELETE FROM donnees_adresses WHERE membres_id = m.old_membres_id2;
    DELETE FROM membres_types_magasins WHERE membres_id = m.old_membres_id2;
    DELETE FROM membre_consentement WHERE id_membre = m.old_membres_id2;

    -- cette action supprime en cascade les donnees associees des tableaux suivantes
    -- - donnees_personnelles
    -- - mot_de_passe_token
    -- - membre_enfants
    -- - donnees_communication
    -- - membres_donnees_partenaire
    DELETE FROM membres WHERE id = m.old_membres_id2;

   /* IF m.numero_carte != m.numero_carte2 THEN
      log('WARN', lino,
        m.membre_identifiant || ' change de carte-u: la ' ||
        m.numero_carte || ' remplace la ' ||
        m.numero_carte2 || ' devenant orphelin.'
      );
    END IF;*/
  END delete_membre;

-- -----------------------------------------------------------------------------
BEGIN
  dbms_output.enable(NULL); -- unlimited output

  -- mettre des donnees statiques / le referentiel en cache
  FOR row IN (SELECT id, code FROM magasins) LOOP magasins_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM type_canal) LOOP type_canal_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM partenaires) LOOP partenaires_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM types_adresses) LOOP types_adresses_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM types_magasins) LOOP types_magasins_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM statut_donnees_partenaire) LOOP statut_donnees_partenaire_map(row.code) := row.id; END LOOP;

  -- bulk collect afin de reduire le cout associe au changement
  -- de contexte entre le moteur sql et celui de scripting

  OPEN imp_cur;
  LOOP FETCH imp_cur BULK COLLECT INTO imp_tbl LIMIT imp_cur_max;
    EXIT WHEN imp_tbl.COUNT = 0;
    FOR lino IN 1..imp_tbl.COUNT LOOP
      imp_row := imp_tbl(lino);

      -- la centralisation de la donnee membre a pour consequence la fusion
      -- des anciennes entrees dont l'arbre decisionnel se trouve ci-dessous.

      IF imp_row.adhesion_magasinsu_statut IS NULL THEN
        log('ERROR', lino, imp_row.membre_identifiant || ' n''est pas associe a l''application magasins-u');

      -- #3
      ELSIF imp_row.membre_idrxp0 IS NULL THEN
        log('ERROR', lino, '1st rxp id is null');

      -- #2
      ELSIF imp_row.idrxp0 IS NOT NULL THEN
        update_membre(lino, imp_row, imp_row.old_membres_id0, imp_row.idcarteu0);

      ELSIF imp_row.idrxp0 IS NULL THEN

        IF imp_row.membre_idrxp1 IS NULL THEN

      -- #12
          IF imp_row.membre_idrxp2 IS NULL THEN
            create_membre(lino, imp_row);
      -- #9
          ELSIF imp_row.idrxp2 IS NULL THEN
            log('ERROR', lino, 'fusion d''ids RXP non-valide : 0=non-existant 1=vide 2=non-existant');
      -- #6
          ELSIF imp_row.idrxp2 IS NOT NULL THEN
            log('ERROR', lino,
              'fusion d''ids RXP non-valide : 0=non-existant 1=vide 2=existe. ' || 
              'ce 3eme (idx=2) est juge obsolete et donc rejete'
            );
          END IF;

        ELSIF imp_row.idrxp1 IS NULL THEN

      -- #11
          IF imp_row.membre_idrxp2 IS NULL THEN
            create_membre(lino, imp_row);
      -- #8
          ELSIF imp_row.idrxp2 IS NULL THEN
            create_membre(lino, imp_row);
      -- #5
          ELSIF imp_row.idrxp2 IS NOT NULL THEN
            update_membre(lino, imp_row, imp_row.old_membres_id2, imp_row.idcarteu2);
          END IF;

        ELSIF imp_row.idrxp1 IS NOT NULL THEN

      -- #10
          IF imp_row.membre_idrxp2 IS NULL THEN
            update_membre(lino, imp_row, imp_row.old_membres_id1, imp_row.idcarteu1);
      -- #7
          ELSIF imp_row.idrxp2 IS NULL THEN
            update_membre(lino, imp_row, imp_row.old_membres_id1, imp_row.idcarteu1);
      -- #4
          ELSIF imp_row.idrxp2 IS NOT NULL THEN
            delete_membre(lino, imp_row);
            update_membre(lino, imp_row, imp_row.old_membres_id1, imp_row.idcarteu1);
          END IF;
        END IF;
      END IF;
    END LOOP;
  END LOOP;
  CLOSE imp_cur;
END;
1
It looks like you're missing the content of the BEGIN ... END section of this block. Could you please edit the question to include it? Without that, all I can really say from the error message is that somewhere your code is trying to use a NULL key in one of the various maps.Luke Woodward
Your code should look like DECLARE....BEGIN....END; --> It is called dynamic block. If it is procedure then it should be CREATE PROCEDURE...BEGIN...END; But looking at your code, It seems like your code is a snippet of some PACKAGE BODY. Please edit your question and add the whole code.Popeye
@LukeWoodward: Here is the whole code for the SQL.Best Dad
OK, I wasn't expecting quite that much code. There are 38 places where your code looks up a value from one of those maps and any one of them could be the problem. Without your data (and please don't add it to the question) I can't say which one it is. I'm afraid you are going to have to debug this yourself. All I can say is that my previous comment about a NULL key to one of this maps still stands. I will say however that I would expect the error message to contain a stacktrace with a line number that says where the problem is.Luke Woodward
For what it's worth, the following LiveSQL script reproduces your error message, and also indicates that the error occurs on line 5: livesql.oracle.com/apex/livesql/s/iphlmdlx8nbpsw37fdzjlgl85Luke Woodward

1 Answers

0
votes

Check the tables in the initialization block (below). Validate the column code does not contain any null values, as that is being used as the index to the collection.

  FOR row IN (SELECT id, code FROM magasins) LOOP magasins_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM type_canal) LOOP type_canal_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM partenaires) LOOP partenaires_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM types_adresses) LOOP types_adresses_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM types_magasins) LOOP types_magasins_map(row.code) := row.id; END LOOP;
  FOR row IN (SELECT id, code FROM statut_donnees_partenaire) LOOP statut_donnees_partenaire_map(row.code) := row.id; END LOOP;