ORA-01427: 단일 행 하위 질의에 2개 이상의 행이 리턴되었습니다. (ORA-01427: single-row subquery returns more than one row) 오류를 해결하는 방법에 대해 안내해드리겠습니다.
해당 오류의 핵심은 스칼라 서브쿼리랍니다. 스칼라 서브쿼리를 통해 가져오는 컬럼은 그 결과가 반드시 하나의 행을 가져와야 합니다.
그런데 서브쿼리가 고유한 값을 보장하지 않는 경우에 해당과 같은 예외가 발생할 수 있습니다. 참고로 '스칼라' 라는 단어의 의미 자체가 하나의 숫자로만 표시되는 양을 뜻하는 단어랍니다. "스칼라 서브쿼리는 왜 하나의 결과만 가져와야 하나요?"라고 물어보시면 안 돼요. 😭 "하나는 왜 하나입니까?" 와 같은 질문을 하는 것이기 때문이지요~
이때 단일행을 획득하기 위해 다음과 같은 방법을 생각할 수 있습니다. 예시에서 사용하는 테이블은 총 2개이며 각각 EMP(PK: EMPNO)와 DEPT(PK: DEPTNO)입니다. 이제부터 해결 방법에 대해 알려드리겠습니다.
프라이머리 키를 활용하기
키값을 이용하여 단일 행을 획득하는 방법입니다. 기본키 DEPTNO를 이용하여 단일 행 하위 질의에 1개 값을 리턴하도록 합니다.
SELECT (SELECT DNAME
FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO) DEPTDNAME,
EMP.*
FROM EMP
유니크 인덱스의 컬럼을 이용하기
유니크 인덱스 또한 오라클에서 로우의 유일성을 보장하는 방법이기 때문에 인덱스 대상 컬럼을 조건으로 하는 것도 단일 행 하위 질의에 반드시 1개의 결과를 얻도록 할 수 있습니다. 예시에서는 DEPTNO가 기본키이므로 동일하게 적용할 수 있습니다.
ROWNUM = 1 조건 추가하기
중복된 값이 많아서 어떠한 값을 가져와도 값이 같다면 ROWNUM = 1 과 같은 간단한 서브쿼리 조건을 추가하는 방법으로 하위 질의에 2개를 예방하는 것입니다. 정확한 값을 가져와야 하는 곳에는 사용하기 힘들지만 반대로 참고할만한 어느 하나의 값을 가져와도 문제가 없다면 해당 조건을 추가하는 것만으로도 ORA-01427 문제를 해결할 수 있습니다.
ROW_NUMBER OVER, MIN 등의 특정 조건을 부여하기
ROW_NUMBER, RANK 등 순위함수를 통한 방법입니다. ROWNUM과 비슷하게 이용할 수 있는 방법입니다.
DEPT 의 데이터를 조건 없이 모두 가져오는 경우를 예시로 생각해 봅시다!
테이블에 행이 2개 이상인 경우는 오류가 나올 것입니다.
외래 키 DEPTNO 를 활용하여 서브쿼리 오류를 수정한 예시입니다.
SELECT EMPNO,
-- (SELECT LOC
-- FROM DEPT
-- WHERE DEPTNO = DEPTNO),
(SELECT LOC
FROM DEPT
WHERE DEPTNO = EMP.DEPTNO),
ENAME,
DEPTNO
FROM EMP