본문 바로가기

Database/Oracle

[Oracle] and system_cd(+) = 'COM' 과 같이 상수값 비교 조건에도 (+)가 붙는 이유

Oracle의 옛날 조인 문법(= “오라클 전용 OUTER JOIN 문법”) 에서 (+)를 사용하는 경우,
AND 절의 모든 조건이 "조인 대상 테이블" 기준으로 일관되게 처리되어야 하기 때문입니다.

🔹배경 설명

예를 들어 아래와 같은 쿼리가 있다고 합시다:

SELECT a.user_id, b.system_cd
FROM user_info a, system_info b
WHERE a.user_id = b.user_id(+)
AND b.system_cd(+) = 'COM';
 

🔹 (+)의 의미

(+)는 해당 테이블이 OUTER JOIN의 “부수적인 테이블” 이라는 뜻입니다.
즉, b 테이블이 없어도 a의 데이터는 모두 나오게 하라는 의미죠.

🔹 그런데 왜 상수 조건에도 (+)가 붙을까?

Oracle의 구식 (+) 문법에서는,
조인 조건뿐 아니라 그 조인에 포함된 모든 조건에서
조인 방향(어느 쪽이 outer냐)을 일관되게 표시해야 합니다.

그렇지 않으면 Oracle이 이렇게 이해합니다:

“b.system_cd = 'COM' 조건은 조인 후 필터 조건으로 봐야겠군.
즉, b가 없으면 NULL인데, NULL = 'COM'은 false니까
결국 outer join이 무의미해지네.”

즉, (+)를 빼면 사실상 inner join처럼 동작하게 되어
조인 결과에서 NULL 행(즉, 매칭 안 된 a의 데이터)이 사라집니다.

🔹 비교 예시

(1) (+) 안 붙은 경우 → inner join처럼 됨

SELECT a.user_id, b.system_cd
FROM user_info a, system_info b
WHERE a.user_id = b.user_id(+)
AND b.system_cd = 'COM';

→ b.system_cd = 'COM'은 매칭된 행만 남기므로,
b가 없는 a 행은 제외됨 → 실질적으로 inner join

(2) (+) 붙은 경우 → 진짜 outer join 유지

SELECT a.user_id, b.system_cd
FROM user_info a, system_info b
WHERE a.user_id = b.user_id(+)
AND b.system_cd(+) = 'COM';

→ b가 없어도 a의 행은 유지됨
(이때 b.system_cd는 NULL로 표시됨)

🔹 결론

AND b.system_cd(+) = 'COM' 처럼 상수 비교에도 (+)를 붙이는 이유는:

해당 조건이 outer join의 한쪽 테이블(b)에 속하는 조건임을 명시하여,
outer join의 의미(= NULL 허용)를 유지하기 위해서입니다.


✅ 참고 (추천 방식)

이 구식 (+) 문법은 이제 표준 SQL JOIN 문법으로 대체하는 것이 좋습니다:

SELECT a.user_id, b.system_cd
FROM user_info a
LEFT JOIN system_info b
  ON a.user_id = b.user_id
 AND b.system_cd = 'COM';
 

이 방식에서는 b.system_cd = 'COM' 조건이 자연스럽게
조인 조건(on절) 에 포함되므로, (+)를 붙일 필요가 없습니다.

 

 

✅ 오라클 방식의 Join에서 상수값 비교에 (+)를 하는 경우

Employees 테이블 전체 행 (PK: EMPLOYEE_ID, FK: DEPARTMENT_ID)

 - 88번 row는 department_id가 null

NO EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL DEPARTMENT_ID
1 198 Donald OConnell DOCONNEL 50
2 199 Douglas Grant DGRANT 50
3 200 Jennifer Whalen JWHALEN 10
4 201 Michael Hartstein MHARTSTE 20
5 202 Pat Fay PFAY 20
6 203 Susan Mavris SMAVRIS 40
7 204 Hermann Baer HBAER 70
8 205 Shelley Higgins SHIGGINS 110
9 206 William Gietz WGIETZ 110
10 100 Steven King SKING 90
11 101 Neena Kochhar NKOCHHAR 90
12 102 Lex De Haan LDEHAAN 90
13 103 Alexander Hunold AHUNOLD 60
14 104 Bruce Ernst BERNST 60
15 105 David Austin DAUSTIN 60
16 106 Valli Pataballa VPATABAL 60
17 107 Diana Lorentz DLORENTZ 60
18 108 Nancy Greenberg NGREENBE 100
19 109 Daniel Faviet DFAVIET 100
20 110 John Chen JCHEN 100
21 111 Ismael Sciarra ISCIARRA 100
22 112 Jose Manuel Urman JMURMAN 100
23 113 Luis Popp LPOPP 100
24 114 Den Raphaely DRAPHEAL 30
25 115 Alexander Khoo AKHOO 30
26 116 Shelli Baida SBAIDA 30
27 117 Sigal Tobias STOBIAS 30
28 118 Guy Himuro GHIMURO 30
29 119 Karen Colmenares KCOLMENA 30
30 120 Matthew Weiss MWEISS 50
31 121 Adam Fripp AFRIPP 50
32 122 Payam Kaufling PKAUFLIN 50
33 123 Shanta Vollman SVOLLMAN 50
34 124 Kevin Mourgos KMOURGOS 50
35 125 Julia Nayer JNAYER 50
36 126 Irene Mikkilineni IMIKKILI 50
37 127 James Landry JLANDRY 50
38 128 Steven Markle SMARKLE 50
39 129 Laura Bissot LBISSOT 50
40 130 Mozhe Atkinson MATKINSO 50
41 131 James Marlow JAMRLOW 50
42 132 TJ Olson TJOLSON 50
43 133 Jason Mallin JMALLIN 50
44 134 Michael Rogers MROGERS 50
45 135 Ki Gee KGEE 50
46 136 Hazel Philtanker HPHILTAN 50
47 137 Renske Ladwig RLADWIG 50
48 138 Stephen Stiles SSTILES 50
49 139 John Seo JSEO 50
50 140 Joshua Patel JPATEL 50
51 141 Trenna Rajs TRAJS 50
52 142 Curtis Davies CDAVIES 50
53 143 Randall Matos RMATOS 50
54 144 Peter Vargas PVARGAS 50
55 145 John Russell JRUSSEL 80
56 146 Karen Partners KPARTNER 80
57 147 Alberto Errazuriz AERRAZUR 80
58 148 Gerald Cambrault GCAMBRAU 80
59 149 Eleni Zlotkey EZLOTKEY 80
60 150 Peter Tucker PTUCKER 80
61 151 David Bernstein DBERNSTE 80
62 152 Peter Hall PHALL 80
63 153 Christopher Olsen COLSEN 80
64 154 Nanette Cambrault NCAMBRAU 80
65 155 Oliver Tuvault OTUVAULT 80
66 156 Janette King JKING 80
67 157 Patrick Sully PSULLY 80
68 158 Allan McEwen AMCEWEN 80
69 159 Lindsey Smith LSMITH 80
70 160 Louise Doran LDORAN 80
71 161 Sarath Sewall SSEWALL 80
72 162 Clara Vishney CVISHNEY 80
73 163 Danielle Greene DGREENE 80
74 164 Mattea Marvins MMARVINS 80
75 165 David Lee DLEE 80
76 166 Sundar Ande SANDE 80
77 167 Amit Banda ABANDA 80
78 168 Lisa Ozer LOZER 80
79 169 Harrison Bloom HBLOOM 80
80 170 Tayler Fox TFOX 80
81 171 William Smith WSMITH 80
82 172 Elizabeth Bates EBATES 80
83 173 Sundita Kumar SKUMAR 80
84 174 Ellen Abel EABEL 80
85 175 Alyssa Hutton AHUTTON 80
86 176 Jonathon Taylor JTAYLOR 80
87 177 Jack Livingston JLIVINGS 80
88 178 Kimberely Grant KGRANT  
89 179 Charles Johnson CJOHNSON 80
90 180 Winston Taylor WTAYLOR 50
91 181 Jean Fleaur JFLEAUR 50
92 182 Martha Sullivan MSULLIVA 50
93 183 Girard Geoni GGEONI 50
94 184 Nandita Sarchand NSARCHAN 50
95 185 Alexis Bull ABULL 50
96 186 Julia Dellinger JDELLING 50
97 187 Anthony Cabrio ACABRIO 50
98 188 Kelly Chung KCHUNG 50
99 189 Jennifer Dilly JDILLY 50
100 190 Timothy Gates TGATES 50
101 191 Randall Perkins RPERKINS 50
102 192 Sarah Bell SBELL 50
103 193 Britney Everett BEVERETT 50
104 194 Samuel McCain SMCCAIN 50
105 195 Vance Jones VJONES 50
106 196 Alana Walsh AWALSH 50
107 197 Kevin Feeney KFEENEY 50
 

Departments 테이블 전체 행(PK: DEPARTMENT_ID)

NO DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
1 10 Administration 200 1700
2 20 Marketing 201 1800
3 30 Purchasing 114 1700
4 40 Human Resources 203 2400
5 50 Shipping 121 1500
6 60 IT 103 1400
7 70 Public Relations 204 2700
8 80 Sales 145 2500
9 90 Executive 100 1700
10 100 Finance 108 1700
11 110 Accounting 205 1700
12 120 Treasury   1700
13 130 Corporate Tax   1700
14 140 Control And Credit   1700
15 150 Shareholder Services   1700
16 160 Benefits   1700
17 170 Manufacturing   1700
18 180 Construction   1700
19 190 Contracting   1700
20 200 Operations   1700
21 210 IT Support   1700
22 220 NOC   1700
23 230 IT Helpdesk   1700
24 240 Government Sales   1700
25 250 Retail Sales   1700
26 260 Recruiting   1700
27 270 Payroll   1700

 

아래와 같이 220을 비교하는 조건에도 (+) 기호가 들어가는 경우가 있다. 이경우는 Outer 조건을 일관성 있게 맞추기 위해서 수행해주는 조건으로 아래와 같이 Outer 조인시에 추가로 상수값을 비교하면 (+) 기호을 넣어준다. 전체적으로 Outer 가 유지 된다.

select *
from DEPARTMENTS D, EMPLOYEES E
where d.department_id = e.department_id (+)
and e.department_id(+) = 220
;

 

결과

 - e.department_id가 동일하고 department_id가 220인 것은 없으므로 우측  Employee부분은 전부 공란이되지만 Outer Join은 유지되어서 좌측은 Department전체가 다 표출된다.

No DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER SALARY
1 10 Administration 200 1700            
2 20 Marketing 201 1800            
3 30 Purchasing 114 1700            
4 40 Human Resources 203 2400            
5 50 Shipping 121 1500            
6 60 IT 103 1400            
7 70 Public Relations 204 2700            
8 80 Sales 145 2500            
9 90 Executive 100 1700            
10 100 Finance 108 1700            
11 110 Accounting 205 1700            
12 120 Treasury   1700            
13 130 Corporate Tax   1700            
14 140 Control And Credit   1700            
15 150 Shareholder Services   1700            
16 160 Benefits   1700            
17 170 Manufacturing   1700            
18 180 Construction   1700            
19 190 Contracting   1700            
20 200 Operations   1700            
21 210 IT Support   1700            
22 220 NOC   1700            
23 230 IT Helpdesk   1700            
24 240 Government Sales   1700            
25 250 Retail Sales   1700            
26 260 Recruiting   1700            
27 270 Payroll   1700            

 

만일 Oracle 표기법으로 상수값 비교 조건에 (+)를 빼면 전체 결과에서 e.department_id = 220 인것으로 판단을 해서 결과는 empty가 나오게 된다 (employee중에 220번 department_id를 가진 사람은 없으므로) 즉 Inner join처럼 동작하게 된다.

select *
from DEPARTMENTS D, EMPLOYEES E
where d.department_id = e.department_id (+)
and e.department_id = 220
;

 

-- The End --