자바에서의 전역변수 지역변수와 같이 오라클도 전역변수 지역변수 개념이 존재한다
정확히는 테이블 유효 수명 및 테이블 별칭 사용법인데 선언한 테이블과 별칭이 어디까지 유효하냐이다
오라클에서
전역테이블은 서브쿼리 밖에서 선언된 테이블이고
지역테이블은 서브쿼리 내에서 선언된 테이블이다
별칭도 마찬가지이다
다만 이 개념은 FROM, JOIN절에서는 존재하지 않는다
구문처리 순서가 다르기 때문
먼저 정리해두면
조건식과 같은
JOIN절의 ON에서 선언된 서브쿼리, FROM절의 WHERE에서 선언된 서브쿼리
안에서는 전역테이블 지역테이블 개념이 통하고
(서브쿼리 밖에서 선언된 테이블도 서브쿼리 내에서 사용 가능)
테이블을 선언하는
JOIN에서 선언된 서브쿼리, FROM에서 선언된 서브쿼리는
전역테이블 지역테이블 개념이 통하지 않는다
(이때는 서브쿼리 내에서 선언된 테이블만 사용 가능)
이러한 이유는 오라클 및 다른 데이터베이스는
SQL문을 분석할때
SQL작성 순서대로 해독하는 것이아닌
#전체 SQL에서 FROM, JOIN절부터 분석후
WHERE, ON절을 분석하기 때문에
테이블을 작성하는 곳에 선언된 서브쿼리는 서브쿼리 내에서 선언된 테이블만 사용 가능하고
조건을 작성하는 곳에서 선언된 서브쿼리는 서브쿼리 밖에서 선언된 테이블도 사용 가능 하다
(FROM, JOIN절의 분석이 끝나 테이블을 인식하고 있는 레벨 이기 때문에)
#SQL은 위에서부터 한줄한줄 분석하는 C언어나 PHP같은 인터프리터가 아닌
JAVA처럼 파일 전체를 분석하고 컴파일 개념이라고 보면 된다
#정리하자면 코드 작성 순서와 상관없이
처리 순서는 FROM, JOIN > WHERE, ON > GROUP BY > ORDER BY 순서이다
SQL에 있는 모든 FROM과 JOIN이 동시에 일괄 처리 된후
다음 WHERE, ON조건식이 동시에 일괄 처리된다고 보면 된다
SELECT
T1.BOARDNUM,
T1.BOARDID,
T1.TITLE,
T1.CONTENT,
T1.INSERTID,
T1.COMMENTCOUNT,
T1.READCOUNT
FROM
FREEBOARD T1-----전역테이블
LEFT OUTER JOIN
ITBOARD T2-----전역테이블
ON
T2.BOARDNUM = T1.BOARDNUM ---- 전역변수는 어디서든 사용 가능하다 O
AND T2.BOARDID = T3.BOARDID ----- 지역변수는 서브쿼리를 벗어나면 선언이 불가능함 X
AND T2.INSERTID = (SELECT ----- 서브쿼리
T3.INSERTID
FROM
EMPTYBOARD T3----------지역 변수( 서브쿼리내 테이블 및 별칭은 지역변수 취급)
WHERE
T1.BOARDNUM = T2.BOARDNUM ------ 전역변수명은 서브쿼리 내에서 사용가능 O
AND T3.BOARDID = T2.BOARDID ----- 서브쿼리 내에서 지역변수와 전역변수 비교 O
전역테이블인 FREEBOARD T1, ITBOARD T2은 QUERY문이 끝날때 까지 유효하지만
서브쿼리 내 선언된 EMPTYBOARD T3 테이블은 서브쿼리가 끝나면 사라진다
SELECT
T1.BOARDNUM,
T1.BOARDID,
T1.TITLE,
T1.CONTENT,
T1.INSERTID,
T1.COMMENTCOUNT,
T1.READCOUNT
FROM
FREEBOARD T1-----전역테이블
LEFT OUTER JOIN
ITBOARD T2-----전역테이블
ON
T2.BOARDNUM = T1.BOARDNUM ---- 전역테이블은 어디서든 사용 가능하다 O
AND T2.BOARDID = (SELECT ----- 서브쿼리
T3.INSERTID
FROM
EMPTYBOARD T3---------- 서브쿼리내 테이블 및 별칭은 지역변수 취급이라 서브쿼리가 끝나면 사라짐
WHERE
T1.BOARDNUM = T2.BOARDNUM
AND T3.BOARDID = T2.BOARDID)
AND T2.INSERTID = (SELECT ----- 서브쿼리
T3.INSERTID
FROM
EMPTYBOARD T3---------- EMPTYBOARD테이블 및 T3별칭은 서브쿼리가 끝나면서 사라져서 재사용 가능
WHERE
T1.BOARDNUM = T2.BOARDNUM
AND T3.BOARDID = T2.BOARDID)
이러한 식으로 서브쿼리내 선언된 테이블 및 별칭은 서브쿼리가 끝나면 사라지므로
다시 재사용 해서 사용가능하다
위에서 설명 했듯이 예외 적인 경우가 있는데
JOIN, FROM 작성된 서브쿼리 안에서는 밖에서 작성한 테이블을 사용할 수 없다
데이터 베이스의 관점에서 보면 FROM, JOIN을 동등한 레벨에서 먼저 분석하기 때문에
JOIN의 서브쿼리의 관점에서는 FROM절의 테이블이 있는지 모르는 상태이다
SELECT
T1.BOARDNUM,
T1.BOARDID,
T1.TITLE,
T1.CONTENT,
T1.INSERTID,
T1.COMMENTCOUNT,
T1.READCOUNT
FROM
FREEBOARD T1-----전역테이블
LEFT OUTER JOIN
(SELECT ----- 서브쿼리
T3.INSERTID
FROM
EMPTYBOARD T3
WHERE
T1.BOARDNUM = T2.BOARDNUM ------ JOIN절에서 작성한 서브쿼리는 서브쿼리 밖에서 작성한 테이블 사용 불가 X
AND T3.BOARDID = T2.BOARDID ----- 위와 마찬가지 X
) SQ
또한 메인 테이블에 별칭을 부여해야할 때가 있다
아래처럼 서브쿼리와 메인쿼리의 테이블이 같을경우
지역 테이블은 서브쿼리가 끝나면 사라지지만 전역 테이블은 서브쿼리 안에서도 사용 가능하므로
서브쿼리 내에서 조건비교를 할경우 컬럼명이 같아져서 테이블 구분이 되지않아 에러가 발생한다
SELECT
BOARDNUM,
BOARDID,
TITLE,
CONTENT,
INSERTID,
COMMENTCOUNT,
READCOUNT
FROM
FREEBOARD -----전역 테이블
INNER JOIN
(SELECT
BOARDNUM,
BOARDID,
TITLE,
CONTENT,
INSERTID,
SUM(READCOUNT) AS READCOUNT_MAX,
FROM
FREEBOARD -- 지역 테이블
WHERE
COMMENTCOUNT >= 10
AND INSERTID = INSERTID --에러, 전역테이블과 지역테이블 구분이 안됨
) SQ
ON
READCOUNT > SQ.READCOUNT_MAX --에러
아래와 같이 메인테이블에 별칭을 부여하면 중복 문제가 해결된다
SELECT
M.BOARDNUM,
M.BOARDID,
M.TITLE,
M.CONTENT,
M.INSERTID,
M.COMMENTCOUNT,
M.READCOUNT
FROM
FREEBOARD M-----전역 테이블 별칭 선언
INNER JOIN
(SELECT
BOARDNUM,
BOARDID,
TITLE,
CONTENT,
INSERTID,
SUM(READCOUNT) AS READCOUNT_MAX,
FROM
FREEBOARD -- 지역 테이블
WHERE
COMMENTCOUNT >= 10
AND M.INSERTID = INSERTID -- 해결
) SQ
ON
M.READCOUNT > SQ.READCOUNT_MAX -- 해결
'DB > Oracle' 카테고리의 다른 글
[ORACLE] CASE문 (0) | 2020.10.22 |
---|---|
[ORACLE] 연산자 및 내장함수 사용시 주의 점 (0) | 2020.10.14 |
[ORACLE] 문자 관련 함수 (0) | 2020.10.06 |
[ORACLE] 숫자 관련 함수 (0) | 2020.10.06 |
[ORACLE] 데이터타입 변환 (TO_CHAR, TO_NUMBER) (0) | 2020.10.06 |