PL / SQL:ORA-00932:不一致的数据类型:预期的UDT得到NUMBER

时间:2016-03-07 11:32:46

标签: oracle plsql

我正在执行PL / SQL代码以显示失败预订表中的货币代码。使用对象类型和嵌套表集合。
运行PL / SQL代码时,会生成以下错误。相应的行在PL / SQL代码部分中突出显示。

错误报告:

ORA-06550: line 27, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBER
ORA-06550: line 27, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:


代码粘贴在下面:

DDL - 创建表格

CREATE TABLE FAILEDRESERVATION
(   
    FAILEDRESERVATIONID NUMBER(18,0), 
    FK_TRANSACTIONID NUMBER(18,0), 
    DEBITRESERVATIONID NUMBER(18,0), 
    RESERVATIONTIME DATE, 
    RESERVATIONAMOUNT NUMBER(18,5), 
    CURRENCYCODE CHAR(3 BYTE), 
    AVAILABLEAMOUNT NUMBER(18,5)
);

ALTER TABLE FAILEDRESERVATION 
ADD CONSTRAINT "PK_FAILEDRESERVATION" PRIMARY KEY ("FAILEDRESERVATIONID");


对象类型:

CREATE OR REPLACE TYPE TYPE type_failedreservation AS OBJECT 
(                                     
    FK_TRANSACTIONID     NUMBER(18),    
    DEBITRESERVATIONID   NUMBER(18),    
    RESERVATIONTIME      DATE,          
    RESERVATIONAMOUNT    NUMBER(18,5),  
    CURRENCYCODE         CHAR(3),       
    AVAILABLEAMOUNT      NUMBER(18,5)   
);     


DML:

INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT) 
VALUES (289,2,1,to_date('07-MAR-16','DD-MON-RR'),20000,'USD',10000);

INSERT INTO FAILEDRESERVATION (FAILEDRESERVATIONID,FK_TRANSACTIONID,DEBITRESERVATIONID,RESERVATIONTIME,RESERVATIONAMOUNT,CURRENCYCODE,AVAILABLEAMOUNT) 
VALUES (288,1,1,to_date('01-MAR-16','DD-MON-RR'),10000,'NOK',10000);


嵌套表:

CREATE OR REPLACE TYPE type_failedreservation_coll as TABLE OF type_failedreservation; 

CREATE OR REPLACE TYPE type_dbtrsid_coll AS TABLE OF NUMBER;


PL / SQL代码:

DECLARE    
    P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;

    vdbtid_coll type_dbtrsid_coll := type_dbtrsid_coll();

BEGIN    
    SELECT TYPE_FAILEDRESERVATION(fk_transactionid,debitreservationid,reservationtime,reservationamount,currencycode,availableamount) 
    BULK COLLECT 
    INTO p_failedreservation                                                                                                     
    FROM failedreservation;

    -- This is line 27
    SELECT frs.debitreservationid
    INTO vdbtid_coll
    FROM TABLE(p_failedreservation) frs;


    FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST  
    LOOP
        dbms_output.put_line('The currency code is: '||v_iterate);  
    END LOOP;

END;


为什么代码会产生此错误?

4 个答案:

答案 0 :(得分:4)

您已将vdbtid_coll声明为收集类型,因此您还需要批量收集:

SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;

随着这一变化:

PL/SQL procedure successfully completed.
The currency code is: 1
The currency code is: 2

虽然这只是给你收藏中的索引编号,所以我不认为这是你真正想要的。你可能想要:

FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST  
LOOP
    dbms_output.put_line('The currency code is: '
        || p_failedreservation(v_iterate).currencycode);  
END LOOP;

得到:

PL/SQL procedure successfully completed.
The currency code is: USD
The currency code is: NOK

你根本不需要第二个选择/收藏,你可以这样做:

FOR v_iterate IN 1..p_failedreservation.COUNT
LOOP
    dbms_output.put_line('The currency code is: '
        || p_failedreservation(v_iterate).currencycode);  
END LOOP;

...得到相同的结果。虽然我不确定debitreservationid在第二个查询中的相关性,因为它在两行中都是相同的值(1)。

答案 1 :(得分:2)

您正尝试在集合中选择多行。您需要使用BULK COLLECT INTO而不仅仅是INTO

更改

SELECT frs.debitreservationid
INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;

SELECT frs.debitreservationid
BULK COLLECT INTO vdbtid_coll
FROM TABLE(p_failedreservation) frs;

你可能希望输出为:

FOR v_iterate IN vdbtid_coll.FIRST..vdbtid_coll.LAST LOOP
  dbms_output.put_line('The currency code is: '|| vdbtid_coll(v_iterate) );
END LOOP;

但是,您可以将其全部简化为:

DECLARE    
    P_FAILEDRESERVATION APPDATA.TYPE_FAILEDRESERVATION_COLL;
BEGIN    
  SELECT TYPE_FAILEDRESERVATION(
           fk_transactionid,
           debitreservationid,
           reservationtime,
           reservationamount,
           currencycode,
           availableamount
         ) 
  BULK COLLECT INTO p_failedreservation
  FROM failedreservation;

  FOR v_iterate IN p_failedreservation.FIRST .. p_failedreservation.LAST LOOP
    dbms_output.put_line(
      'The currency code is: '|| p_failedreservation(v_iterate).currencycode
    );
  END LOOP;
END;

答案 2 :(得分:1)

尝试将类型数组转换为其类型,如下所示

SELECT frs.debitreservationid
  BULK COLLECT INTO vdbtid_coll
  FROM TABLE(CAST(p_failedreservation as APPDATA.TYPE_FAILEDRESERVATION_COLL)) frs;

答案 3 :(得分:0)

PL / SQL:ORA-00932:数据类型不一致:预期的UDT得到了CHAR

如果在以下情况下写类型表代替类型对象,则可能会出现此错误: 使用批量收集进入,我遇到了这个错误,因为我这样做了。

例如:

CREATE OR REPLACE TYPE OBJ_TYPE AS OBJECT (NAME VARCHAR2(20));
/

CREATE OR REPLACE TYPE TBL_TYPE IS TABLE OF OBJ_TYPE;
/

CREATE OR REPLACE FUNCTION FUNC1 RETURN TBL_TYPE AS
TBL_TEXT TBL_TYPE := TBL_TYPE();
BEGIN
SELECT ***OBJ_TYPE*** (NAME) BULK COLLECT INTO ***TBL_TEXT*** FROM <table-name> ;
RETURN ***TBL_TEXT***;
END;
/

在函数中使用对象类型和表类型时应格外小心。