PL/SQL을 다루다 보면 가끔 PLS-00382: expression is of wrong type 오류를 마주할 수 있어요. 이 오류는 주로 서로 다른 타입의 변수를 섞어 사용하거나, 데이터를 복사하려고 할 때 발생합니다. 특히, 레코드 타입을 활용할 때 이 문제가 자주 발생하지요.
오늘은 오류의 원인과 해결 방법을 알아보겠습니다.
PLS-00382 오류 원인: 타입 불일치
PL/SQL에서는 동일한 구조를 가진 레코드 타입이라도 정의된 위치나 이름이 다르면 서로 다른 타입으로 간주합니다. 예를 들어, 두 개의 레코드 타입을 정의했다고 가정해 봅시다.
DECLARE
TYPE emp_rec1 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
TYPE emp_rec2 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
emp_var1 emp_rec1;
emp_var2 emp_rec2;
BEGIN
emp_var2.empno := 1001;
emp_var2.ename := 'John';
emp_var2.sal := 3000;
emp_var1 := emp_var2; -- 여기서 오류 발생!
END;
/
emp_var1 := emp_var2; -- 여기서 오류 발생!
*
ERROR at line 10:
ORA-06550: line 10, column 15:
PLS-00382: expression is of wrong type
ORA-06550: line 10, column 3:
PL/SQL: Statement ignored
위 코드에서 emp_rec1과 emp_rec2는 구조적으로 동일해 보이지만, PL/SQL은 서로 다른 타입으로 간주합니다. 따라서 두 변수 간 데이터를 바로 복사하려고 하면 PLS-00382: expression is of wrong type 오류가 발생해요.
PLS-00382 해결 방법: 상황에 맞는 접근법
1. 필드 단위로 복사하기
가장 간단한 방법은 각 필드를 개별적으로 복사하는 것입니다.
DECLARE
TYPE emp_rec1 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
TYPE emp_rec2 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
emp_var1 emp_rec1;
emp_var2 emp_rec2;
BEGIN
-- emp_var2 초기화
emp_var2.empno := 1001;
emp_var2.ename := 'John';
emp_var2.sal := 3000;
-- 필드별로 데이터 복사
emp_var1.empno := emp_var2.empno;
emp_var1.ename := emp_var2.ename;
emp_var1.sal := emp_var2.sal;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_var1.ename || ', Salary: ' || emp_var1.sal);
END;
/
이 방법은 간단하고 명확하지만, 필드가 많아질수록 번거로울 수 있어요.
2. 공통 레코드 타입 선언
만약 두 레코드 타입이 동일한 구조를 가지고 있다면, 공통 타입을 선언하여 이를 공유하는 것을 가장 자주 사용하는 편이에요.
DECLARE
TYPE emp_rec IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
emp_var1 emp_rec;
emp_var2 emp_rec;
BEGIN
-- emp_var2 초기화
emp_var2.empno := 1001;
emp_var2.ename := 'John';
emp_var2.sal := 3000;
-- 바로 복사 가능
emp_var1 := emp_var2;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_var1.ename || ', Salary: ' || emp_var1.sal);
END;
/
공통 타입을 선언하면 구조가 변경되더라도 유지보수가 쉽고, 타입 간 호환성 문제가 사라집니다.
3. SUBTYPE 활용
기존 레코드 타입을 확장하여 '서브타입'으로 정의하는 방법입니다. 다른 개발언어의 상속과 비슷한 개념이지요.
DECLARE
TYPE emp_rec IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
SUBTYPE emp_rec_sub IS emp_rec;
emp_var1 emp_rec;
emp_var2 emp_rec_sub;
BEGIN
-- emp_rec_sub 타입 변수 초기화
emp_var2.empno := 1001;
emp_var2.ename := 'John';
emp_var2.sal := 3000;
-- 타입 간 복사 가능
emp_var1 := emp_var2;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_var1.ename || ', Salary: ' || emp_var1.sal);
END;
/
SUBTYPE을 사용하면 기존 타입을 재활용하면서도 별도의 하위 타입을 정의할 수 있어요.
4. SQL SELECT INTO를 활용한 데이터 변환
PL/SQL에서 직접적인 타입 변환은 지원하지 않지만, SQL 문을 통해 데이터를 변환할 수 있습니다. 이 방법은 복잡한 변환 작업에서 유용할 수 있어요.
DECLARE
TYPE emp_rec1 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
TYPE emp_rec2 IS RECORD (empno NUMBER, ename VARCHAR2(50), sal NUMBER);
emp_var1 emp_rec1;
emp_var2 emp_rec2;
BEGIN
-- emp_var2 초기화
emp_var2.empno := 1001;
emp_var2.ename := 'John';
emp_var2.sal := 3000;
-- SQL 문을 통해 필드 변환
SELECT emp_var2.empno, emp_var2.ename, emp_var2.sal
INTO emp_var1.empno, emp_var1.ename, emp_var1.sal
FROM DUAL;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_var1.ename || ', Salary: ' || emp_var1.sal);
END;
/
이 방법은 데이터베이스 작업과 통합된 복잡한 로직에서 적합하지만, 단순한 상황에서는 비효율적일 수 있어요.
요약
PLS-00382 오류는 타입 간 호환성 문제로 발생하지만, 다양한 방법으로 해결할 수 있습니다. 사용 사례에 따라 다음을 선택하세요.
- 필드 단위 복사: 단순한 코드에서 빠르게 적용 가능.
- 공통 레코드 타입: 동일한 구조의 타입을 여러 곳에서 사용하는 경우 적합.
- SUBTYPE: 기존 타입을 확장해야 하는 경우 적합.
- SQL 변환: 데이터 변환이 복잡하거나 SQL과의 통합 작업이 필요한 경우 활용.
이 중 공통 레코드 타입 선언이 가장 일반적이고 유지보수 측면에서도 효율적입니다. 😊
