MySQL만 쓰다가 Oracle을 처음 쓰면서 헷갈린 것들. 비슷해 보이지만 생각보다 많이 다르다.
-- MySQL
SELECT * FROM table LIMIT 10;
-- Oracle
SELECT * FROM table WHERE ROWNUM <= 10;
MySQL의 LIMIT이 Oracle에선 ROWNUM이다. 처음엔 왜 LIMIT이 안 되지? 했는데 이거였음.
-- MySQL
SELECT NOW();
-- Oracle
SELECT SYSDATE FROM DUAL;
Oracle은 DUAL이라는 더미 테이블을 써야 한다. 처음엔 이게 뭔가 싶었는데, 테이블 없이 단순 계산이나 함수 결과만 조회할 때 쓰는 형식상의 테이블임.
-- MySQL
SELECT DATE_FORMAT(col, '%Y-%m-%d');
-- Oracle
SELECT TO_CHAR(col, 'YYYY-MM-DD') FROM DUAL;
-- MySQL
SELECT IFNULL(col, '없음');
-- Oracle
SELECT NVL(col, '없음') FROM table;
SELECT NVL2(col, '값 있음', '값 없음') FROM table; -- 있을 때/없을 때 구분 가능
-- MySQL
SELECT CONCAT('안녕', '하세요');
-- Oracle
SELECT '안녕' || '하세요' FROM DUAL;
Oracle은 || 연산자를 주로 쓴다. CONCAT도 되긴함.
-- MySQL
SELECT IF(score >= 60, '합격', '불합격');
-- Oracle — IF 없음! CASE나 DECODE 써야 함
SELECT CASE WHEN score >= 60 THEN '합격' ELSE '불합격' END FROM table;
SELECT DECODE(SIGN(score - 60), 1, '합격', 0, '합격', '불합격') FROM table;
Oracle엔 IF() 함수 자체가 없다. CASE WHEN이나 DECODE로 대체해야 함.
| 기능 | MySQL | Oracle |
|---|---|---|
| 행 제한 | LIMIT n | ROWNUM <= n |
| 현재시간 | NOW() | SYSDATE |
| 날짜 포맷 | DATE_FORMAT() | TO_CHAR() |
| NULL 대체 | IFNULL() | NVL() |
| 문자열 합치기 | CONCAT() | \|\| |
| 조건식 | IF() | DECODE(), CASE WHEN |
| 더미 테이블 | 불필요 | FROM DUAL 필요 |
| 자동증가 | AUTO_INCREMENT | SEQUENCE |
왼쪽 테이블은 무조건 다 가져오고, 오른쪽 테이블은 매칭되는 것만 가져오는 것.
매칭이 없으면 오른쪽은 NULL로 채워진다.
[테이블 A] [테이블 B]
REQ_NO | 이름 REQ_NO | 주소
1 | 홍길동 1 | 서울
2 | 김철수 3 | 부산
3 | 이영희
-- LEFT OUTER JOIN 결과
REQ_NO | 이름 | 주소
1 | 홍길동 | 서울
2 | 김철수 | NULL ← B에 없어도 A는 나옴
3 | 이영희 | 부산
SELECT X.컬럼A, Y.컬럼B, Z.컬럼C
FROM 테이블X X
LEFT JOIN 테이블Y Y ON X.REQ_NO = Y.REQ_NO
LEFT JOIN 테이블Z Z ON Y.REQ_NO = Z.REQ_NO;
체인처럼 이어서 쓰면 된다. 꼭 같은 기준 테이블일 필요 없이, 관계에 따라 Y 기준으로 Z를 붙이는 것도 가능.
여러 테이블을 JOIN할 때 이런 에러가 난 적 있다:
ORA-00918: 열의 정의가 애매합니다
원인은 WHERE 절에서 컬럼 앞에 테이블 alias를 안 붙여서. 두 테이블에 같은 이름의 컬럼이 있으면 Oracle이 어느 테이블 거냐고 모르는 것.
-- 에러
WHERE REQ_NO = '123'
-- 해결
WHERE A.REQ_NO = '123'
분명히 DB에 데이터가 여러 건인데 화면에 딱 1개만 나왔다. 쿼리도 맞고 JOIN도 맞는데 왜 1개지?
getFieldMap()을 쓰고 있었기 때문.
| 메서드 | 반환 | 용도 |
|---|---|---|
getFieldMap() | 1행만 반환 | 단건 조회 (상세 화면) |
getListMap() | 여러 행 반환 | 목록 조회 |
getFieldMap()은 결과가 아무리 많아도 첫 번째 행 하나만 돌려준다. 목록이 필요하면 반드시 getListMap()을 써야 함.
<%
sb = new StringBuffer();
sb.append("SELECT C035002, C035003 FROM CRC035TD WHERE REQ_NO=" + REQ_NO);
// getFieldMap → getListMap으로 변경
List<StringMap> list = sq.mgr.getListMap(sb.toString(), true);
%>
<table>
<tbody>
<%for(StringMap row : list){%>
<tr>
<td><%=row.get("C035002","-")%></td>
<td><%=row.get("C035003","-")%></td>
</tr>
<%}%>
</tbody>
</table>
화면에 데이터가 1건만 나온다면, 먼저 getFieldMap을 쓰고 있는지 확인하자.
처음으로 혼자 JSP 화면을 만들어보라는 업무 지시를 받았다. 주어진 건 테이블 명세서 하나.
CRC033TD
- REQ_NO : 요청번호 (PK)
- C033000 : 일련번호
- C033001 : 고유번호
- C033002 : 주소
- C033003 : 문서명
- C033004 : 관할등기소
...
<%
StringMap info = sq.mgr.getFieldMap("SELECT * FROM CRC033TD WHERE REQ_NO=" + REQ_NO, true);
%>
<div style="text-align:left;">
고유번호: <%=info.get("C033001","-")%><br>
주소: <%=info.get("C033002","-")%>
</div>

<table>
<thead>
<tr>
<th rowspan="2">이름</th>
<th colspan="3">출석여부</th>
<th rowspan="2">점수</th>
</tr>
<tr>
<th>1일차</th>
<th>2일차</th>
<th>3일차</th>
</tr>
</thead>
<tbody>
<tr>
<td>김OO</td>
<td>출석</td>
<td>결석</td>
<td>출석</td>
<td>70점</td>
</tr>
</tbody>
</table>
기존 프로젝트에서 <LINK href="pop/css/comm.css"> 로 스타일을 불러오는데 내가 짠 코드만 글씨체가 동떨어져 보였다. 원인은 클래스를 안 붙여서.
빠른 해결법: 다른 JSP 파일에서 텍스트 출력하는 부분 찾아서 어떤 클래스 쓰는지 복붙하면 됨.
XPlatform UXStudio는 Tobesoft에서 만든 엔터프라이즈 UI 개발 툴. 금융/공공 환경에서 많이 쓰인다.
| 상황 | 선택 |
|---|---|
| 서버 데이터를 표로 조회/편집 | Grid |
| 이미 만들어진 웹페이지를 보여줄 때 | WebBrowser |
| 데이터 바인딩, 저장, 삭제 필요 | Grid |
| 외부 URL이나 레거시 HTML 재사용 | WebBrowser |
요약: Grid는 데이터를 직접 다루는 컴포넌트, WebBrowser는 웹화면을 끼워넣는 액자.
월별 데이터 추출 쿼리에서 자주 쓰는 패턴:
SELECT *
FROM 테이블
WHERE 등록일자 BETWEEN '&fm_date1' AND '&to_date1'
&변수명 은 Oracle SQL Developer나 내부 쿼리 실행 툴에서 실행 시 값을 입력받는 치환 변수. 저거 실행하면 시작날짜 끝날짜 입력받는 칸이 popup형태로 순서대로 뜸.
슬래시(/) 앞의 값만 뽑아야 할 때:
SELECT SUBSTR(컬럼, 1, INSTR(컬럼, '/') - 1) FROM 테이블
INSTR로 /의 위치를 찾고, SUBSTR로 그 앞까지 자름.
긴 숫자(주민번호, 계좌번호 등)를 Excel로 뽑으면 2.0260E+13 같은 형태로 바뀌는 문제.
해결법: 해당 열 선택 후 Ctrl+1 눌러서 숫자변환 후 저장.
처음엔 아무것도 모르고 getFieldMap 쓰다가 데이터 1개만 나오고, limit=1 했는데 sql문법 에러나고...그런 것들을 하나하나 해결한 기록이다.
앞으로도 막히면 막힌 것들을 계속 기록할 것이다.