ORA-06550/PLS-00382错误排查:P41_ATTACHMENT文件上传问题
ORA-06550/PLS-00382 类型不匹配错误排查与解决
问题背景
执行PL/SQL过程时触发错误:
ORA-06550: line 5, column 20: PLS-00382: expression is of wrong type
错误指向P41_ATTACHMENT变量的类型匹配问题,相关代码、表结构及项配置如下:
涉事PL/SQL代码
DECLARE v_part_number_list VARCHAR2(4000) := :P41_PART_NUMBER; v_invalid_part_numbers VARCHAR2(4000); -- Almacena valores no válidos v_part_number VARCHAR2(255); -- Almacena cada valor de la lista v_blob BLOB := :P41_ATTACHMENT; -- Archivo cargado v_mimetype VARCHAR2(100) := :P41_MIMETYPE; -- Tipo MIME del archivo v_filename VARCHAR2(100) := :P41_FILENAME; -- Nombre del archivo v_last_updated TIMESTAMP := SYSTIMESTAMP; -- Fecha/Hora de la carga BEGIN -- Validar que todos los valores en la lista de PART_NUMBER sean alfanuméricos FOR part_number IN ( SELECT TRIM(REGEXP_SUBSTR(v_part_number_list, '[^,]+', 1, LEVEL)) AS part_number FROM DUAL CONNECT BY REGEXP_SUBSTR(v_part_number_list, '[^,]+', 1, LEVEL) IS NOT NULL ) LOOP v_part_number := part_number.part_number; -- Ignorar valores vacíos IF v_part_number IS NULL OR v_part_number = '' THEN CONTINUE; END IF; -- Si el valor no es alfanumérico, agregarlo a la lista de valores inválidos IF NOT REGEXP_LIKE(v_part_number, '^[A-Za-z0-9]+$') THEN v_invalid_part_numbers := NVL(v_invalid_part_numbers || ',', '') || v_part_number; END IF; END LOOP; -- Si hay valores no válidos en PART_NUMBER, generar un error IF v_invalid_part_numbers IS NOT NULL THEN RAISE_APPLICATION_ERROR(-20003, 'Invalid Part Number(s): ' || v_invalid_part_numbers); END IF; -- Validar que otros campos numéricos sean correctos IF NOT REGEXP_LIKE(:P41_QTY, '^\d+$') THEN RAISE_APPLICATION_ERROR(-20004, 'Invalid Quantity (QTY): ' || :P41_QTY); END IF; IF NOT REGEXP_LIKE(:P41_HU, '^\d+$') THEN RAISE_APPLICATION_ERROR(-20005, 'Invalid HU value: ' || :P41_HU); END IF; -- Insertar los datos en la tabla, incluyendo el archivo y sus metadatos IF v_blob IS NOT NULL THEN INSERT INTO QDL_SCRAP_REQUESTS ( REQ_ID, REQ_DATE, REQUESTOR, DISPOSAL_TYPE, PART_NUMBER, HU, STATUS, -- Siempre se inserta como "yellow" QTY, PPM, TE_MIN, COMMENTS, OVERDUE, QSB_APPROVED, APPROVAL_DATE, CLAIM_NUM, ATTACHMENT, -- Archivo cargado MIMETYPE, -- Tipo MIME del archivo FILENAME, -- Nombre del archivo ATTCH_UPDATE, -- Fecha de carga QSP_APPROVAL_DATE ) VALUES ( QDL_SCRAP_REQUESTS_SEQ.NEXTVAL, -- Genera REQ_ID automáticamente TO_TIMESTAMP(:P41_RELOJ_EN_TIEMPO_REAL, 'DD/MM/YYYY HH24:MI:SS'), -- Fecha del reloj :P41_REQUESTOR, -- Requestor :P41_DISPOSAL_TYPE, -- Disposal Type :P41_PART_NUMBER, -- Part Number :P41_HU, -- HU 'yellow', -- STATUS: Siempre se inserta como "yellow" :P41_QTY, -- Qty :P41_PPM, -- PPM :P41_TE_MIN, -- TE_MIN :P41_COMMENTS, -- Comments 'N', -- Overdue NULL, -- QSB Approved NULL, -- Approval Date :P41_CLAIM_NUM, -- Claim Num v_blob, -- Archivo cargado v_mimetype, -- Tipo MIME v_filename, -- Nombre del archivo v_last_updated, -- Fecha de carga NULL -- QSP Approval Date ); ELSE -- Si no se cargó un archivo, insertar los datos sin archivo INSERT INTO QDL_SCRAP_REQUESTS ( REQ_ID, REQ_DATE, REQUESTOR, DISPOSAL_TYPE, PART_NUMBER, HU, STATUS, -- Siempre se inserta como "yellow" QTY, PPM, TE_MIN, COMMENTS, OVERDUE, QSB_APPROVED, APPROVAL_DATE, CLAIM_NUM, ATTACHMENT, -- Archivo vacío MIMETYPE, -- Tipo MIME vacío FILENAME, -- Nombre vacío ATTCH_UPDATE, -- Fecha de carga vacía QSP_APPROVAL_DATE ) VALUES ( QDL_SCRAP_REQUESTS_SEQ.NEXTVAL, -- Genera REQ_ID automáticamente TO_TIMESTAMP(:P41_RELOJ_EN_TIEMPO_REAL, 'DD/MM/YYYY HH24:MI:SS'), -- Fecha del reloj :P41_REQUESTOR, -- Requestor :P41_DISPOSAL_TYPE, -- Disposal Type :P41_PART_NUMBER, -- Part Number :P41_HU, -- HU 'yellow', -- STATUS: Siempre se inserta como "yellow" :P41_QTY, -- Qty :P41_PPM, -- PPM :P41_TE_MIN, -- TE_MIN :P41_COMMENTS, -- Comments 'N', -- Overdue NULL, -- QSB Approved NULL, -- Approval Date :P41_CLAIM_NUM, -- Claim Num EMPTY_BLOB(), -- Archivo vacío NULL, -- Tipo MIME vacío NULL, -- Nombre vacío NULL, -- Fecha de carga vacía NULL -- QSP Approval Date ); END IF; -- Confirmar los cambios COMMIT; END;
QDL_SCRAP_REQUESTS表结构
Column Name Data Type Nullable Default Primary Key Comment Identity REQ_ID NUMBER Y REQ_DATE TIMESTAMP(9) Y REQUESTOR VARCHAR2(50) Y DISPOSAL_TYPE VARCHAR2(50) Y PART_NUMBER VARCHAR2(4000) Y HU VARCHAR2(4000) Y STATUS VARCHAR2(500) Y QTY NUMBER Y PPM NUMBER Y TE_MIN NUMBER Y COMMENTS VARCHAR2(4000) Y OVERDUE VARCHAR2(1) Y QSB_APPROVED VARCHAR2(1) Y APPROVAL_DATE TIMESTAMP(9) Y CLAIM_NUM VARCHAR2(4000) Y MIMETYPE VARCHAR2(50) Y FILENAME VARCHAR2(200) Y ATTCH_UPDATE TIMESTAMP(9) Y QSP_APPROVAL VARCHAR2(1) Y QSP_APPROVAL_DATE TIMESTAMP(9) Y ATTACHMENT BLOB Y
P41_ATTACHMENT项配置
Storage Type BLOB column specified in Item Source attribute MIME Type Column MIMETYPE Filename Column FILENAME Character Set Column BLOB Last Updated Column ATTCH_UPDATE
错误原因分析
错误出现在第5行v_blob BLOB := :P41_ATTACHMENT;,核心原因是:
- Oracle APEX中,当文件上传项配置为"BLOB column specified in Item Source attribute"时,绑定变量
:P41_ATTACHMENT返回的并非直接的BLOB对象,而是APEX_APPLICATION_FILES表中的文件ID(VARCHAR2类型) - 直接将VARCHAR2类型的文件ID赋值给BLOB类型变量,触发类型不匹配
解决步骤
方案1:直接使用绑定变量插入(推荐)
无需提前声明BLOB变量,直接在INSERT语句中引用:P41_ATTACHMENT,APEX会自动处理类型转换:
DECLARE v_part_number_list VARCHAR2(4000) := :P41_PART_NUMBER; v_invalid_part_numbers VARCHAR2(4000); -- Almacena valores no válidos v_part_number VARCHAR2(255); -- Almacena cada valor de la lista v_mimetype VARCHAR2(100) := :P41_MIMETYPE; -- Tipo MIME del archivo v_filename VARCHAR2(100) := :P41_FILENAME; -- Nombre del archivo v_last_updated TIMESTAMP := SYSTIMESTAMP; -- Fecha/Hora de la carga BEGIN -- 保留原有校验逻辑... -- 插入部分修改:直接使用:P41_ATTACHMENT IF :P41_ATTACHMENT IS NOT NULL THEN INSERT INTO QDL_SCRAP_REQUESTS ( REQ_ID, REQ_DATE, REQUESTOR, DISPOSAL_TYPE, PART_NUMBER, HU, STATUS, QTY, PPM, TE_MIN, COMMENTS, OVERDUE, QSB_APPROVED, APPROVAL_DATE, CLAIM_NUM, ATTACHMENT, MIMETYPE, FILENAME, ATTCH_UPDATE, QSP_APPROVAL_DATE ) VALUES ( QDL_SCRAP_REQUESTS_SEQ.NEXTVAL, TO_TIMESTAMP(:P41_RELOJ_EN_TIEMPO_REAL, 'DD/MM/YYYY HH24:MI:SS'), :P41_REQUESTOR, :P41_DISPOSAL_TYPE, :P41_PART_NUMBER, :P41_HU, 'yellow', :P41_QTY, :P41_PPM, :P41_TE_MIN, :P41_COMMENTS, 'N', NULL, NULL, :P41_CLAIM_NUM, :P41_ATTACHMENT, -- 直接引用绑定变量 v_mimetype, v_filename, v_last_updated, NULL ); ELSE -- 保留原有无文件插入逻辑... END IF; COMMIT; END;
方案2:通过文件ID查询BLOB(适合需提前处理文件内容的场景)
如果需要在插入前处理BLOB内容,可通过文件ID从APEX_APPLICATION_FILES中获取实际BLOB:
DECLARE v_part_number_list VARCHAR2(4000) := :P41_PART_NUMBER; v_invalid_part_numbers VARCHAR2(4000); v_part_number VARCHAR2(255); v_blob BLOB; -- 仅声明不初始化 v_mimetype VARCHAR2(100) := :P41_MIMETYPE; v_filename VARCHAR2(100) := :P41_FILENAME; v_last_updated TIMESTAMP := SYSTIMESTAMP; BEGIN -- 获取文件BLOB IF :P41_ATTACHMENT IS NOT NULL THEN SELECT blob_content INTO v_blob FROM apex_application_files WHERE name = :P41_ATTACHMENT; END IF; -- 保留原有校验和插入逻辑,插入时使用v_blob... END;
额外优化建议
- 替换
:P41_QTY和:P41_HU的正则校验为TO_NUMBER异常捕获,更符合Oracle类型处理规范:
BEGIN :P41_QTY := TO_NUMBER(:P41_QTY); EXCEPTION WHEN VALUE_ERROR THEN RAISE_APPLICATION_ERROR(-20004, 'Invalid Quantity (QTY): ' || :P41_QTY); END;
- 表中
QTY、HU为NUMBER类型,插入时直接传入:P41_QTY即可,无需额外格式校验
内容的提问来源于stack exchange,提问作者fesm
相关产品推荐
相关产品推荐

