[MS-SQL] order by_열이름 [열이름]이 불확실 합니다. - 문제해결
MS-SQL을 비롯한 모든 관계형 데이터 베이스에서
결과를 특정 컬럼으로 오름차순 또는 내림차순으로 정렬하는 것은
기본적이지만 대단히 중요한 기능이기도 하다.
MS-SQL을 자주 사용하는 사람이라면
오늘 얘기 하려고 하는 에러를 한 번 이상은 본 적이 있을 거라고 생각한다.
"열이름 [열이름]이 불확실 합니다."
이런 에러가 뜨는 것은 다양한 이유가 있긴 한데
대부분 이런 에러가 발생하는 경우는
중복되는 열 이름이 존재하는 둘 이상의 테이블을 조인(join)을 할 때
어떤 테이블의 컬럼인지 명시해 주지 않을 때라고 생각한다.
간단하게 다음과 같이
-- 지점 테이블
select *
from branch
-- 결과
branch_code branch_name branch_pnumber branch_address_1 branch_address_2
----------- -------------------- -------------- -------------------------------------------------- --------------------------------------------------
101 강남 11111 강남구 역삼동 테헤란로
102 명동 22222 중구 명동 아무아무길
103 수택동 33333 구리시 수택동 체육관로
104 명동2 22222 중구 회현 아무개아무개길
105 강남2 11111 역삼동 테헤란
-- 고객정보 테이블
select *
from cust_info
order by branch_code
-- 결과
branch_code cust_no contract_num1 cust_name cust_pnumber cust_address_1 cust_address_2
----------- ----------- ---------------- ------------------------------ ------------ -------------------------------------------------- --------------------------------------------------
101 1 1011010000000001 홍길동 11111 강남 헬로
101 2 1011010000000002 임꺽정 11111 강남 헬로2
102 1 1021020000000001 명동주민 22222 명동 백병
102 2 1021020000000002 이아무개 22222 명동 명동성당
103 1 1031030000000001 동대문구민 33333 동대문 평화시장
지점 테이블과 고객 테이블이 있고 두 테이블을 join할 때
두 테이블에 모두 존재하는 지점번호 branch_code를 명시하지 않을 경우 발생하는 것이다.
select branch_code, *
from branch b
join cust_info c
on b.branch_code = c.branch_code
-- 결과
메시지 209, 수준 16, 상태 1, 줄 10
열 이름 'branch_code'이(가) 불확실합니다.
select 에서 branch_code란 컬럼을 명시적으로 적었는데
이게 SQL서버는 branch테이블의 branch_code인지 cust_info 테이블의 branch_code 알 방도가 없으니
당연히 에러를 뱉어낼 수 밖에 없는 것이다.
뭐... 이 정도는 흔히들 경험하는 얘기고 납득할 만한 수준이니까 해결 방법은 따로 언급하진 않겠다.
오늘 할 얘기는 이거랑은 좀 다른 얘기인데 테이블 join이 없을 경우에도 [열 이름]이 불확실 하다는 에러를 만날수 있다.
어떤 경우냐
아까 위에서 예를 들었던 cust_info 테이블을 예로 들어 보겠다.
-- 고객정보 테이블
select *
from cust_info
order by branch_code
-- 결과
branch_code cust_no contract_num1 cust_name cust_pnumber cust_address_1 cust_address_2
----------- ----------- ---------------- ------------------------------ ------------ -------------------------------------------------- --------------------------------------------------
101 1 1011010000000001 홍길동 11111 강남 헬로
101 2 1011010000000002 임꺽정 11111 강남 헬로2
102 1 1021020000000001 명동주민 22222 명동 백병
102 2 1021020000000002 이아무개 22222 명동 명동성당
103 1 1031030000000001 동대문구민 33333 동대문 평화시장
단순히 테이블 전체를 select하면 다음과 같은 결과를 볼 수가 있다.
그런데 다음과 같이 쿼리를 작성하게 되면?
-- 고객정보 테이블
select branch_code, *
from cust_info
order by branch_code
-- 결과
메시지 209, 수준 16, 상태 1, 줄 4
열 이름 'branch_code'이(가) 불확실합니다.
응?
에러가 발생하지 않은 첫 번째 쿼리와 두 번째 쿼리의 차이점은 무엇일까?
힌트는 order by 인데
참고로 이 에러는 MS-SQL 2005보다 과거버전인 MS-SQL 2000까지는 발생하지 않았던 에러이다.
간단히 말해서 이 에러의 원인은 order by 때문이다.
MS-SQL 2005 부터 그 이전버전에서 모호하게 사용했던 order by 를 좀 더 명확하게 구분을 시작했기 때문이다.
다시 첫 번째 쿼리와 두 번째 쿼리를 자세히 보기 바란다.
첫 번째 쿼리에서는 select 에서 모든 컬럼을 전부 불러오도록 했고
두 번째 쿼리에서는 select 에서 branch_code란 컬럼을 명시적으로 적은 후 모든 컬럼을 불러오도록 하면서
둘 다 order by에서 branch_code로 정렬을 하라고 명령을 내리고 있다.
결국 이 부분에서 SQL서버는 어떤 branch_code로 정렬을 해야 하는지에 대한 판단을 내리지 못하고
사용자에게 불확실 오류코드는 반환하며 다시 물어보게 되는 것이다.
따라서 이 문제를 올바르게 해결하기 위해서는 order by 구문에서 어떤 branch_code인지를 명시해 줄 필요가 있다.
-- 고객정보 테이블
select branch_code, *
from cust_info
order by cust_info.branch_code
--결과
branch_code branch_code cust_no contract_num1 cust_name cust_pnumber cust_address_1 cust_address_2
----------- ----------- ----------- ---------------- ------------------------------ ------------ -------------------------------------------------- --------------------------------------------------
101 101 1 1011010000000001 홍길동 11111 강남 헬로
101 101 2 1011010000000002 임꺽정 11111 강남 헬로2
102 102 1 1021020000000001 명동주민 22222 명동 백병
102 102 2 1021020000000002 이아무개 22222 명동 명동성당
103 103 1 1031030000000001 동대문구민 33333 동대문 평화시장
이런 식으로....
물론 사람이 봤을 땐 이게 뭔가 싶고 왜 이런 불편함을 주는가 싶겠지만
데이터베이스라는 것은 데이터의 일관성을 가지는 것이 굉장히 중요한 일이다.
데이터의 일관성이 조금이라도 깨져버린다면 해당 데이터베이스를 신뢰할 수 있을까?
다시 한 번 사람의 입장이 아니라 SQL서버의 입장에서 order by 절의 branch_code를 보도록 하자.
-- 고객정보 테이블
select branch_code, *
from cust_info
order by branch_code
-- 결과
메시지 209, 수준 16, 상태 1, 줄 4
열 이름 'branch_code'이(가) 불확실합니다.
order by 의 branch_code는 select절에서 명시한 branch_code일까 아니면 "*" 에 속해있는 branch_code인 것일까
SQL서버의 입장에서 각각의 branch_code는 정말 같은 컬럼인가?
예시는 아주 단순하게 하나의 테이블을 사용한 쿼리를 사용했지만 좀 더 복잡한 쿼리에서 위 에러가 발생한다면?
오류는 단순했지만 앞으로 고민 할 여지를 많이 남기는 오류인 듯 하다.