ORA-06502: PL/SQL: 数字或值错误: NULL 索引表键值
Posted
技术标签:
【中文标题】ORA-06502: PL/SQL: 数字或值错误: NULL 索引表键值【英文标题】:ORA-06502: PL/SQL: numeric or value error: NULL index table key value 【发布时间】:2019-07-22 09:53:54 【问题描述】:我正在尝试将临时表中的数据分派到目标表中。 代码已经由第三方开发者编写,但在他们离开之前从未测试过。
我设法纠正了其他错误,现在第一行给了我以下错误:
ORA-06502:PL/SQL:数字或值错误:NULL 索引表键值。
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;
【问题讨论】:
您似乎缺少此块的BEGIN
... END
部分的内容。您能否编辑问题以包含它?没有它,我可以从错误消息中真正说的是,您的代码在某处尝试在各种map
s 之一中使用NULL
键。
你的代码应该看起来像DECLARE....BEGIN....END;
--> 它被称为动态块。如果是程序,那么它应该是CREATE PROCEDURE...BEGIN...END;
但是看看你的代码,你的代码似乎是一些PACKAGE BODY
的sn-p。请编辑您的问题并添加整个代码。
@LukeWoodward:这是 SQL 的完整代码。
好吧,我没想到会有那么多代码。您的代码在 38 个位置从其中一个映射中查找值,其中任何一个都可能是问题所在。如果没有您的数据(请不要将其添加到问题中),我无法说出它是哪一个。恐怕您将不得不自己调试。我只能说,我之前关于其中一张地图的NULL
键的评论仍然有效。但是我会说,我希望错误消息包含一个堆栈跟踪,其中包含一个说明问题所在的行号。
不管怎样,下面的 LiveSQL 脚本重现了你的错误信息,并且还指出错误发生在第 5 行:livesql.oracle.com/apex/livesql/s/iphlmdlx8nbpsw37fdzjlgl85
【参考方案1】:
检查初始化块中的表格(如下)。验证列代码不包含任何空值,因为它被用作集合的索引。
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;
【讨论】:
以上是关于ORA-06502: PL/SQL: 数字或值错误: NULL 索引表键值的主要内容,如果未能解决你的问题,请参考以下文章
ORA-06502: PL/SQL: 数字或值错误: 字符到数字的转换错误
ORA-06502: PL/SQL: 数字或值错误: NULL 索引表键值
ORA-06502: PL/SQL: 数字或值错误: 数字精度太大
获取 ORA-06502:PL/SQL:数字或值错误:SQL 触发器中的字符到数字转换错误