如何从 Python 引发 Oracle PL/SQL 异常

问题描述 投票:0回答:1

我正在尝试创建一个使用 Oracle 过程进行操作的 CRUD 应用程序。 每个过程都有异常,并且有一个与之关联的触发器,但是当使用 Python 代码时,它们都不会得到处理。 例如,如果我尝试输入重复的 ID,它应该处理异常,因为它们应该是唯一的。在 Oracle 上执行时工作正常,但从 Python 执行时,它的行为就好像记录已插入,尽管事实并非如此。

这是Python代码的插入部分

import cx_Oracle

#INSERT EMPLOYEE
def crearEmpleado():
    validEmpno = False
    while(not validEmpno):
        p_empno = input('Ingrese el número de empleado: ')
        if p_empno.isnumeric() and int(p_empno) > 0 and int(p_empno) <= 999999:
            validEmpno = True
            p_empno = int(p_empno)
        else:
            print('Error')

    validEname = False
    while(not validEname):
        p_ename = input('Ingrese el nombre del empleado: ')
        if len(p_ename) > 0 and len(p_ename) <= 10:
            validEname = True
        else:
            print('Error')

    validJob = False
    while(not validJob):
        p_job = input('Ingrese el puesto del empleado: ')
        if len(p_job) > 0 and len(p_job) <= 9:
            validJob = True
        else:
            print('Error')
    
    validMgr = False
    while(not validMgr):
        p_mgr = input('Ingrese el número de manager: ')
        if p_mgr.isnumeric() and int(p_mgr) > 0 and int(p_mgr) <= 9999:
            validMgr = True
            p_mgr = int(p_mgr)
        else:
            print('Error')

    validHiredate = False
    while(not validHiredate):
        p_hiredate = input('Ingrese la fecha de contratación en formato DD/MM/YYYY: ')
        if len(p_hiredate) > 0 and len(p_hiredate) <= 10:
            validHiredate = True
        else:
            print('Error')

    validSal = False
    while(not validSal):
        p_sal = input('Ingrese el salario: ')
        if float(p_sal) > 0 and float(p_sal) <= 99999.99:
            validSal = True
            p_sal = float(p_sal)
        else:
            print('Error')

    validComm = False
    while(not validComm):
        p_comm = input('Ingrese el porcentaje de comisión: ')
        if float(p_comm) <= 99999.99:
            validComm = True
            p_comm = float(p_comm)
        else:
            print('Error')

    validDeptno = False
    while(not validDeptno):
        p_deptno = input('Ingrese el número de departamento: ')
        if p_deptno.isnumeric() and int(p_deptno) > 0 and int(p_deptno) <= 99:
            validDeptno = True
            p_deptno = int(p_deptno)
        else:
            print('Error')

    data = [p_empno, p_ename, p_job, p_mgr, p_hiredate, p_sal, p_comm, p_deptno]
    return data

#CONECT
def connCrearEmpleado(data):
        conn = cx_Oracle.connect('HR/hr@localhost:1521/xepdb1')
        try:
            cursor = conn.cursor()
            cursor.callproc('add_emp', data)
            print('\n¡Empleado registrado!\n')
        except cx_Oracle.DatabaseError as err:
            print('Database connection error: {}'.format(err))
            print(err.code)
            print(err.message)
            print(err.context)
            raise

这是正在使用的桌子:

CREATE TABLE emp (
    empno NUMBER(4) NOT NULL,
    ename VARCHAR2(10) NOT NULL,
    job VARCHAR2(9) NOT NULL,
    mgr NUMBER(4) NOT NULL,
    hiredate DATE NOT NULL,
    sal NUMBER(7,2) NOT NULL,
    comm NUMBER(7,2),
    deptno NUMBER(2) NOT NULL
)

这是 PL/SQL 过程:

create or replace PROCEDURE add_emp
    (p_empno in NUMBER, p_ename in VARCHAR2, p_job in VARCHAR2, p_mgr in NUMBER, p_hiredate in VARCHAR2, p_sal in NUMBER, p_comm in NUMBER, p_deptno in NUMBER)

IS
    v_empno                 NUMBER;
    e_unique_empno          EXCEPTION;              
    e_notnull_empno         EXCEPTION;
    e_notnull_ename         EXCEPTION;
    e_notnull_job           EXCEPTION;
    e_notnull_mgr           EXCEPTION;
    e_notnull_hiredate      EXCEPTION;
    e_valid_sal             EXCEPTION;
    e_notnull_sal           EXCEPTION;  
    v_deptno                NUMBER;
    e_notnull_deptno        EXCEPTION;

BEGIN
    IF p_empno IS NULL THEN
        RAISE e_notnull_empno;
    ELSIF p_ename IS NULL THEN
        RAISE e_notnull_ename;
    ELSIF p_job IS NULL THEN
        RAISE e_notnull_job;
    ELSIF p_mgr IS NULL THEN
        RAISE e_notnull_mgr;
    ELSIF p_hiredate IS NULL THEN
        RAISE e_notnull_hiredate;
    ELSIF p_sal IS NULL THEN
        RAISE e_notnull_sal;
    ELSIF p_sal <= 0 THEN
        RAISE e_valid_sal;
    ELSIF p_deptno IS NULL THEN
        RAISE e_notnull_deptno;
    END IF;
    
    SELECT COUNT(*) INTO v_empno FROM emp WHERE p_empno = empno;
        
    IF v_empno > 0 THEN
        RAISE e_unique_empno;
    END IF;

    INSERT INTO emp
    VALUES(p_empno, UPPER(p_ename), UPPER(p_job), p_mgr, TO_DATE(p_hiredate, 'DD-MM-YYYY'), p_sal, p_comm, p_deptno);
    COMMIT; 

EXCEPTION
    WHEN e_unique_empno THEN
        dbms_output.put_line('El ID ya existe.');
    WHEN e_notnull_empno THEN
        dbms_output.put_line('El campo EMPNO no puede ser nulo.');
    WHEN e_notnull_ename THEN
        dbms_output.put_line('El campo ENAME no puede ser nulo.');
    WHEN e_notnull_job THEN
        dbms_output.put_line('El campo JOB no puede ser nulo.');
    WHEN e_notnull_mgr  THEN
        dbms_output.put_line('El campo MGR no puede ser nulo.');
    WHEN e_notnull_hiredate  THEN
        dbms_output.put_line('El campo HIRE_DATE no puede ser nulo.');
    WHEN e_valid_sal THEN
        dbms_output.put_line('El salario no puede ser menor o igual a cero.');  
    WHEN e_notnull_sal THEN
        dbms_output.put_line('El campo SALARY no puede ser nulo.');
    WHEN e_notnull_deptno THEN
        dbms_output.put_line('El campo DEPTNO no puede ser nulo.');
    WHEN OTHERS THEN
        dbms_output.put_line(SQLERRM);
END add_emp;
/

从 Python 执行时不会引发任何 PL/SQL 异常

python oracle plsql cx-oracle
1个回答
0
投票

给表添加主键约束:

ALTER TABLE emp ADD CONSTRAINT emp__empno__pk PRIMARY KEY(empno);

然后不要捕获异常并将错误打印到控制台。让异常被引发并让

PRIMARY KEY
NOT NULL
约束完成其工作,而不是尝试手动执行完全相同的操作。

CREATE PROCEDURE add_emp(
  p_empno    in EMP.EMPNO%TYPE,
  p_ename    in EMP.ENAME%TYPE,
  p_job      in EMP.JOB%TYPE,
  p_mgr      in EMP.MGR%TYPE,
  p_hiredate in VARCHAR2,
  p_sal      in EMP.SAL%TYPE,
  p_comm     in EMP.COMM%TYPE,
  p_deptno   in EMP.DEPTNO%TYPE
)
IS
BEGIN
  INSERT INTO emp(
    empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    comm,
    deptno
  ) VALUES(
    p_empno,
    UPPER(p_ename),
    UPPER(p_job),
    p_mgr,
    TO_DATE(p_hiredate, 'DD-MM-YYYY'),
    p_sal,
    p_comm,
    p_deptno
  );
END add_emp;
/
© www.soinside.com 2019 - 2024. All rights reserved.