문자열 연결은 Oracle ||, SQL Server + 다. Oracle || 는 NULL 을 건너뛰고, SQL Server + 는 NULL 을 만나면 NULL 이다.
NULL 대체는 Oracle NVL, SQL Server ISNULL 이다. COALESCE·NULLIF·CASE 는 두 DB 모두 쓴다. DECODE·NVL2 는 Oracle 에만 있다.
Oracle 은 '' 를 NULL 로 보고, 오름차순 정렬에서 NULL 을 맨 뒤에 둔다. SQL Server 는 '' 를 NULL 과 구분하고, 오름차순에서 NULL 이 맨 앞이다.
Top N 은 Oracle ROWNUM·FETCH FIRST, SQL Server TOP(n) 이다. 외부 조인 (+), 계층형 질의 CONNECT BY, 차집합 MINUS 는 Oracle 표기이고 SQL Server 는 ANSI 조인·재귀 CTE·EXCEPT 를 쓴다.
Oracle 은 DML 뒤에 COMMIT 을 직접 하고 DDL 은 자동 커밋된다. SQL Server 는 기본이 AUTO COMMIT 이고, BEGIN TRAN 안에서는 DDL 도 ROLLBACK 된다.
SELECT ENAME || ' / ' || JOB AS EJ, 'A' || NULL || 'B' AS AB FROM EMP WHERE EMPNO = 7839;
EJ AB---------------------- --KING / PRESIDENT AB
SQL Server 는 같은 일을 + 로 한다. + 는 덧셈과 연결을 함께 맡는다.
SELECT ENAME + ' / ' + JOB FROM EMP WHERE EMPNO = 7839; -- KING / PRESIDENTSELECT 'A' + NULL + 'B'; -- NULLSELECT CONCAT('A', NULL, 'B'); -- AB (CONCAT 은 NULL 을 빈 문자열로 본다)
Oracle 에서 + 는 산술 연산자뿐이다. 문자열에 쓰면 숫자로 바꾸려다 실패한다.
SELECT ENAME + JOB FROM EMP WHERE EMPNO = 7839;
SELECT ENAME + JOB FROM EMP WHERE EMPNO = 7839 *ERROR at line 1:ORA-01722: unable to convert string value containing 'K' to a number: ENAMEORA-03302: (ORA-01722 details) invalid string value: KING
23ai 이전 Oracle 은 같은 오류를 ORA-01722: invalid number 한 줄로 보여 준다. 오류 번호는 같다.
Oracle 의 CONCAT 은 시험 기준으로 인자가 둘이다(W3 Day 2). SQL Server 의 CONCAT 은 인자를 여럿 받는다.
NULL 을 다른 값으로 바꾸는 함수는 이름이 갈린다. COALESCE 는 표준 함수라 두 DB 에서 같다.
SELECT EMPNO, ENAME, NVL(COMM, 0) AS NVL_COMM, COALESCE(COMM, MGR, 0) AS COAL FROM EMP WHERE EMPNO IN (7499, 7566, 7839) ORDER BY EMPNO;
EMPNO ENAME NVL_COMM COAL---------- ---------- ---------- ---------- 7499 ALLEN 300 300 7566 JONES 0 7839 7839 KING 0 0
JONES 는 COMM 이 NULL 이라 COALESCE 가 다음 인자 MGR(7839)을 골랐다. KING 은 COMM·MGR 이 모두 NULL 이라 마지막 0 이다.
SQL Server 에서는 ISNULL(COMM, 0) 이 NVL(COMM, 0) 의 짝이다. Oracle 에 ISNULL 을 쓰면 없는 이름이라 ORA-00904 다.
SELECT ISNULL(COMM, 0) FROM EMP;
SELECT ISNULL(COMM, 0) FROM EMP *ERROR at line 1:ORA-00904: "ISNULL": invalid identifier
SELECT SUBSTR('DATABASE', 1, 4) AS SUB, LENGTH('DATABASE') AS LEN, TO_CHAR(DATE '2026-11-04', 'YYYY/MM/DD') AS CH, CAST('123' AS NUMBER) + 1 AS CA FROM DUAL;
SUB LEN CH CA---- ---------- ---------- ----------DATA 8 2026/11/04 124
SQL Server 로 옮기면 이렇다.
SELECT SUBSTRING('DATABASE', 1, 4), -- DATA (SQL Server 2022 까지는 길이 인자를 생략할 수 없다) LEN('DATABASE'), -- 8 CONVERT(VARCHAR(10), GETDATE(), 111), -- 오늘 날짜를 yyyy/mm/dd 로 CAST('123' AS INT) + 1; -- 124
하는 일
Oracle
SQL Server
현재 날짜·시각
SYSDATE
GETDATE()
하루 뒤
SYSDATE + 1
DATEADD(DAY, 1, GETDATE())
날짜 → 문자
TO_CHAR(날짜, '형식')
CONVERT(VARCHAR, 날짜, 스타일번호)
올림
CEIL
CEILING
나머지
MOD(m, n)
m % n
CAST(값 AS 타입) 은 표준 문법이라 두 DB 에 모두 있다. 타입 이름만 각 DB 의 것을 쓴다.
SYSDATE 에는 괄호가 없고 GETDATE 에는 괄호가 있다. SYSDATE() 나 GETDATE 로 쓴 보기는 둘 다 틀린 형태다.
외부 조인을 WHERE 절의 (+) 로 쓰는 것은 Oracle 만의 표기다. SQL Server 는 ANSI 조인만 받는다.
SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO(+) = D.DEPTNO;
COUNT(*)---------- 15
SELECT COUNT(*) FROM EMP E RIGHT OUTER JOIN DEPT D ON E.DEPTNO = D.DEPTNO; -- SQL Server, 15
ANSI 표기는 Oracle 에서도 그대로 돈다. 두 DB 에 공통으로 쓸 수 있는 쪽은 ANSI 다.
차집합 연산자는 Oracle MINUS, SQL Server EXCEPT 다.
SELECT DEPTNO FROM DEPT MINUS SELECT DEPTNO FROM EMP;
DEPTNO---------- 40
실습장의 Oracle 23ai 는 EXCEPT 도 받는다(W5 Day 3). 시험에서는 Oracle 차집합을 MINUS 로 본다.
값에 따라 결과를 고르는 일은 Oracle 에서 DECODE 와 CASE 둘 다 된다. SQL Server 에는 DECODE 가 없어 CASE 만 쓴다.
SELECT ENAME, DEPTNO, DECODE(DEPTNO, 10, 'ACCT', 20, 'RSCH', 'ETC') AS DEC, CASE DEPTNO WHEN 10 THEN 'ACCT' WHEN 20 THEN 'RSCH' ELSE 'ETC' END AS CS FROM EMP WHERE EMPNO IN (7369, 7499, 7839) ORDER BY EMPNO;
START WITH … CONNECT BY PRIOR 는 Oracle 의 계층형 질의 문법이다. KING 아래 2단계까지 펼친다.
SELECT LEVEL, ENAME, MGR FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR AND LEVEL <= 2 ORDER SIBLINGS BY ENAME;
LEVEL ENAME MGR---------- ---------- ---------- 1 KING 2 BLAKE 7839 2 CLARK 7839 2 JONES 7839
SQL Server 에는 CONNECT BY 가 없다. 자기 자신을 참조하는 WITH 절(재귀 CTE)로 같은 트리를 만든다.
WITH ORG (EMPNO, ENAME, MGR, LVL) AS ( SELECT EMPNO, ENAME, MGR, 1 FROM EMP WHERE MGR IS NULL -- 시작 행 (START WITH 역할) UNION ALL SELECT E.EMPNO, E.ENAME, E.MGR, O.LVL + 1 FROM EMP E JOIN ORG O ON E.MGR = O.EMPNO -- 한 단계 아래 (CONNECT BY 역할))SELECT LVL, ENAME, MGR FROM ORG WHERE LVL <= 2;
앞 SELECT 가 루트, UNION ALL 뒤 SELECT 가 "앞 단계의 부하" 를 찾는다. 더 찾을 행이 없으면 멈춘다.
LEVEL 같은 의사 열은 없다. 깊이는 LVL 처럼 직접 열을 만들어 센다.
Oracle 도 11g R2 부터 재귀 WITH 를 지원한다. SQLD 에서 Oracle 의 계층형 질의라고 하면 CONNECT BY 를 가리킨다.
주문 번호처럼 1, 2, 3 … 으로 늘어나는 키를 만들 때 Oracle 은 시퀀스 객체를 따로 만든다. 실습장은 시퀀스 생성을 지원하지 않아 문법만 본다.
-- Oracle: 테이블과 별개인 시퀀스 객체CREATE SEQUENCE ORD_SEQ START WITH 1 INCREMENT BY 1;INSERT INTO ORDERS (ORDER_ID, ITEM) VALUES (ORD_SEQ.NEXTVAL, 'PEN');SELECT ORD_SEQ.CURRVAL FROM DUAL;-- SQL Server: 열 속성으로 붙는 IDENTITYCREATE TABLE ORDERS (ORDER_ID INT IDENTITY(1, 1) PRIMARY KEY, ITEM VARCHAR(20));INSERT INTO ORDERS (ITEM) VALUES ('PEN'); -- ORDER_ID 는 적지 않는다
시퀀스는 테이블과 독립된 객체라 여러 테이블이 하나를 나눠 쓸 수 있다. NEXTVAL 로 다음 값을 얻고 CURRVAL 로 방금 얻은 값을 본다.
IDENTITY(시작값, 증가값) 은 그 열에 묶인 속성이다. INSERT 에서 그 열을 빼면 값이 자동으로 채워진다.
지금은 Oracle 12c 의 GENERATED AS IDENTITY 열, SQL Server 2012 의 CREATE SEQUENCE 처럼 서로의 방식을 모두 갖췄다. 두 DB 를 대비하는 문항에서는 Oracle 은 SEQUENCE, SQL Server 는 IDENTITY 로 짝짓는다.