【问题标题】:PL/SQL: ORA-00932: inconsistent datatypes: expected UDT got NUMBERPL/SQL:ORA-00932:不一致的数据类型:预期的 UDT 得到了 NUMBER
【发布时间】:2018-09-12 14:20:55
【问题描述】:

我正在执行 PL/SQL 代码以显示 Failed Reservation 表中的货币代码。使用对象类型和嵌套表集合。
运行 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;


为什么代码会产生这个错误?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您已将 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)。

    【讨论】:

      【解决方案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;
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 我没有注意到你在收集价值。使用bulk collect 进行操作。我已经修改了答案。
        【解决方案4】:

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

        如果你写类型表代替类型对象,你可能会得到这个错误 使用 BULK COLLECT INTO,我遇到了这个错误,因为我这样做了。

        例如:

        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;
        /
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-22
          • 2013-05-31
          • 2019-07-24
          • 2014-06-06
          相关资源
          最近更新 更多