PL/SQL : 我的程序工作正常但不是我的例外?
PL/SQL : My procedure works fine but not my exceptions?
我正在处理的包有一些问题。我正在使用 sqldeveloper 并在 PL/SQL.
中写入
程序"Ajouter"
应该添加游泳者,你必须指定名字、姓氏等。当我尝试并提供正确的信息时,它运行良好。
但是当我尝试测试我的异常时,它不起作用。 None 我的例外有效。例如,如果我尝试在 sex 中写 "Z"
,它不会告诉我 "Sex has to be F or M"
。它只告诉我 "Procédure PL/SQL terminée."
,类似于 "PL / SQL procedure completed."
.
问题出在哪里?我怎样才能解决这个问题并让我的例外工作?
这是 "Ajouter"(添加)代码:
PROCEDURE Ajouter(Nageur Nageurs%ROWTYPE) AS
ExcNull EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcNull, -1400);
ExcPK EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcPK, -00001);
ExcFK EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcFK, -2291);
ExcCheck EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcCheck, -2290);
BEGIN
INSERT INTO Nageurs values (Nageur.NRLIGUE, Nageur.NOM, Nageur.PRENOM,
Nageur.ANNEENAISS, Nageur.SEXE, Nageur.CATEGORIE, Nageur.CLUB, Nageur.ADRESSE,
Nageur.CODEPOSTAL, Nageur.LOCALITE, Nageur.NRTELEPHONE, Nageur.EMAIL, Nageur.GSM, Nageur.COTISATION);
COMMIT;
DBMS_OUTPUT.PUT_LINE('Nageur ajouté');
EXCEPTION
WHEN ExcNull THEN
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.');
END IF;
WHEN ExcPK THEN
IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.');
ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.');
END IF;
WHEN ExcFK THEN
IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le club n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.');
END IF;
WHEN ExcCheck THEN
IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M');
ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N');
END IF;
WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.');
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Pas de données.');
WHEN OTHERS THEN RAISE;
END;
这是 table Nageur(游泳运动员):
CREATE TABLE Nageurs
(NrLigue CHAR(14)
CONSTRAINT EveCpNageurs PRIMARY KEY,
Nom VARCHAR2(20)
CONSTRAINT EveNomNotNull NOT NULL,
Prenom VARCHAR2(20)
CONSTRAINT EvePrenomNotNull NOT NULL,
AnneeNaiss NUMBER(4)
CONSTRAINT EveNaissanceNotNull NOT NULL,
Sexe CHAR(1)
CONSTRAINT EveSexeNotNull NOT NULL
CONSTRAINT EveSexe CHECK (Sexe in ('F','M')),
Categorie CHAR(2)
CONSTRAINT EveRefNageursCat REFERENCES Categories(Categorie),Club CHAR(5)
CONSTRAINT EveRefNageursClubs REFERENCES Clubs (Club),
Adresse VARCHAR2(50),
CodePostal CHAR(5)
CONSTRAINT EveRefNageursCP REFERENCES CodePostaux (CodePostal),
Localite VARCHAR2(20),
NrTelephone CHAR(15),
EMAIL VARCHAR2(50),
GSM CHAR(15),
Cotisation CHAR(1)
CONSTRAINT EveCotisation CHECK (Cotisation in ('O','N')),
CONSTRAINT EveUnicite UNIQUE (Nom, Prenom)
);
这是一个不起作用的测试示例:
DECLARE
nag nageurs%rowtype;
BEGIN
nag.nrligue := '01/000325/CCM';
nag.nom := 'DISNEY';
nag.prenom := 'WALTER';
nag.anneenaiss := '1901';
nag.sexe := 'Z';
nag.club := 'CCM';
EveGestionNageursMasters.Ajouter(nag);
END ;
我建议在每个异常处理程序中的 IF 语句之前添加 dbms_output.put_line 语句,以准确查看 SQLERRM
.
的文本
您的异常处理程序打印消息但不传播异常。也许您想在每个异常处理程序的末尾添加一个 RAISE;
以将异常传播回调用者,如下所示。
EXCEPTION
WHEN ExcNull THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.');
END IF;
RAISE;
WHEN ExcPK THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.');
ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.');
END IF;
RAISE;
WHEN ExcFK THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le club n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.');
END IF;
RAISE;
WHEN ExcCheck THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M');
ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N');
END IF;
RAISE;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.');
RAISE;
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Pas de données.');
RAISE;
WHEN OTHERS THEN
RAISE;
END;
当您在 Oracle 中这样命名对象时,没有分隔符:
CONSTRAINT EveNomNotNull NOT NULL
实际的约束名称是不区分大小写的,所以报错信息中的约束名称会报:
EVENOMNOTNULL
您可以通过 运行 这样的查询来检查:
select constraint_name from all_constraints where table_name = 'NAGEURS';
这就是使用 INSTR
的以下条件不会检测约束名称的原因:
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN
由于 INSTR 进行区分大小写的搜索,您必须确保它与数据库中创建的约束名称相匹配,例如:
IF(INSTR(SQLERRM, 'EVENOMNOTNULL') <> 0) THEN
我正在处理的包有一些问题。我正在使用 sqldeveloper 并在 PL/SQL.
中写入程序"Ajouter"
应该添加游泳者,你必须指定名字、姓氏等。当我尝试并提供正确的信息时,它运行良好。
但是当我尝试测试我的异常时,它不起作用。 None 我的例外有效。例如,如果我尝试在 sex 中写 "Z"
,它不会告诉我 "Sex has to be F or M"
。它只告诉我 "Procédure PL/SQL terminée."
,类似于 "PL / SQL procedure completed."
.
问题出在哪里?我怎样才能解决这个问题并让我的例外工作?
这是 "Ajouter"(添加)代码:
PROCEDURE Ajouter(Nageur Nageurs%ROWTYPE) AS
ExcNull EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcNull, -1400);
ExcPK EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcPK, -00001);
ExcFK EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcFK, -2291);
ExcCheck EXCEPTION;
PRAGMA EXCEPTION_INIT(ExcCheck, -2290);
BEGIN
INSERT INTO Nageurs values (Nageur.NRLIGUE, Nageur.NOM, Nageur.PRENOM,
Nageur.ANNEENAISS, Nageur.SEXE, Nageur.CATEGORIE, Nageur.CLUB, Nageur.ADRESSE,
Nageur.CODEPOSTAL, Nageur.LOCALITE, Nageur.NRTELEPHONE, Nageur.EMAIL, Nageur.GSM, Nageur.COTISATION);
COMMIT;
DBMS_OUTPUT.PUT_LINE('Nageur ajouté');
EXCEPTION
WHEN ExcNull THEN
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.');
END IF;
WHEN ExcPK THEN
IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.');
ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.');
END IF;
WHEN ExcFK THEN
IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le club n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.');
END IF;
WHEN ExcCheck THEN
IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M');
ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N');
END IF;
WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.');
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Pas de données.');
WHEN OTHERS THEN RAISE;
END;
这是 table Nageur(游泳运动员):
CREATE TABLE Nageurs
(NrLigue CHAR(14)
CONSTRAINT EveCpNageurs PRIMARY KEY,
Nom VARCHAR2(20)
CONSTRAINT EveNomNotNull NOT NULL,
Prenom VARCHAR2(20)
CONSTRAINT EvePrenomNotNull NOT NULL,
AnneeNaiss NUMBER(4)
CONSTRAINT EveNaissanceNotNull NOT NULL,
Sexe CHAR(1)
CONSTRAINT EveSexeNotNull NOT NULL
CONSTRAINT EveSexe CHECK (Sexe in ('F','M')),
Categorie CHAR(2)
CONSTRAINT EveRefNageursCat REFERENCES Categories(Categorie),Club CHAR(5)
CONSTRAINT EveRefNageursClubs REFERENCES Clubs (Club),
Adresse VARCHAR2(50),
CodePostal CHAR(5)
CONSTRAINT EveRefNageursCP REFERENCES CodePostaux (CodePostal),
Localite VARCHAR2(20),
NrTelephone CHAR(15),
EMAIL VARCHAR2(50),
GSM CHAR(15),
Cotisation CHAR(1)
CONSTRAINT EveCotisation CHECK (Cotisation in ('O','N')),
CONSTRAINT EveUnicite UNIQUE (Nom, Prenom)
);
这是一个不起作用的测试示例:
DECLARE
nag nageurs%rowtype;
BEGIN
nag.nrligue := '01/000325/CCM';
nag.nom := 'DISNEY';
nag.prenom := 'WALTER';
nag.anneenaiss := '1901';
nag.sexe := 'Z';
nag.club := 'CCM';
EveGestionNageursMasters.Ajouter(nag);
END ;
我建议在每个异常处理程序中的 IF 语句之前添加 dbms_output.put_line 语句,以准确查看 SQLERRM
.
您的异常处理程序打印消息但不传播异常。也许您想在每个异常处理程序的末尾添加一个 RAISE;
以将异常传播回调用者,如下所示。
EXCEPTION
WHEN ExcNull THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.');
ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.');
END IF;
RAISE;
WHEN ExcPK THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.');
ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.');
END IF;
RAISE;
WHEN ExcFK THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le club n''existe pas');
ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.');
END IF;
RAISE;
WHEN ExcCheck THEN
dbms_output.put_line(SQLERRM);
IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M');
ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN
DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N');
END IF;
RAISE;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.');
RAISE;
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Pas de données.');
RAISE;
WHEN OTHERS THEN
RAISE;
END;
当您在 Oracle 中这样命名对象时,没有分隔符:
CONSTRAINT EveNomNotNull NOT NULL
实际的约束名称是不区分大小写的,所以报错信息中的约束名称会报:
EVENOMNOTNULL
您可以通过 运行 这样的查询来检查:
select constraint_name from all_constraints where table_name = 'NAGEURS';
这就是使用 INSTR
的以下条件不会检测约束名称的原因:
IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN
由于 INSTR 进行区分大小写的搜索,您必须确保它与数据库中创建的约束名称相匹配,例如:
IF(INSTR(SQLERRM, 'EVENOMNOTNULL') <> 0) THEN