Search code examples
oracle-databasetypesplsqlvarcharvarchar2

PL/SQL Compilation error - PLS-00382: expression is of wrong type


I'm running the below PL/SQL...

DECLARE
BEGIN 
FOR i IN (select VALUE from REWARDS)
LOOP 
insert into BT_CMS.T_REWARDS_TYPES 
(ID, REWARD_LABEL, REWARD_VALUE, REWARD_METHOD, UPDATE_USER, UPDATE_DATE, PAYMENT_PROVIDER_ID, CREATE_DATE, COUNTRY_CODE_ID) 
values 
(BT_CMS.SEQ_REWARD_TYPE_ID.nextval, 'R' || i || ' Real Time', i, 'Airtime', 'DEVOPS-826', sysdate, 120, sysdate, 206); 
END LOOP; 
END;

... and getting the error below...

ORA-06550: line 8, column 72:
PLS-00382: expression is of wrong type
ORA-06550: line 8, column 52:
PLS-00382: expression is of wrong type
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.

I'm fairly sure the issue is with the i being substituted into the values but I don't know what exactly is the issue. The VALUE column in the REWARDS table that i is being selected as has data_type = VARCHAR2(20 BYTE). The REWARD_LABEL column that I'm trying to insert it into has data_type = VARCHAR2(50 CHAR).


Solution

  • Inside the loop, i refers to the whole record, not to the (unique) field of the record; you need to use i.value instead of i:

    DECLARE
    BEGIN
        FOR i IN (SELECT VALUE FROM REWARDS)
        LOOP
            INSERT INTO BT_CMS.T_REWARDS_TYPES(
                                               ID,
                                               REWARD_LABEL,
                                               REWARD_VALUE,
                                               REWARD_METHOD,
                                               UPDATE_USER,
                                               UPDATE_DATE,
                                               PAYMENT_PROVIDER_ID,
                                               CREATE_DATE,
                                               COUNTRY_CODE_ID
                                              )
                 VALUES (
                         BT_CMS.SEQ_REWARD_TYPE_ID.NEXTVAL,
                         'R' || i.VALUE || ' Real Time',
                         i.VALUE,
                         'Airtime',
                         'DEVOPS-826',
                         SYSDATE,
                         120,
                         SYSDATE,
                         206
                        );
        END LOOP;
    END;
    

    A better approach could be using a single insert-select instead of looping through a cursor; for example:

    INSERT INTO BT_CMS.T_REWARDS_TYPES(
                                       ID,
                                       REWARD_LABEL,
                                       REWARD_VALUE,
                                       REWARD_METHOD,
                                       UPDATE_USER,
                                       UPDATE_DATE,
                                       PAYMENT_PROVIDER_ID,
                                       CREATE_DATE,
                                       COUNTRY_CODE_ID
                                      )
        SELECT BT_CMS.SEQ_REWARD_TYPE_ID.NEXTVAL,
               'R' || r.VALUE || ' Real Time',
               r.VALUE,
               'Airtime',
               'DEVOPS-826',
               SYSDATE,
               120,
               SYSDATE,
               206
          FROM REWARDS r