SQLD 2회 기출복원 풀이
목차 52
1과목 데이터 모델링의 이해 (문 1~10)
문 1. 아래 데이터 모델에서 키 엔터티로 가장 적절하지 않은 것은? 🎯 고난도

- ① 회원
- ② 상품
- ③ 주문상품
- ④ 주문
정답 및 해설 보기
정답 ③
키 엔터티(기본 엔터티)는 다른 엔터티에 의존하지 않고 독립적으로 생성되며 고유한 주식별자를 갖는다. 회원·상품은 그 자체로 발생하는 기본 엔터티이고, 주문은 행위로 발생하지만 자신만의 주식별자(주문ID)를 새로 부여받는다. 반면 주문상품은 주문ID와 상품ID를 모두 부모로부터 상속받아 주식별자로 쓰는 교차(행위) 엔터티이므로, 부모 없이는 존재할 수 없는 종속 엔터티다. 따라서 키 엔터티가 아니다.
🔑 암기 기본 엔터티 = 독립 생성·고유 주식별자(회원·상품). 교차 엔터티 = 두 부모의 식별자를 함께 상속(주문상품).
문 2. 엔터티의 특징으로 가장 적절하지 않은 것은?
- ① 유일하게 구분할 수 있는 식별자를 가지고 있어야 한다.
- ② 다른 엔터티와 관계를 가질 수 없으며 독립적으로 존재해야 한다.
- ③ 최소한 하나 이상의 속성을 포함해야 한다.
- ④ 반드시 업무에 필요하고 실제로 활용되는 관리 대상이어야 한다.
정답 및 해설 보기
정답 ②
엔터티는 다른 엔터티와 한 개 이상의 관계(Relationship)를 맺는 것이 일반적인 특징이다. "관계를 가질 수 없으며 독립적으로 존재해야 한다"는 설명은 엔터티의 성질을 정반대로 적은 것이다. (통계성 데이터·코드성 엔터티처럼 관계가 약한 예외는 있으나, 원칙은 관계를 가진다는 것이다.)
오답 ① 유일 식별자 보유, ③ 최소 하나 이상의 속성, ④ 업무에 필요한 관리 대상 — 모두 엔터티의 정당한 특징이다.
🔑 암기 엔터티의 특징 = 식별자·속성·업무 필요성 + 다른 엔터티와의 관계.
문 3. 속성에 대한 설명으로 가장 적절하지 않은 것은?
- ① 엔터티의 성질이나 상태를 구체적으로 설명하는 최소의 데이터 단위이다.
- ② 엔터티의 주식별자에 함수적으로 종속될 수 있으며, 이를 통해 엔터티의 의미를 표현한다.
- ③ 하나의 속성에 여러 개의 값이 동시에 저장되도록 정의할 수 있다.
- ④ 특성에 따라 기본 속성, 파생 속성, 설계 속성 등으로 구분할 수 있다.
정답 및 해설 보기
정답 ③
하나의 속성에는 오직 하나의 값(단일값)만 저장되어야 한다. 여러 값을 동시에 저장하는 것은 관계형 데이터 모델의 원자성(1차 정규형) 원칙에 어긋난다. 전화번호·취미처럼 여러 값이 필요하면 제1정규화를 거쳐 별도 엔터티로 분리한다.
오답 ① 최소 데이터 단위, ② 주식별자에 함수적 종속, ④ 기본·파생·설계 속성 분류 — 모두 정확하다.
⚠️ 함정 "하나의 속성에 여러 값" → 다중값 속성 허용처럼 보이지만 단일값 원칙 위반이다.
문 4. 아래 ERD에 대한 설명으로 가장 적절한 것은?

- ① 자동차는 블랙박스가 없어도 존재할 수 있다.
- ② 하나의 블랙박스는 여러 대의 자동차와 연결될 수 있다.
- ③ 자동차에는 반드시 블랙박스가 한 개 이상 있어야 한다.
- ④ 하나의 자동차는 여러 개의 블랙박스와 연결될 수 있다.
정답 및 해설 보기
정답 ①
까마귀 발이 없는 1:1 관계다. 블랙박스 쪽에 동그라미(○, 선택)가 붙어 있으므로 자동차는 블랙박스를 0개 또는 1개 가질 수 있다. 즉, 블랙박스가 없어도 자동차는 존재할 수 있다.
오답 ② 블랙박스는 최대 한 대의 자동차와 연결된다(1:1). ③ 선택(○) 표기이므로 반드시 있어야 하는 것은 아니다. ④ 1:1이므로 여러 개와 연결될 수 없다.
🔑 암기 ERD 선 끝 — 동그라미(○) = 선택(Optional, 0 가능) · 직선(│) = 필수(Mandatory, 1 이상).
문 5. 아래 ERD에 대한 설명으로 가장 적절한 것은?

- ① 고객은 반드시 하나 이상의 계약을 가지고 있어야 한다.
- ② 계약은 고객의 체결 행위에 의해 발생하는 사건 엔터티이다.
- ③ 하나의 계약은 오직 하나의 계약항목만을 가질 수 있다.
- ④ 계약항목은 독립적으로 존재할 수 있는 기본 엔터티이다.
정답 및 해설 보기
정답 ②
계약은 고객이 상품을 계약하는 체결 행위가 일어날 때마다 새로 발생하는 사건(행위) 엔터티다. 고유한 주식별자(계약번호)가 있더라도 부모인 고객에 의존해 생성된다.
오답 ① 고객은 기본 엔터티이므로 반드시 계약을 가져야 하는 것은 아니다. ③ 계약과 계약항목은 1:N 관계이므로 하나의 계약은 여러 계약항목을 가질 수 있다. ④ 계약항목은 계약·상품의 식별자를 참조하는 교차 엔터티라 독립적으로 존재할 수 없다.
🔑 암기 사건(행위) 엔터티 = 비즈니스 프로세스가 일어날 때마다 발생(계약·주문·결제).
문 6. 비식별자 관계에 의해 속성을 생성하는 경우로 가장 적절하지 않은 것은?
- ① 여러 개의 엔터티가 통합되더라도 각 엔터티가 별도의 관계를 유지하는 경우
- ② 자식 엔터티에서 별도의 주식별자를 새로 생성한 경우
- ③ 자식 엔터티에서 부모로부터 상속받은 속성이 반드시 필수일 필요가 없는 경우
- ④ 부모와 자식 엔터티의 데이터 생명주기를 동일하게 관리해야 하는 경우
정답 및 해설 보기
정답 ④
비식별자 관계(점선)는 부모의 주식별자를 자식의 일반 속성(외래 키)으로만 받아 느슨하게 연결하므로, 부모와 자식의 생명주기가 같을 필요가 없고 부모가 없어도 자식이 독립적으로 존재할 수 있다. 생명주기를 동일하게 묶어야 하는 강한 종속은 식별자 관계(실선)를 맺어야 하는 대표적 이유이므로 ④는 비식별자 관계의 사례가 아니다.
🔑 암기 식별자 관계(실선) = 강한 종속·생명주기 동일 / 비식별자 관계(점선) = 약한 종속·독립 생명주기.
문 7. 제3정규형을 만족하는 데이터 모델에 대한 설명으로 가장 적절하지 않은 것은?
- ① 각 속성은 반드시 하나의 값만 가져야 한다.
- ② 모든 속성은 기본 키 전체에 대해 완전하게 종속되어야 한다.
- ③ 기본 키가 아닌 속성은 다른 속성에 종속되지 않고 기본 키에만 종속되어야 한다.
- ④ 이행 함수 종속을 허용해야 한다.
정답 및 해설 보기
정답 ④
정규화는 종속성을 제거해 이상 현상을 막는 과정이다. 제3정규형은 기본 키가 아닌 일반 속성끼리 꼬리를 무는 이행 함수 종속(Transitive Dependency)을 제거한 상태를 말한다. "이행 함수 종속을 허용해야 한다"는 정규화의 목적을 정반대로 적은 오답이다.
오답 ① 원자값(1NF), ② 완전 함수 종속(2NF), ③ 이행 종속 제거(3NF) — 모두 정확하다.
🔑 암기 1NF 원자값 → 2NF 부분 종속 제거 → 3NF 이행 종속 제거.
문 8. 상호 배타적 관계의 예로 가장 적절한 것은?
- ① 결제수단 테이블과 결제 테이블에서, 한 결제 건에 카드와 현금을 동시에 사용하는 경우
- ② 사원 테이블과 부서 테이블에서, 사원이 특정 부서에 소속되는 경우
- ③ 차량 테이블에서, 차량이 법인 소속이거나 개인 소유로만 구분되어 사용하는 경우
- ④ 학생 테이블과 강의 테이블에서, 한 학생이 여러 강의를 수강할 수 있는 경우
정답 및 해설 보기
정답 ③
상호 배타적 관계(Arc 관계)는 여러 선택지 중 단 하나와만 관계를 맺을 수 있는 'A 아니면 B' 구조다. 차량은 법인 소속이거나 개인 소유 중 하나로만 구분되므로 완벽한 배타적 관계다.
오답 ① 카드와 현금을 동시에 사용하므로 배타적이 아니다. ② 사원이 부서에 소속되는 것은 존재로 성립하는 일반 관계다. ④ 학생이 여러 강의를 수강하는 것은 행위로 성립하는 M:N 관계다.
🔑 암기 상호 배타적(Arc) 관계 = 여러 대상 중 하나와만(A OR B, 동시 불가).
문 9. 아래 ERD에 대한 설명으로 가장 적절하지 않은 것은?

- ① 하나의 진료기록은 반드시 하나의 환자에 속한다.
- ② 환자는 진료기록을 가질 수도 있고 가지지 않을 수도 있다.
- ③ 한 명의 환자는 여러 개의 진료ID를 가질 수 없다.
- ④ 진료기록에는 환자를 식별할 수 있는 정보가 포함된다.
정답 및 해설 보기
정답 ③
진료기록 쪽에 까마귀 발(<)이 그려져 있으므로 한 환자는 여러 개의 진료기록(진료ID)을 가질 수 있는 1:N 관계다. 따라서 "여러 개의 진료ID를 가질 수 없다"는 ③이 ERD와 어긋난다.
오답 ① 진료기록 쪽 필수(│) 표기 — 반드시 한 환자에 속한다. ② 환자 쪽 선택(○) 표기 — 진료기록이 없을 수도 있다. ④ 진료기록에 환자ID(외래 키)가 있어 환자를 식별한다.
🔑 암기 까마귀 발(<) = 다수(Many). 한 부모가 여러 자식을 가질 수 있다.
문 10. 트랜잭션에 대한 설명으로 가장 적절하지 않은 것은?
- ① 트랜잭션은 데이터베이스에서 하나의 논리적 연산 단위를 의미한다.
- ② 트랜잭션은 부분적으로 실행된 상태를 그대로 유지하거나 일부만 취소하는 것이 가능하다.
- ③ 트랜잭션은 동시에 수행되는 다른 트랜잭션의 영향을 받지 않아야 한다.
- ④ 트랜잭션 수행이 완료되면 커밋을 통해 결과가 데이터베이스에 영구적으로 반영된다.
정답 및 해설 보기
정답 ②
트랜잭션은 원자성(Atomicity)에 따라 'All or Nothing' — 전부 커밋되거나 전부 롤백되어야 한다. 계좌 이체에서 출금만 되고 입금이 안 된 부분 실행 상태로 끝나면 안 된다. "부분 실행 상태를 유지하거나 일부만 취소"한다는 ②가 원자성을 정면으로 위반한다.
오답 ① 논리적 연산 단위(정의), ③ 고립성(Isolation), ④ 지속성(Durability) — 모두 정확하다.
🔑 암기 ACID — 원자성(All or Nothing)·일관성·고립성·지속성.
2과목 SQL 기본 및 활용 (문 11~50)
문 11. 아래 SQL의 실행 결과가 다른 하나는? (단, DBMS는 오라클로 가정함)
①
SELECT REPLACE('00A0BC00', '0') FROM DUAL;
②
SELECT LTRIM('00A0BC', '0') FROM DUAL;
③
SELECT RTRIM('A0BC00', '0') FROM DUAL;
④
SELECT TRIM('0' FROM '00A0BC00') FROM DUAL;
정답 및 해설 보기
정답 ①
REPLACE는 바꿀 문자가 생략되면 찾을 문자('0')를 위치와 무관하게 모두 제거한다. ①은 '00A0BC00'에서 0을 전부 없애 'ABC'가 된다. 반면 TRIM 3형제는 양쪽 끝의 문자만 다듬는다. ② LTRIM('00A0BC','0')은 왼쪽 0만 제거해 'A0BC', ③ RTRIM('A0BC00','0')은 오른쪽 0만 제거해 'A0BC', ④ TRIM('0' FROM '00A0BC00')은 양 끝 0을 제거해 'A0BC'다. 즉 ②③④는 모두 'A0BC'이고 ①만 'ABC'로 다르다. 실행으로 네 결과(ABC / A0BC / A0BC / A0BC)를 검산했다.
⚠️ 함정 보기마다 입력 문자열이 다르다. REPLACE는 중간 문자도 제거하지만, TRIM/LTRIM/RTRIM은 양 끝만 건드린다.
문 12. 아래 SQL의 실행 결과는? 🎯 고난도
[EMP]
| ENAME |
|---|
| KIM |
| KAN |
| KANG |
| KING |
| K_N |
| PK_NG |
SELECT COUNT(*) CNT
FROM (SELECT ENAME
FROM EMP
WHERE ENAME
LIKE '%K_N%'
UNION ALL
SELECT ENAME
FROM EMP
WHERE ENAME
LIKE '%K\_N%' ESCAPE '\');
- ① 5
- ② 6
- ③ 7
- ④ 8
정답 및 해설 보기
정답 ③
위쪽 LIKE '%K_N%'에서 언더스코어(_)는 임의의 한 글자를 뜻하므로 'K + 한 글자 + N' 패턴을 품은 KAN·KANG·KING·K_N·PK_NG가 걸려 5건이다(K_N·PK_NG의 실제 _ 문자도 와일드카드 한 글자에 매칭). 아래쪽 LIKE '%K\_N%' ESCAPE '\'는 역슬래시 뒤의 _를 일반 문자로 취급하므로 진짜 'K_N' 텍스트를 포함한 K_N·PK_NG 2건이다. UNION ALL은 중복을 제거하지 않으므로 5 + 2 = 7건이다. 실행으로 7을 검산했다.
🔑 암기 _ = 정확히 한 글자 / ESCAPE 지정 문자 뒤의 와일드카드 = 일반 문자 / UNION ALL = 중복 포함 합산.
문 13. PRICE의 값이 NULL이 아닌 경우를 조회하는 SQL로 가장 적절한 것은?
①
SELECT * FROM PRODUCT
WHERE PRICE NOT NULL;
②
SELECT * FROM PRODUCT
WHERE PRICE <> NULL;
③
SELECT * FROM PRODUCT
WHERE PRICE != NULL;
④
SELECT * FROM PRODUCT
WHERE PRICE IS NOT NULL;
정답 및 해설 보기
정답 ④
NULL은 '값이 없음'이라 =·<>·!= 같은 비교 연산자로는 판별할 수 없다(결과가 항상 UNKNOWN). NULL 여부는 전용 문법인 IS NULL·IS NOT NULL로만 확인한다. 따라서 ④가 정답이다.
오답 ① NOT NULL은 비교 연산자가 아닌 잘못된 문법, ②③ <> NULL·!= NULL은 결과가 늘 UNKNOWN이라 한 행도 반환하지 못한다.
🔑 암기 NULL 판별은 IS NULL / IS NOT NULL 만.
문 14. 아래 STUDENT 테이블에서 수강생이 3명 이상인 강좌(COURSE)를 출력하는 SQL로 가장 적절하지 않은 것은?
(단, COURSE 칼럼에는 NOT NULL 제약 조건이 걸려 있음)
[테이블]
STUDENT (ID, NAME, MAJOR, GRADE, COURSE)
①
SELECT COURSE
FROM STUDENT
GROUP BY COURSE
HAVING COUNT(ID) >= 3;
②
SELECT COURSE
FROM STUDENT
GROUP BY COURSE
HAVING COUNT(*) >= 3;
③
SELECT COURSE
FROM STUDENT
WHERE COUNT(ID) >= 3;
④
SELECT DISTINCT COURSE
FROM STUDENT
WHERE COURSE IN (
SELECT COURSE
FROM STUDENT
GROUP BY COURSE
HAVING COUNT(*) >= 3);
정답 및 해설 보기
정답 ③
COUNT·SUM 같은 집계 함수는 GROUP BY로 그룹을 묶은 뒤에 계산되므로, 그룹화 이전 단계인 WHERE 절에서는 직접 쓸 수 없다. ③은 WHERE COUNT(ID) >= 3처럼 WHERE에 집계 함수를 써서 문법 오류가 발생한다. 그룹 조건은 HAVING 절을 써야 한다.
오답 ① ID는 기본 키라 NULL이 없어 COUNT(ID)와 COUNT(*)가 동일, ② HAVING COUNT(*), ④ 서브쿼리에서 HAVING으로 거른 뒤 메인쿼리가 DISTINCT로 조회 — 모두 정상이다.
⚠️ 함정 집계 함수는 WHERE에 못 쓴다. 그룹 조건은 반드시 HAVING.
문 15. ORDER BY 절에 대한 설명으로 가장 적절하지 않은 것은?
- ① 여러 개의 칼럼을 동시에 지정하여 우선순위를 두고 정렬할 수 있다.
- ② ORDER BY 절은 SELECT 문에서 가장 마지막 단계에 실행된다.
- ③ ORDER BY 절의 기본 정렬 방식은 오름차순이다.
- ④ SELECT 절에 포함되지 않은 칼럼은 ORDER BY 절에서 정렬 기준으로 사용할 수 없다.
정답 및 해설 보기
정답 ④
SQL 실행 순서는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY로, ORDER BY가 SELECT보다 뒤에 실행된다. 이때 원본 테이블(FROM)의 정보가 메모리에 올라와 있으므로, SELECT 절에서 출력하지 않은 칼럼이라도 원본에 존재하면 ORDER BY의 정렬 기준으로 쓸 수 있다. 따라서 "사용할 수 없다"는 ④가 틀렸다. (단, GROUP BY·DISTINCT로 행이 압축되면 SELECT에 명시된 칼럼·집계 함수만 쓸 수 있는 제한이 생긴다.)
오답 ① 다중 칼럼 우선순위 정렬, ② 실행 순서상 가장 마지막, ③ 기본값 ASC(오름차순) — 모두 정확하다.
🔑 암기 실행 순서 FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY. 원본 칼럼이면 SELECT에 없어도 정렬 기준 가능.
문 16. 아래 테이블에 대한 SQL의 실행 결과가 다른 하나는?
[테이블]
EMP(ENO, ENAME, DEPTNO)
DEPT(DEPTNO, DNAME)
①
SELECT *
FROM EMP INNER JOIN DEPT USING (DEPTNO);
②
SELECT *
FROM EMP LEFT JOIN DEPT USING (DEPTNO);
③
SELECT *
FROM EMP JOIN DEPT USING (DEPTNO);
④
SELECT * FROM EMP NATURAL JOIN DEPT;
정답 및 해설 보기
정답 ②
①·③(JOIN은 기본이 INNER JOIN)·④(NATURAL JOIN은 공통 칼럼 DEPTNO 기준 내부 조인)는 모두 양쪽에 매칭되는 행만 출력하는 내부 조인이라 결과가 같다. ②만 LEFT JOIN으로, 왼쪽 EMP의 모든 행을 보존하고 DEPT에 매칭이 없으면 NULL로 채운다. 매칭되지 않는 사원까지 살아남으므로 ②의 결과가 다르다.
🔑 암기 INNER/JOIN/NATURAL JOIN = 교집합 / LEFT JOIN = 왼쪽 전부 보존 + 미매칭 NULL.
문 17. 아래 SQL의 실행 결과를 순서대로 나열한 것은?
[TBL]
| COL1 | COL2 | COL3 |
|---|---|---|
| 10 | NULL | 50 |
| 20 | 30 | NULL |
| 30 | 40 | 0 |
SELECT AVG(COL3)
FROM TBL;
SELECT AVG(COL3)
FROM TBL WHERE COL3 > 0;
SELECT AVG(COL3)
FROM TBL WHERE COL3 IS NOT NULL;
- ① 25, 50, 25
- ② 25, NULL, 25
- ③ 50, 50, 50
- ④ 50, 50, 0
정답 및 해설 보기
정답 ①
집계 함수는 NULL을 무시한다. 첫 쿼리 AVG(COL3)은 50·NULL·0 중 NULL을 빼고 50·0의 평균 (50+0)/2 = 25다. 둘째 WHERE COL3 > 0은 0과 NULL이 탈락해 50만 남으니 평균 50이다. 셋째 WHERE COL3 IS NOT NULL은 50·0이 남아 다시 25다. 따라서 25, 50, 25이며 실행으로 검산했다.
⚠️ 함정 WHERE COL3 > 0은 0뿐 아니라 NULL도 제외(NULL은 비교 불가). IS NOT NULL은 0을 포함하므로 첫 쿼리와 같은 25.
문 18. 아래 테이블에서 월별 총매출액을 조회하는 SQL로 가장 적절하지 않은 것은? (단, S_DATE 칼럼은 DATE 타입임) 🎯 고난도
[SALES]
| S_ID | S_DATE | M_ID | AMT |
|---|---|---|---|
| 1 | 2018-07-03 | 201807 | 1200 |
| 2 | 2018-07-25 | 201807 | 1800 |
| 3 | 2018-08-10 | 201808 | 2000 |
| 4 | 2018-08-28 | 201808 | 2500 |
| 5 | 2018-09-05 | 201809 | 3000 |
| 6 | 2018-09-21 | 201809 | 4000 |
①
SELECT M_ID, SUM(AMT) AS TOTAL
FROM (
SELECT SUBSTR(TO_CHAR(S_DATE,
'YYYYMM'), 1, 6) AS M_ID, AMT
FROM SALES
) X
GROUP BY M_ID
ORDER BY M_ID;
②
SELECT TO_CHAR(S_DATE, 'YYYYMM') AS M_ID,
SUM(AMT) AS TOTAL
FROM SALES
GROUP BY S_DATE
ORDER BY TO_CHAR(S_DATE, 'YYYYMM');
③
SELECT M_ID,
SUM(AMT) AS TOTAL
FROM (
SELECT TO_CHAR(S_DATE, 'YYYYMM') AS
M_ID, AMT
FROM SALES
) X
GROUP BY M_ID
ORDER BY TO_DATE(M_ID, 'YYYYMM');
④
SELECT M_ID, SUM(AMT) AS TOTAL
FROM (
SELECT TO_DATE(TO_CHAR(S_DATE,
'YYYYMM'), 'YYYYMM') AS M_ID, AMT
FROM SALES
) X
GROUP BY M_ID
ORDER BY M_ID;
정답 및 해설 보기
정답 ②
②는 SELECT에서 TO_CHAR(S_DATE,'YYYYMM')으로 월을 표시하지만, 정작 GROUP BY는 DATE 타입 원본 칼럼 S_DATE로 묶는다. S_DATE는 일자가 다르면 다른 값이므로 2018-07-03과 2018-07-25가 서로 다른 그룹으로 쪼개져 월별이 아닌 일자별 집계가 된다.
오답 ①③④는 모두 인라인 뷰에서 월(YYYYMM) 단위로 가공한 M_ID로 GROUP BY 하므로 같은 달이 하나로 묶인다(③의 ORDER BY TO_DATE도 정렬만 바꿀 뿐 그룹화에는 영향 없음).
⚠️ 함정 SELECT에서 월로 잘라도 GROUP BY가 원본 날짜면 일자별로 쪼개진다. 집계 단위는 GROUP BY 기준이 결정한다.
문 19. 아래 테이블과 실행 결과를 참고할 때 SQL의 빈칸 ㉠에 들어갈 내용으로 가장 적절한 것은?
[T1]
| CODE |
|---|
| A |
| B |
| B |
| C |
[T2]
| CODE |
|---|
| B |
| C |
| D |
SELECT T1.CODE AS COL1,
T2.CODE AS COL2
FROM T1 ㉠ T2
ON T1.CODE = T2.CODE;
[실행 결과]
| COL1 | COL2 |
|---|---|
| B | B |
| B | B |
| C | C |
| A | NULL |
- ① RIGHT OUTER JOIN
- ② FULL OUTER JOIN
- ③ INNER JOIN
- ④ LEFT OUTER JOIN
정답 및 해설 보기
정답 ④
실행 결과를 보면 왼쪽 T1의 A·B·B·C가 모두 살아남았고, T2에 짝이 없는 A는 오른쪽이 NULL로 채워졌다. 반대로 T2에만 있던 D는 결과에 없다. 왼쪽 테이블을 모두 보존하고 오른쪽 미매칭을 NULL로 처리하는 조인은 LEFT OUTER JOIN이다.
오답 ① RIGHT면 D가 살고 A가 빠진다. ② FULL이면 D도 나온다. ③ INNER면 A가 빠진다.
🔑 암기 LEFT OUTER JOIN = 왼쪽 전부 보존, 오른쪽 미매칭은 NULL.
문 20. 아래 SQL의 실행 결과는?
[MY_TAB]
| C1 | C2 | C3 | C4 |
|---|---|---|---|
| 1 | 1 | 1 | 50 |
| 2 | 1 | 1 | 40 |
| 2 | 2 | 1 | 60 |
| 3 | 1 | 1 | NULL |
| 1 | 2 | 1 | NULL |
SELECT C1, C4, C2, C3
FROM MY_TAB
ORDER BY C4 DESC NULLS LAST, C1 ASC
FETCH FIRST 3 ROWS ONLY;
①
| C1 | C4 | C2 | C3 |
|---|---|---|---|
| 2 | 60 | 2 | 1 |
| 2 | 40 | 1 | 1 |
| 1 | 50 | 1 | 1 |
②
| C1 | C4 | C2 | C3 |
|---|---|---|---|
| 1 | 50 | 1 | 1 |
| 2 | 60 | 2 | 1 |
| 2 | 40 | 1 | 1 |
③
| C1 | C4 | C2 | C3 |
|---|---|---|---|
| 2 | 60 | 2 | 1 |
| 1 | 50 | 1 | 1 |
| 1 | NULL | 2 | 1 |
④
| C1 | C4 | C2 | C3 |
|---|---|---|---|
| 2 | 60 | 2 | 1 |
| 1 | 50 | 1 | 1 |
| 2 | 40 | 1 | 1 |
정답 및 해설 보기
정답 ④
ORDER BY C4 DESC NULLS LAST로 C4를 내림차순 정렬하되 NULL은 맨 뒤로 보낸다. C4 = 60, 50, 40이 차례로 1·2·3등이고 그 뒤가 NULL 두 행이다. 세 값이 모두 달라 2차 기준 C1 ASC는 상위 3위 안에서는 영향이 없다. FETCH FIRST 3 ROWS ONLY로 상위 3행만 가져오면 (2,60,2,1)·(1,50,1,1)·(2,40,1,1)이다. 실행으로 검산했다.
🔑 암기 다중 ORDER BY는 앞 기준 우선·동점일 때만 다음 기준 / NULLS LAST = NULL을 맨 뒤로 / FETCH FIRST n ROWS ONLY = 상위 n행.
문 21. 아래 SQL의 실행 결과로 오류가 발생하지 않는 것은?
[EMPLOYEE]
| EMP_ID | EMP_NAME | DEPT | SALARY |
|---|---|---|---|
| 1001 | 박준호 | 10 | 5000 |
| 1002 | 이서윤 | 10 | 3000 |
| 1003 | 최민수 | 20 | 4000 |
| 1004 | 한지민 | 20 | 2000 |
| 1005 | 김철수 | 30 | 6000 |
①
SELECT EMP_ID, EMP_NAME,
RANK() OVER (PARTITION BY DEPT
ORDER BY SALARY DESC) AS RK
FROM EMPLOYEE
WHERE
RANK() OVER (PARTITION BY DEPT
ORDER BY SALARY DESC) <= 3;
②
SELECT EMP_ID, EMP_NAME,
DENSE_RANK() OVER (PARTITION BY
DEPT) AS DRK
FROM EMPLOYEE;
③
SELECT DEPT, TOTAL_SAL,
RANK() OVER (ORDER BY TOTAL_SAL
DESC) AS DEPT_RK
FROM (
SELECT
DEPT,
SUM(SALARY) AS TOTAL_SAL
FROM EMPLOYEE
GROUP BY DEPT
)
ORDER BY DEPT_RK;
④
SELECT EMP_ID, EMP_NAME,
RANK() OVER (ORDER BY SUM(SALARY)
DESC) AS RK
FROM EMPLOYEE;
정답 및 해설 보기
정답 ③
③은 서브쿼리에서 부서별 합계 TOTAL_SAL을 GROUP BY로 먼저 구한 뒤, 메인쿼리에서 RANK() OVER (ORDER BY TOTAL_SAL DESC)로 순위를 매기는 정상 문법이다. 윈도우 함수가 만든 별칭 DEPT_RK를 ORDER BY에서 참조하는 것도 가능하다.
오답 ① 윈도우 함수는 WHERE 절에서 쓸 수 없다. ② 순위 함수(DENSE_RANK)는 OVER 안에 ORDER BY가 필수인데 빠졌다. ④ 윈도우 함수의 OVER 안에서 집계 함수 SUM을 쓰면서 GROUP BY가 없어 오류다.
⚠️ 함정 윈도우 함수는 SELECT·ORDER BY에서만. WHERE 사용 불가, 순위 함수는 OVER에 ORDER BY 필수.
문 22. 아래 SQL의 실행 시 출력되는 행의 개수로 가장 적절한 것은?
[TAB1]
| 고객명 | 주문금액 |
|---|---|
| 홍길동 | 50 |
| 이순신 | 180 |
| 김유신 | 220 |
| 장보고 | NULL |
[TAB2]
| 등급 | 최저금액 | 최고금액 |
|---|---|---|
| 일반 | 0 | 99 |
| 프리미엄 | 100 | 199 |
| VIP | 200 | 299 |
| VVIP | 300 | 999 |
SELECT *
FROM TAB1 CROSS JOIN TAB2
UNION ALL
SELECT *
FROM TAB1 INNER JOIN TAB2
ON TAB1.주문금액
BETWEEN TAB2.최저금액
AND TAB2.최고금액
UNION ALL
SELECT *
FROM TAB1 FULL OUTER JOIN TAB2
ON TAB1.주문금액
BETWEEN TAB2.최저금액
AND TAB2.최고금액;
- ① 22
- ② 23
- ③ 24
- ④ 25
정답 및 해설 보기
정답 ③
세 결과를 UNION ALL로 단순 합산한다. CROSS JOIN은 4 × 4 = 16건이다. INNER JOIN(BETWEEN)은 홍길동(50)→일반, 이순신(180)→프리미엄, 김유신(220)→VIP가 매칭되고 장보고(NULL)는 비교 불가로 탈락해 3건이다. FULL OUTER JOIN(BETWEEN)은 매칭 3건에 더해 짝 없는 왼쪽 장보고(NULL) 1건과 짝 없는 오른쪽 VVIP 1건이 추가되어 5건이다. 16 + 3 + 5 = 24건이며 실행으로 검산했다.
🔑 암기 CROSS JOIN = M × N / FULL OUTER JOIN = 매칭 + 왼쪽 미매칭 + 오른쪽 미매칭.
문 23. SQL의 실행 결과가 아래와 같을 때 빈칸 ㉠에 들어갈 내용으로 가장 적절한 것은?
TBL1: {1, 2}
TBL2: {7, 8, 9}
결과:
{{1, 7}, {1, 8}, {1, 9}, {2, 7}, {2, 8}, {2, 9}}
SELECT *
FROM TBL1 ㉠ TBL2;
- ① NATURAL JOIN
- ② CROSS JOIN
- ③ INNER JOIN
- ④ LEFT OUTER JOIN
정답 및 해설 보기
정답 ②
TBL1의 2건과 TBL2의 3건이 만들 수 있는 모든 조합 6건(2 × 3)이 빠짐없이 나왔다. 조인 조건 없이 두 테이블 행을 곱해 모든 경우의 수(카테시안 곱)를 만드는 조인은 CROSS JOIN이다.
🔑 암기 CROSS JOIN = 조인 조건 없는 카테시안 곱(행 수 = M × N).
문 24. 아래 테이블을 참고할 때 SQL의 실행 결과가 다른 하나는?
CREATE TABLE R1 (
VAL VARCHAR2(10)
);
CREATE TABLE R2 (
VAL VARCHAR2(10)
);
INSERT INTO R1 VALUES ('X');
INSERT INTO R1 VALUES ('Y');
INSERT INTO R1 VALUES (NULL);
INSERT INTO R2 VALUES ('X');
INSERT INTO R2 VALUES ('X');
INSERT INTO R2 VALUES ('Z');
①
SELECT *
FROM R1
WHERE VAL IN (SELECT VAL FROM R2);
②
SELECT *
FROM R1 NATURAL JOIN R2;
③
SELECT *
FROM R1 INNER JOIN R2 USING (VAL);
④
SELECT *
FROM R1 JOIN R2 USING (VAL);
정답 및 해설 보기
정답 ①
①의 IN은 R2에 값이 존재하는지만 확인하므로, R2에 'X'가 두 건 있어도 R1의 'X' 한 건만 출력한다(NULL과 'Y'는 매칭 실패). 반면 ②③④는 모두 VAL 기준 내부 조인이라 R1의 'X' 한 건이 R2의 'X' 두 건과 각각 짝지어져 2건으로 증식된다. 따라서 1건만 나오는 ①이 다르다. 실행으로 IN=1건, JOIN=2건을 검산했다.
🔑 암기 IN(서브쿼리) = 존재 여부만 확인(증식 없음) / JOIN = 매칭마다 행 증식(1:M).
문 25. 아래 SQL을 실행할 때 오류가 발생하는 것의 개수로 가장 적절한 것은? 🎯 고난도
CREATE TABLE SALES (
ITM VARCHAR2(10),
AMT NUMBER
);
INSERT INTO SALES VALUES ('A', 100);
INSERT INTO SALES VALUES ('B', 100);
INSERT INTO SALES VALUES ('B', 200);
CREATE VIEW SALE_SUM AS
SELECT ITM, SUM(AMT) AS TOT
FROM SALES
GROUP BY ITM;
(가) SELECT *
FROM SALES WHERE ITM = 'Z';
(나) INSERT INTO
SALES VALUES ('Z', 300);
(다) INSERT INTO
SALE_SUM VALUES ('A', 100);
(라) SELECT SALES.ITM, SALE_SUM.TOT
FROM SALES, SALE_SUM
WHERE SALES.AMT = SALE_SUM.TOT;
- ① 1개
- ② 2개
- ③ 3개
- ④ 4개
정답 및 해설 보기
정답 ①
오류는 (다) 한 건뿐이다. SALE_SUM은 GROUP BY와 집계 함수(SUM)로 만든 뷰라, 입력값 100을 원본 SALES의 어느 행에 어떻게 배분할지 알 수 없어 INSERT·UPDATE·DELETE가 불가능하다.
오답 (가) 없는 값을 조회해도 단순 조회라 정상, (나) 원본 테이블에 제약 조건이 없어 정상 삽입, (라) 원본과 뷰를 조인하는 단순 조회라 정상이다.
⚠️ 함정 집계 함수·GROUP BY·DISTINCT가 포함된 뷰는 DML(INSERT/UPDATE/DELETE) 불가.
문 26. 학과가 'MATH'이면서 직급이 'PROFESSOR'가 아닌 교직원을 조회하려고 할 때, SQL의 빈칸 ㉠에 들어갈 내용으로 가장 적절한 것은?
SELECT PID, PNAME, DEPT, TITLE, SAL
FROM PROF
WHERE DEPT = 'MATH'
㉠
SELECT PID, PNAME, DEPT, TITLE, SAL
FROM PROF
WHERE TITLE = 'PROFESSOR';
- ① INTERSECT
- ② UNION
- ③ UNION ALL
- ④ MINUS
정답 및 해설 보기
정답 ④
'MATH 학과' 집합에서 'PROFESSOR 직급' 집합을 빼는 차집합 연산이다. 오라클에서 차집합은 MINUS다(SQL Server는 EXCEPT). 위 결과에서 아래 결과를 제거하면 'MATH이면서 PROFESSOR가 아닌' 교직원만 남는다.
🔑 암기 합집합 UNION · 교집합 INTERSECT · 차집합 MINUS(SQL Server는 EXCEPT).
문 27. 아래 SQL의 실행 결과는?
[T1]
| C | D | X | Y |
|---|---|---|---|
| 1 | 10 | a | N |
| 2 | 10 | b | Y |
| 3 | 30 | c | N |
| 4 | 30 | c | N |
| 5 | 50 | d | X |
| 6 | NULL | e | N |
[T2]
| D | E |
|---|---|
| 10 | e |
| 20 | x |
| 30 | E |
| NULL | E |
| 50 | E |
| 40 | NULL |
SELECT COUNT(DISTINCT C)
FROM T1
WHERE D IN (
SELECT D
FROM T2
WHERE UPPER(E) = 'E'
AND D IS NOT NULL
);
- ① 4
- ② 5
- ③ 6
- ④ 7
정답 및 해설 보기
정답 ②
서브쿼리는 T2에서 UPPER(E)='E'이고 D가 NULL이 아닌 행, 즉 D = 10, 30, 50을 반환한다((NULL, E)는 D가 NULL이라 제외). 메인쿼리는 T1에서 D가 10·30·50인 행 5건을 찾고, 그 C 값은 1·2·3·4·5다. COUNT(DISTINCT C)는 중복이 없으므로 5다. 실행으로 검산했다.
🔑 암기 다중행 서브쿼리 IN = 반환 값 중 하나라도 일치하면 참 / COUNT(DISTINCT) = 중복 제거 건수.
문 28. 아래 테이블을 참고할 때 SQL의 실행 결과가 다른 하나는? (단, DBMS는 오라클로 가정함)
[학생]
| 학번 | 이름 |
|---|---|
| S1 | 홍길동 |
| S2 | 김철수 |
| S3 | 이영희 |
| S4 | 박민수 |
| S5 | 최지우 |
[성적]
| 시험번호 | 학번 | 점수 |
|---|---|---|
| T1 | S1 | 80 |
| T2 | S1 | 90 |
| T3 | S2 | 70 |
| T4 | S2 | 85 |
| T5 | S4 | 100 |
| T6 | S5 | 60 |
①
SELECT S.학번, S.이름,
(SELECT NVL(SUM(G.점수), 0)
FROM 성적 G
WHERE G.학번 = S.학번) AS 총점
FROM 학생 S
ORDER BY S.학번;
②
SELECT S.학번,
(SELECT 이름
FROM 학생
WHERE 학번 = S.학번) AS 이름,
(SELECT NVL(SUM(점수), 0)
FROM 성적
WHERE 학번 = S.학번) AS 총점
FROM 학생 S
ORDER BY S.학번;
③
SELECT S.학번, S.이름,
SUM(G.점수) AS 총점
FROM 학생 S
JOIN 성적 G ON S.학번 = G.학번
WHERE S.학번 IN (SELECT 학번 FROM 성적)
GROUP BY S.학번, S.이름
ORDER BY S.학번;
④
SELECT S.학번, S.이름,
NVL(SUM(G.점수), 0) AS 총점
FROM 학생 S
LEFT JOIN 성적 G ON S.학번 = G.학번
GROUP BY S.학번, S.이름
ORDER BY S.학번;
정답 및 해설 보기
정답 ③
성적 테이블에는 S3(이영희)의 점수가 없다. ③은 INNER JOIN(JOIN)을 쓰고 WHERE 학번 IN (성적) 조건까지 걸어 성적이 있는 학생만 남기므로 S3가 누락되어 4명만 출력된다. 반면 ①·②는 스칼라 서브쿼리로 학생 5명을 모두 유지하며 성적 없는 S3은 총점 0으로, ④는 LEFT JOIN으로 5명을 모두 보존한다. 따라서 4명만 나오는 ③의 결과가 다르다.
⚠️ 함정 INNER JOIN은 미매칭 행을 누락한다. 스칼라 서브쿼리·OUTER JOIN은 기준 테이블의 행을 모두 보존.
문 29. 아래 SQL의 실행 결과는?
[TBL1]
| COL1 | COL2 |
|---|---|
| A | NULL |
| A | 100 |
| B | 100 |
| B | 150 |
| C | 200 |
| C | NULL |
[TBL2]
| COL1 | COL2 |
|---|---|
| A | NULL |
| B | 100 |
| B | 200 |
| C | 100 |
| D | NULL |
| E | 300 |
[TBL3]
| COL1 | COL2 |
|---|---|
| A | NULL |
| B | 200 |
| C | 100 |
| C | NULL |
| E | 300 |
| F | 200 |
SELECT COL1, COL2
FROM TBL1
UNION ALL
SELECT COL1, COL2
FROM TBL2
MINUS
SELECT COL1, COL2
FROM TBL3;
①
| COL1 | COL2 |
|---|---|
| A | NULL |
| A | 100 |
| B | 100 |
| B | 150 |
| C | 200 |
| C | NULL |
②
| COL1 | COL2 |
|---|---|
| A | 100 |
| B | 100 |
| B | 150 |
| C | 200 |
| D | NULL |
③
| COL1 | COL2 |
|---|---|
| A | 100 |
| B | 100 |
| B | 150 |
| C | 100 |
| C | 200 |
| D | NULL |
④
| COL1 | COL2 |
|---|---|
| A | 100 |
| B | 100 |
| B | 150 |
| C | 200 |
| E | 300 |
정답 및 해설 보기
정답 ②
먼저 UNION ALL로 TBL1·TBL2를 그대로 붙이면 12행이 된다. 이어 MINUS TBL3를 수행하는데, MINUS는 차집합을 구하면서 결과 집합의 중복까지 제거한다(ALL이 없으면 UNION·INTERSECT·MINUS 모두 중복 제거). 12행을 중복 정리한 뒤 TBL3에 있는 (A,NULL)·(B,200)·(C,100)·(C,NULL)·(E,300)을 빼면 (A,100)·(B,100)·(B,150)·(C,200)·(D,NULL) 5행만 남는다(MINUS는 NULL을 같은 값으로 취급해 (A,NULL)도 제거). 실행으로 검산했다.
⚠️ 함정 MINUS는 차집합 + 중복 제거(DISTINCT 효과)를 동시에 한다. ③처럼 중복이 남지 않는다.
문 30. 집계 함수에 대한 설명으로 가장 적절하지 않은 것은?
- ① 집계 함수는 여러 행을 대상으로 계산을 수행하며, 이때 NULL 값은 기본적으로 제외하고 처리된다.
- ② 집계 함수는 HAVING 절에서 그룹별 조건을 지정할 때 사용할 수 있다.
- ③ COUNT(*)는 테이블의 모든 행을 대상으로 하며, 일부 칼럼이 NULL이어도 행은 집계 대상에 포함된다.
- ④ 집계 함수는 WHERE 절에서 직접 사용할 수 있다.
정답 및 해설 보기
정답 ④
집계 함수는 GROUP BY 이후에 계산되고 WHERE 절은 그룹화 이전의 행 단위 조건을 처리하므로, 집계 함수를 WHERE 절에서 직접 쓸 수 없다(문 14에서도 같은 함정이 나왔다). 집계 결과로 조건을 걸려면 HAVING 절을 써야 한다.
오답 ① NULL 제외 처리, ② HAVING에서 그룹 조건, ③ COUNT(*)는 일부 칼럼이 NULL이어도 행을 센다 — 모두 정확하다.
⚠️ 함정 집계 함수는 WHERE 불가, HAVING 가능. 단골 출제 포인트다.
문 31. 아래 실행 결과를 출력하는 SQL로 가장 적절한 것은? 🎯 고난도
[대출현황]
| 도서코드 | 대출월 | 지점 | 대출수 |
|---|---|---|---|
| B001 | 202401 | 중앙 | 30 |
| B001 | 202401 | 분관 | 45 |
| B001 | 202402 | 중앙 | 40 |
| B001 | 202402 | 분관 | 35 |
| B002 | 202401 | 중앙 | 20 |
| B002 | 202401 | 분관 | 25 |
| B002 | 202402 | 중앙 | 22 |
| B002 | 202402 | 분관 | 28 |
[실행 결과]
| 도서코드 | 대출월 | 지점 | 대출수 |
|---|---|---|---|
| B001 | 202401 | 중앙 | 30 |
| B001 | 202401 | 분관 | 45 |
| B001 | 202401 | NULL | 75 |
| B001 | 202402 | 중앙 | 40 |
| B001 | 202402 | 분관 | 35 |
| B001 | 202402 | NULL | 75 |
| B002 | 202401 | 중앙 | 20 |
| B002 | 202401 | 분관 | 25 |
| B002 | 202401 | NULL | 45 |
| B002 | 202402 | 중앙 | 22 |
| B002 | 202402 | 분관 | 28 |
| B002 | 202402 | NULL | 50 |
①
SELECT 도서코드, 대출월, 지점,
SUM(대출수) AS 대출수
FROM 대출현황
GROUP BY 도서코드, 대출월, CUBE (지점);
②
SELECT 도서코드, 대출월, 지점,
SUM(대출수) AS 대출수
FROM 대출현황
GROUP BY CUBE (도서코드, 대출월, 지점);
③
SELECT 도서코드, 대출월, 지점,
SUM(대출수) AS 대출수
FROM 대출현황
GROUP BY ROLLUP (도서코드, 지점), 대출월;
④
SELECT 도서코드, 대출월, 지점,
SUM(대출수) AS 대출수
FROM 대출현황
GROUP BY ROLLUP (도서코드, 대출월, 지점);
정답 및 해설 보기
정답 ①
실행 결과는 도서코드·대출월을 그대로 고정한 채, 지점에 대해서만 소계(지점 = NULL) 행이 하나씩 추가된 모습이다. GROUP BY 도서코드, 대출월, CUBE (지점)은 도서코드·대출월을 일반 기준으로 깔고 지점 한 칼럼에만 CUBE를 적용하므로, [지점별 데이터] + [지점을 묶은 소계] 두 가지가 나와 결과와 정확히 일치한다.
오답 ② CUBE(세 칼럼)는 도서코드 소계·대출월 소계·전체 총계까지 모두 만든다. ③ ROLLUP(도서코드, 지점)은 기준이 꼬여 대출월 단위 총계가 끼어든다. ④ ROLLUP(세 칼럼)은 도서코드 소계·전체 총계까지 생성한다.
🔑 암기 GROUP BY A, B, CUBE(C) = A·B 고정 + C에 대한 집계만 추가.
문 32. 아래 SQL의 실행 결과는? 🎯 고난도
[PRODUCT]
| PNAME |
|---|
| TV |
| PC |
| PHONE |
| DESK |
SELECT COUNT(*) CNT
FROM PRODUCT
HAVING COUNT(*) > 4;
- ① 0
- ② 1
- ③ 오류가 발생한다.
- ④ 공집합
정답 및 해설 보기
정답 ④
GROUP BY가 없어도 집계 함수가 있으면 테이블 전체를 하나의 그룹으로 보고 HAVING을 적용할 수 있어 오류는 나지 않는다. PRODUCT는 4행이라 COUNT(*) = 4인데, HAVING COUNT(*) > 4는 거짓이므로 유일한 그룹이 탈락한다. 그룹이 통째로 사라지면 출력할 행이 없어 0이 아니라 공집합(빈 결과)이 된다. 실행하면 한 행도 반환되지 않음을 검산했다.
⚠️ 함정 GROUP BY 없는 HAVING이 거짓이면 결과는 0이 아니라 공집합(no rows).
문 33. 아래 SQL에 대한 설명으로 가장 적절한 것은?
[테이블]
학생(학번, 이름, 학년, 장학금, 전공)
강좌(강좌코드, 강좌명)
수강(학번, 강좌코드)
* 수강 테이블의 학번과 강좌코드는 각각 학생 테이블과
강좌 테이블을 참조하는 외래 키이다.
WITH X AS (
SELECT C.강좌코드,
C.강좌명,
SUM(S.장학금) AS 총장학금
FROM 강좌 C
JOIN 수강 E ON C.강좌코드 = E.강좌코드
JOIN 학생 S ON S.학번 = E.학번
GROUP BY C.강좌코드, C.강좌명
)
SELECT X1.강좌코드, X1.강좌명, X1.총장학금
FROM X X1
WHERE X1.총장학금 = (
SELECT MAX(총장학금) FROM X);
- ① 각 강좌를 수강하는 학생들의 장학금 총합이 가장 큰 강좌를 반환한다.
- ② 각 강좌의 평균 장학금이 가장 높은 강좌를 반환한다.
- ③ 모든 학생 중 장학금이 가장 큰 학생이 수강하는 강좌를 반환한다.
- ④ 각 강좌의 수강 인원수가 가장 많은 강좌를 반환한다.
정답 및 해설 보기
정답 ①
WITH 절 X는 강좌·수강·학생을 조인한 뒤 GROUP BY 강좌코드, 강좌명으로 묶어 SUM(장학금)을 구하므로, 강좌별 수강생 장학금 총합을 담는다. 메인쿼리는 WHERE 총장학금 = (SELECT MAX(총장학금) FROM X)로 그중 총합이 가장 큰 강좌만 남긴다. 따라서 ①이 정답이다.
오답 ② 평균이 아니라 SUM(총합)이다. ③ 학생 단위가 아니라 강좌 단위 집계다. ④ 인원수(COUNT)가 아니라 장학금 총합이다.
🔑 암기 WITH = 임시 결과 집합 / SUM + MAX 조합 = 그룹 총합이 가장 큰 그룹 추출.
문 34. 아래 SQL의 실행 결과는? 🎯 고난도
[SALES]
| STORE | CATEGORY | AMOUNT |
|---|---|---|
| S1 | A | 100 |
| S1 | A | 150 |
| S1 | B | 200 |
| S2 | A | 50 |
| S2 | B | NULL |
| S3 | B | 300 |
SELECT STORE,
CATEGORY,
SUM(AMOUNT) AS TOTAL
FROM SALES
GROUP BY ROLLUP (STORE, CATEGORY)
HAVING GROUPING(STORE)
+ GROUPING(CATEGORY) != 1;
①
| STORE | CATEGORY | TOTAL |
|---|---|---|
| S1 | A | 250 |
| S1 | B | 200 |
| S2 | A | 50 |
| S2 | B | 0 |
| S3 | B | 300 |
②
| STORE | CATEGORY | TOTAL |
|---|---|---|
| S1 | NULL | 450 |
| S2 | NULL | 50 |
| S3 | NULL | 300 |
| NULL | NULL | 800 |
③
| STORE | CATEGORY | TOTAL |
|---|---|---|
| S1 | A | 250 |
| S1 | B | 200 |
| S2 | A | 50 |
| S2 | B | NULL |
| S3 | B | 300 |
| NULL | NULL | 800 |
④
| STORE | CATEGORY | TOTAL |
|---|---|---|
| S1 | NULL | 450 |
| S2 | NULL | 50 |
| S3 | NULL | 300 |
정답 및 해설 보기
정답 ③
ROLLUP(STORE, CATEGORY)은 상세 행·STORE별 소계·전체 합계를 만든다. GROUPING 함수는 그 칼럼이 집계되어 NULL이 된 행이면 1, 원래 데이터면 0을 반환한다.
- 상세 행 → (0, 0), 합 0 →
!= 1참 → 출력 - STORE별 소계 → (0, 1), 합 1 →
!= 1거짓 → 제외 - 전체 합계 → (1, 1), 합 2 →
!= 1참 → 출력
따라서 중간 소계만 빠지고 상세 행 + 전체 합계(NULL, NULL, 800)가 남는다. 이때 S2-B는 AMOUNT가 NULL뿐이라 SUM도 NULL이다(0이 아님). 실행으로 검산했다.
⚠️ 함정 SUM은 NULL만 모이면 0이 아니라 NULL을 반환한다(①의 S2-B = 0은 오답).
문 35. GROUPING SETS에 대한 설명으로 가장 적절하지 않은 것은?
- ① GROUPING SETS의 결과를 정렬하려면 ORDER BY 절을 사용해야 한다.
- ② GROUPING SETS는 여러 GROUP BY 결과를 합친 것과 동일한 집계 효과를 제공한다.
- ③ GROUPING SETS는 인수의 나열 순서에 따라 결과가 자동으로 정렬된다.
- ④ GROUPING SETS는 ROLLUP이나 CUBE와 함께 사용할 수 있다.
정답 및 해설 보기
정답 ③
관계형 데이터베이스는 ORDER BY를 명시하지 않으면 출력 순서를 보장하지 않는다. GROUPING SETS도 인수의 나열 순서대로 자동 정렬되지 않으므로, 정렬이 필요하면 ORDER BY를 명시해야 한다. 따라서 ③이 틀렸다.
오답 ① 정렬은 ORDER BY로, ② 여러 GROUP BY를 UNION ALL한 효과, ④ ROLLUP·CUBE와 함께 사용 가능 — 모두 정확하다.
⚠️ 함정 "자동으로 정렬된다"는 표현은 거의 항상 오답이다. 순서는 ORDER BY로만 보장된다.
문 36. 아래 SQL의 실행 결과는?
[사원]
| 부서 | 이름 | 연봉 |
|---|---|---|
| A | 김철수 | 5000 |
| A | 박영희 | 3000 |
| B | 최민수 | 7000 |
| B | 정하나 | 6000 |
| C | 오지훈 | 4000 |
| C | 유미나 | 2000 |
SELECT 부서, 이름, COL2, COL3
FROM (
SELECT 부서, 이름, 연봉,
ROW_NUMBER() OVER (
PARTITION BY 부서
ORDER BY 연봉 DESC
) AS COL1,
SUM(연봉) OVER (
PARTITION BY 부서
ORDER BY 연봉 DESC
RANGE BETWEEN
UNBOUNDED PRECEDING
AND CURRENT ROW
) AS COL2,
MAX(연봉) OVER (
ORDER BY 부서, 연봉 DESC
ROWS BETWEEN
UNBOUNDED PRECEDING
AND CURRENT ROW
) AS COL3
FROM 사원
)
WHERE COL1 = 2
ORDER BY 1;
①
| 부서 | 이름 | COL2 | COL3 |
|---|---|---|---|
| A | 박영희 | 8000 | 5000 |
| B | 정하나 | 13000 | 7000 |
| C | 유미나 | 6000 | 7000 |
②
| 부서 | 이름 | COL2 | COL3 |
|---|---|---|---|
| A | 김철수 | 5000 | 3000 |
| B | 최민수 | 7000 | 6000 |
| C | 오지훈 | 4000 | 2000 |
③
| 부서 | 이름 | COL2 | COL3 |
|---|---|---|---|
| A | 박영희 | 8000 | 7000 |
| B | 정하나 | 13000 | 7000 |
| C | 유미나 | 6000 | 7000 |
④
| 부서 | 이름 | COL2 | COL3 |
|---|---|---|---|
| A | 김철수 | 5000 | 5000 |
| B | 최민수 | 7000 | 7000 |
| C | 오지훈 | 4000 | 7000 |
정답 및 해설 보기
정답 ①
WHERE COL1 = 2는 부서별 연봉 2위를 뽑으므로 박영희(A)·정하나(B)·유미나(C)가 출력된다. COL2는 부서별 누적 합계라 박영희 = 5000 + 3000 = 8000, 정하나 = 7000 + 6000 = 13000, 유미나 = 4000 + 2000 = 6000이다. COL3은 PARTITION BY가 없어 전체를 부서 오름차순·연봉 내림차순으로 줄 세운 누적 최댓값으로, 박영희 시점 5000, 정하나 시점 7000, 유미나 시점 7000이다. 결과는 8000/5000·13000/7000·6000/7000이며 실행으로 검산했다.
🔑 암기 누적 프레임 UNBOUNDED PRECEDING AND CURRENT ROW = 처음부터 현재 행까지. PARTITION BY 유무가 누적 범위를 가른다.
문 37. 데이터 조작어에 해당하지 않는 명령어는?
- ① INSERT
- ② CREATE
- ③ UPDATE
- ④ DELETE
정답 및 해설 보기
정답 ②
CREATE는 테이블 같은 객체를 정의하는 데이터 정의어(DDL)다. INSERT·UPDATE·DELETE(그리고 SELECT·MERGE)는 데이터를 다루는 데이터 조작어(DML)다.
🔑 암기 DDL = CREATE·ALTER·DROP·RENAME·TRUNCATE / DML = SELECT·INSERT·UPDATE·DELETE·MERGE / DCL = GRANT·REVOKE / TCL = COMMIT·ROLLBACK·SAVEPOINT.
문 38. 아래 SQL의 실행 결과는?
[TBL]
| NO |
|---|
| 10 |
| 20 |
| 30 |
| 40 |
| 50 |
| 60 |
SELECT GROUP_NO,
MIN(NO) AS MIN_NO,
MAX(NO) AS MAX_NO
FROM (
SELECT NO,
NTILE(3) OVER (ORDER BY NO)
AS GROUP_NO
FROM TBL
) X
GROUP BY GROUP_NO
ORDER BY GROUP_NO;
①
| GROUP_NO | MIN_NO | MAX_NO |
|---|---|---|
| 1 | 10 | 30 |
| 2 | 30 | 50 |
| 3 | 50 | 60 |
②
| GROUP_NO | MIN_NO | MAX_NO |
|---|---|---|
| 1 | 10 | 40 |
| 2 | 30 | 50 |
| 3 | 50 | 60 |
③
| GROUP_NO | MIN_NO | MAX_NO |
|---|---|---|
| 1 | 20 | 20 |
| 2 | 40 | 40 |
| 3 | 60 | 60 |
④
| GROUP_NO | MIN_NO | MAX_NO |
|---|---|---|
| 1 | 10 | 20 |
| 2 | 30 | 40 |
| 3 | 50 | 60 |
정답 및 해설 보기
정답 ④
NTILE(3)은 정렬된 6개 행을 3개의 버킷으로 균등 분할해 그룹당 2개씩 배정한다. 그룹 1 = {10, 20}, 그룹 2 = {30, 40}, 그룹 3 = {50, 60}이다. 그룹별 MIN·MAX는 (10, 20)·(30, 40)·(50, 60)이며 실행으로 검산했다.
🔑 암기 NTILE(N) = 전체를 N개 버킷으로 균등 분할해 버킷 번호 부여.
문 39. 아래 SQL의 실행 결과는? (단, DBMS는 오라클로 가정함)
SELECT COUNT(*)
FROM DUAL
START WITH LEVEL = 3
CONNECT BY LEVEL <= 4;
- ① 0
- ② 1
- ③ 2
- ④ 공집합
정답 및 해설 보기
정답 ①
계층형 질의에서 루트 노드의 LEVEL은 항상 1이다. START WITH LEVEL = 3은 시작점부터 1 = 3이라는 거짓 조건을 거니 루트가 하나도 만들어지지 않아 계층이 전개되지 않고 조회 행이 0건이다. 다만 그룹화하지 않은 COUNT(*)는 조회 행이 없을 때 공집합이 아니라 숫자 0을 반환한다(일반 칼럼이었다면 공집합). 따라서 0이며 실행으로 검산했다.
⚠️ 함정 루트 LEVEL은 1 → START WITH LEVEL = 3은 전개 불가. 그룹 없는 COUNT(*)는 0건이면 0(공집합 아님).
문 40. 아래 SQL의 실행 결과는? (단, DBMS는 오라클로 가정함)
[RECORDS]
| DEPT | MON | CNT |
|---|---|---|
| Sales | Apr | 10 |
| Sales | May | NULL |
| Sales | Jun | 15 |
| HR | Apr | NULL |
| HR | May | 8 |
| HR | Jun | NULL |
| RnD | Apr | 5 |
| RnD | May | 6 |
| RnD | Jun | 7 |
SELECT DEPT, APR, MAY, JUN
FROM (
SELECT DEPT, MON, CNT
FROM RECORDS
)
PIVOT (
SUM(CNT)
FOR MON IN (
'Apr' AS APR,
'May' AS MAY,
'Jun' AS JUN
)
)
ORDER BY DEPT;
①
| DEPT | APR | MAY | JUN |
|---|---|---|---|
| HR | 0 | 8 | 0 |
| RnD | 5 | 6 | 7 |
| Sales | 10 | 0 | 15 |
②
| DEPT | APR | MAY | JUN |
|---|---|---|---|
| HR | NULL | 8 | NULL |
| RnD | 5 | 6 | 7 |
| Sales | 10 | NULL | 15 |
③
| DEPT | APR | MAY | JUN |
|---|---|---|---|
| HR | NULL | 8 | NULL |
| RnD | 10 | NULL | 15 |
| Sales | 5 | 6 | 7 |
④
| DEPT | APR | MAY | JUN |
|---|---|---|---|
| HR | NULL | NULL | NULL |
| RnD | 5 | 6 | NULL |
| Sales | 10 | NULL | 15 |
정답 및 해설 보기
정답 ②
PIVOT은 SUM(CNT)를 DEPT별로 모아 Apr·May·Jun 열로 펼친다. PIVOT 절에 없는 DEPT가 자동으로 행 그룹 기준이 된다. 각 DEPT·MON 조합이 한 건씩이라 CNT 값이 그대로 들어가고, 원본이 NULL이면 결과도 NULL이다(NVL을 씌우지 않는 한 0이 아니다). 따라서 HR(NULL, 8, NULL)·RnD(5, 6, 7)·Sales(10, NULL, 15)이고, ORDER BY DEPT로 HR → RnD → Sales 순이다. 실행으로 검산했다.
⚠️ 함정 PIVOT에서 매칭 데이터가 없으면 0이 아니라 NULL이 들어간다(①은 0으로 바꿔 오답).
문 41. 아래 SQL의 실행 결과는?
SELECT REGEXP_INSTR('AB1CD2EF3GH',
'[A-Z]{2}[0-9]', 1, 2)
FROM DUAL;
- ① 1
- ② 3
- ③ 4
- ④ 7
정답 및 해설 보기
정답 ③
패턴 [A-Z]{2}[0-9]는 '대문자 2개 + 숫자 1개'다. 'AB1CD2EF3GH'에서 매칭은 AB1(시작 위치 1)·CD2(시작 위치 4)·EF3(시작 위치 7)이다. 함수 인자 1, 2는 1번째 위치부터 검색해 2번째 매칭의 시작 위치를 반환하라는 뜻이므로 CD2의 시작 위치 4가 나온다. 실행으로 검산했다.
🔑 암기 REGEXP_INSTR(문자열, 패턴, 시작위치, N번째매칭) = N번째 매칭의 시작 위치 반환.
문 42. 아래 SQL의 빈칸 ㉠에 들어갔을 때 실행 결과로 NULL이 출력되는 것은? (단, DBMS는 오라클로 가정함) 🎯 고난도
SELECT
REGEXP_SUBSTR(' ㉠ ', '^\D{2}\d{3}$')
FROM DUAL;
- ① AB012
- ② 9X123
- ③ _A999
- ④ Z-787
정답 및 해설 보기
정답 ②
패턴 ^\D{2}\d{3}$는 '숫자가 아닌 문자(\D) 2개 + 숫자(\d) 3개'로 정확히 5글자다. ① AB012(문자 2 + 숫자 3), ③ _A999(특수기호·문자도 \D라 문자 2 + 숫자 3), ④ Z-787(문자 2 + 숫자 3)은 모두 매칭된다. ② 9X123은 첫 글자가 숫자라 ^\D{2} 조건을 위반해 매칭에 실패하고 NULL이 반환된다. 실행으로 9X123만 NULL임을 검산했다.
🔑 암기 \d = 숫자 / \D = 숫자가 아닌 문자(기호 포함) / ^ = 시작 / $ = 끝.
문 43. 아래 SQL의 실행 결과는? (단, DBMS는 오라클로 가정함) 🎯 고난도
SELECT '''X''Y''' AS R1
FROM DUAL;
- ① X'Y
- ② 'X'Y'
- ③ 'X''Y'
- ④ ''X'Y''
정답 및 해설 보기
정답 ②
오라클에서 문자열을 감싸는 양 끝 따옴표 안의 작은따옴표 두 개('')는 실제 따옴표 하나(')로 해석된다. '''X''Y'''를 왼쪽부터 풀면 맨 앞 '(시작), ''→', X, ''→', Y, ''→', 맨 뒤 '(끝)이 되어 'X'Y'가 출력된다. 실행으로 검산했다.
🔑 암기 문자열 안에서 작은따옴표 1개를 출력하려면 ''(두 개 연속)로 적는다.
문 44. 아래 SQL에 대한 설명으로 가장 적절한 것은? (단, DBMS는 오라클로 가정함)
DROP TABLE T1 CASCADE CONSTRAINTS;
- ① T1 테이블의 데이터만 모두 삭제되고, 테이블 구조는 남는다.
- ② T1 테이블과 T1 테이블을 참조하는 자식 테이블이 함께 삭제된다.
- ③ T1 테이블과 T1 테이블의 부모 테이블이 함께 삭제된다.
- ④ T1 테이블과 T1 테이블을 참조하는 외래 키 제약 조건이 함께 삭제된다.
정답 및 해설 보기
정답 ④
CASCADE CONSTRAINTS는 T1을 삭제하면서, T1을 참조하던 다른 테이블의 외래 키 제약 조건까지 함께 제거한다. 자식 테이블의 데이터나 테이블 자체가 아니라 '제약 조건이라는 연결 끈'만 끊는다.
오답 ① 데이터만 지우고 구조를 남기는 것은 TRUNCATE·DELETE다. ② 자식 테이블 자체는 삭제되지 않는다. ③ 부모 테이블은 삭제되지 않는다.
🔑 암기 CASCADE CONSTRAINTS = 참조하는 외래 키 '제약 조건'을 연쇄 삭제(테이블·데이터는 그대로).
문 45. 아래 SQL에 대한 설명으로 가장 적절하지 않은 것은? (단, DBMS는 오라클로 가정함)
SELECT 과목코드, 과목명
FROM 과목
WHERE 과목코드 NOT IN (700,800)
START WITH 상위과목코드 IS NULL
CONNECT BY 상위과목코드 = PRIOR 과목코드;
- ① 상위과목에서 하위과목으로 전개되는 순방향 계층형 질의이다.
- ② 동일한 계층 구조는 재귀적 CTE(Common Table Expression)로도 구현할 수 있다.
- ③ 무한 루프를 방지하기 위해 CONNECT BY NOCYCLE 옵션을 지정할 수 있다.
- ④ 상위과목코드가 NULL이면서 과목코드가 700 또는 800인 경우 전개가 중단된다.
정답 및 해설 보기
정답 ④
계층형 질의에서 WHERE 절은 계층 전개가 모두 끝난 뒤 최종 결과에서 특정 행만 솎아내는 필터다. WHERE 과목코드 NOT IN (700, 800)은 700·800 과목 본인만 결과에서 빠질 뿐, 그 아래 자식 노드는 이미 전개되어 살아남는다. 전개 자체를 끊으려면(가지치기) 조건이 WHERE가 아니라 CONNECT BY 절에 있어야 한다. 따라서 "전개가 중단된다"는 ④가 틀렸다.
오답 ① 상위 → 하위 순방향, ② 재귀 CTE로 동일 구현 가능, ③ NOCYCLE로 무한 루프 방지 — 모두 정확하다.
⚠️ 함정 계층형 WHERE = 전개 후 결과 필터(가지치기 아님). 가지치기는 CONNECT BY 조건으로.
문 46. 아래 SQL의 실행 결과는?
CREATE TABLE T3 (NO NUMBER);
INSERT INTO T3 VALUES (1);
INSERT INTO T3 VALUES (2);
SAVEPOINT SV;
UPDATE T3 SET NO = 5 WHERE NO = 1;
SAVEPOINT SV;
INSERT INTO T3 VALUES (0);
SAVEPOINT SV;
DELETE FROM T3
WHERE NO BETWEEN 2 AND 5;
ROLLBACK TO SV;
UPDATE T3 SET NO = 1 WHERE NO = 0;
DELETE FROM T3 WHERE NO = 2;
INSERT INTO T3 VALUES (3);
COMMIT;
SELECT MIN(NO) FROM T3;
- ① 0
- ② 1
- ③ 3
- ④ 5
정답 및 해설 보기
정답 ②
같은 이름 SV로 SAVEPOINT를 다시 지정하면 이전 SV는 사라지고 최신 시점으로 덮어쓰인다. INSERT 1·2 → SV → UPDATE(1→5)로 {5, 2} → SV(덮어씀) → INSERT 0으로 {5, 2, 0} → SV(다시 덮어씀, 최종 SV 시점 = {5, 2, 0})가 된다. 이후 DELETE WHERE NO BETWEEN 2 AND 5로 5·2가 지워져 {0}이 되지만, ROLLBACK TO SV로 최신 SV 시점인 {5, 2, 0}으로 복구된다. 다시 UPDATE 0→1로 {5, 2, 1}, DELETE NO=2로 {5, 1}, INSERT 3으로 {5, 1, 3}이 되고 COMMIT한다. 최종 {5, 1, 3}의 MIN(NO)는 1이며 실행으로 검산했다.
🔑 암기 같은 이름 SAVEPOINT 재지정 = 최신 시점으로 덮어쓰기 / ROLLBACK TO = 그 지점까지만 부분 롤백.
문 47. 제약 조건에 대한 설명으로 가장 적절하지 않은 것은?
- ① 기본 키 제약을 정의하면 DBMS는 UNIQUE 인덱스를 만들며 기본 키 칼럼에는 NULL을 넣을 수 있다.
- ② UNIQUE 제약은 칼럼 값의 중복을 막지만 NULL은 허용된다.
- ③ 외래 키 제약은 다른 테이블의 기본 키나 UNIQUE 칼럼을 참조하여 무결성을 보장한다.
- ④ CHECK 제약은 행 입력이나 수정 시 조건식이 TRUE인지 검사하여 데이터의 유효성을 제한한다.
정답 및 해설 보기
정답 ①
기본 키(Primary Key)는 유일성(UNIQUE)과 NOT NULL이 함께 강제되며, 이를 위해 DBMS가 고유 인덱스를 자동 생성한다. 따라서 기본 키 칼럼에는 NULL을 넣을 수 없다. "NULL을 넣을 수 있다"는 ①이 틀렸다.
오답 ② UNIQUE는 중복은 막지만 NULL은 허용, ③ 외래 키는 기본 키·UNIQUE 칼럼 참조, ④ CHECK는 조건식 TRUE만 허용 — 모두 정확하다.
🔑 암기 PRIMARY KEY = UNIQUE + NOT NULL(NULL 불가) / UNIQUE = 중복 불가, NULL 허용.
문 48. 아래 SQL을 모두 실행할 경우, PRODUCT 테이블에 대한 DELETE 권한을 가지고 있는 사용자는? 🎯 고난도
DBA: GRANT SELECT, INSERT, DELETE
ON PRODUCT TO A1;
DBA: GRANT DELETE
ON PRODUCT TO A2
WITH GRANT OPTION;
A2: GRANT DELETE
ON PRODUCT TO A3;
DBA: REVOKE DELETE
ON PRODUCT FROM A2 RESTRICT;
- ① DBA, A1
- ② DBA, A1, A2
- ③ DBA, A1, A3
- ④ DBA, A1, A2, A3
정답 및 해설 보기
정답 ④
DBA가 A1에게 DELETE를, A2에게는 WITH GRANT OPTION과 함께 DELETE를 부여하자 A2가 A3에게 DELETE를 재부여한다. 이후 DBA가 REVOKE ... FROM A2 RESTRICT로 회수를 시도하는데, RESTRICT는 해당 사용자가 이미 다른 사용자에게 권한을 재부여한 이력이 있으면 회수 명령 자체를 거부(오류)한다. A2는 A3에게 권한을 준 상태라 이 REVOKE는 실패하고 아무도 권한을 잃지 않는다. 결국 DBA·A1·A2·A3 모두 DELETE 권한을 유지한다.
🔑 암기 REVOKE ... RESTRICT = 재부여 이력이 있으면 회수 명령 자체가 실패 / CASCADE = 연쇄 회수.
문 49. 아래 SQL에 대한 설명으로 가장 적절한 것은? (단, 매장ID는 매장 테이블의 기본 키이고, 상품ID는 상품 테이블의 기본 키임)
CREATE TABLE 판매 (
영수증번호 VARCHAR2(20),
매장ID NUMBER,
상품ID NUMBER,
수량 NUMBER,
CONSTRAINT sale_pk
PRIMARY KEY (영수증번호, 매장ID),
CONSTRAINT sale_fk1
FOREIGN KEY (매장ID)
REFERENCES 매장(매장ID),
CONSTRAINT sale_fk2
FOREIGN KEY (상품ID)
REFERENCES 상품(상품ID)
);
- ① 하나의 상품은 반드시 한 매장에서만 판매될 수 있다.
- ② 한 매장에서는 동일한 상품을 여러 번 판매할 수 없다.
- ③ 동일한 영수증번호가 여러 매장에서 발생할 수 있다.
- ④ 수량 칼럼은 반드시 1 이상의 값을 가져야 한다.
정답 및 해설 보기
정답 ③
기본 키가 (영수증번호, 매장ID) 복합 키라 두 칼럼의 조합만 유일하면 된다. 따라서 (1번 영수증, A매장)과 (1번 영수증, B매장)은 조합이 다르므로 PK 위반 없이 함께 들어갈 수 있다. 즉 동일한 영수증번호가 여러 매장에서 발생할 수 있다.
오답 ① 상품ID는 일반 외래 키라 여러 매장 판매를 막지 않는다. ② 영수증번호만 다르면 같은 매장에서 같은 상품을 여러 번 팔 수 있다. ④ 수량에 CHECK 제약이 없어 1 이상 강제가 없다(0·NULL도 가능).
🔑 암기 복합 기본 키 = 칼럼 조합의 유일성만 보장. 개별 칼럼 값은 중복 가능.
문 50. 아래 테이블에 대한 INSERT 구문 수행 시 오류가 발생하지 않는 SQL은?
CREATE TABLE STUDENT (
학번 NUMBER(3) PRIMARY KEY,
이름 VARCHAR2(10) NOT NULL,
학년 NUMBER(1) DEFAULT 1
);
INSERT INTO
STUDENT (학번, 이름) VALUES (101, 'Kim');
INSERT INTO
STUDENT (학번, 이름) VALUES (102, 'Lee');
①
INSERT INTO STUDENT VALUES (102, 'Park', 2);
②
INSERT INTO STUDENT (학번) VALUES (103);
③
INSERT INTO STUDENT (학번, 학년)
VALUES ('Hong', 2);
④
INSERT INTO STUDENT (학번, 이름, 학년)
VALUES (103, 'Choi', 3);
정답 및 해설 보기
정답 ④
④는 새 학번 103, 필수값 이름 'Choi', 자료형이 맞는 학년 3을 모두 채워 정상 실행된다.
오답 ① 학번 102는 이미 'Lee'가 쓰는 값이라 기본 키 중복 오류. ② 이름이 NOT NULL인데 빠져 제약 위반 오류. ③ 학번이 NUMBER(3)인데 문자열 'Hong'을 넣어 자료형 불일치 오류.
🔑 암기 INSERT 검증 3종 — 기본 키 중복·NOT NULL 누락·자료형 불일치.
합격까지
SQLD, 약점 유형이 보이나요?
초개인화 학습앱 Klue로 틀린 유형을 집중 공략하고, 에듀윌 온라인강의로 개념까지 정리하세요.
