[SQLD] SQL 개발자 기출유형 모의고사 2회
SQLD SQL 개발자 실전 모의고사

SQL 개발자 기출유형 모의고사 2회

총 50문항 · 객관식 · A4 약 1장

1 / 1
A4정답 포함
SQLD SQL 개발자 실전 모의고사모두CBT · moducbt.com

SQL 개발자 기출유형 모의고사 2회

총 50문항 · 객관식 · 정답·해설 포함
문제 1
데이터 모델링 단계 중 논리적 모델링에서 수행하는 작업으로 가장 적절한 것은?
1DBMS별 데이터 타입과 용량을 정한다
2정규화로 속성과 관계를 정제한다
3테이블스페이스와 인덱스를 정의한다
4핵심 엔터티만 추려 전사 관점을 잡는다
정답 및 해설

논리적 모델링은 개념 모델을 업무 규칙에 맞게 구체화하며 정규화로 속성과 관계를 정제하는 단계이다.

특정 DBMS 와 무관하게 키·속성·관계를 확정하므로 재사용성이 가장 높은 산출물이 나온다.

  • 테이블스페이스·인덱스 정의는 물리적 모델링에서 한다.
  • 핵심 엔터티로 전사 관점을 잡는 일은 개념적 모델링이다.
  • DBMS별 데이터 타입·용량 결정도 물리적 모델링이다.
문제 2
다음은 온라인 강의 서비스의 ERD 초안이다. 운영사에는 이 서비스를 운영하는 자사 정보 1건만 저장되며 다른 업무에서 참조하지 않는다. 엔터티 성립 조건에 비추어 엔터티로 보기 어려운 것과 그 이유를 바르게 짝지은 것은?

그림

1운영사: 인스턴스가 하나뿐이다
2수강신청: 주식별자가 두 속성이다
3강좌: 일반 속성이 두 개뿐이다
4회원: 관계가 하나만 연결된다
정답 및 해설

운영사는 자사 1건만 저장되어 인스턴스가 두 개 이상이라는 엔터티 성립 조건을 충족하지 못한다.

게다가 다른 엔터티와의 관계도 없어 업무 데이터로서 쓰임이 없으므로 설정값처럼 따로 관리하는 편이 낫다.

  • 수강신청은 회원번호·강좌코드 복합 식별자로 유일하게 구분되면 충분하다.
  • 강좌는 일반 속성이 두 개라도 속성을 가진다는 조건을 만족한다.
  • 회원은 수강신청과 관계를 맺고 있어 관계 조건을 충족한다.
문제 3
속성(Attribute)에 대한 설명으로 가장 적절한 것은?
1하나의 속성에 여러 값을 묶어 저장한다
2한 인스턴스는 속성마다 값을 하나 가진다
3한 속성은 여러 엔터티에 동시에 속한다
4속성은 엔터티 없이 단독으로 존재한다
정답 및 해설

속성은 엔터티를 설명하는 더 이상 쪼갤 수 없는 단위이며, 한 인스턴스는 각 속성에 대해 하나의 값만 가진다.

값이 여러 개라면 별도 엔터티로 분리하거나 속성을 나누어 원자성을 지켜야 한다.

  • 여러 값을 한 속성에 묶으면 제1정규형을 위반한다.
  • 속성은 반드시 어떤 엔터티에 소속되어야 의미를 가진다.
  • 하나의 속성은 하나의 엔터티에만 소속된다.
문제 4
도서관에서 한 회원은 여러 도서를 대출하고, 한 도서도 여러 회원에게 대출된다. 이 관계를 논리 모델에서 처리하는 방법으로 가장 적절한 것은?
1도서에 회원번호 속성 하나를 추가한다
2회원에 도서번호를 반복 속성으로 둔다
3대출 엔터티를 두어 1:M 둘로 푼다
4두 엔터티를 하나로 통합해 관리한다
정답 및 해설

회원과 도서는 M:N 관계이므로 논리 모델에서는 대출이라는 교차 엔터티를 두어 회원–대출, 도서–대출의 1:M 관계 둘로 해소한다.

대출에는 회원번호·도서번호가 FK 로 상속되고 대출일·반납일 같은 관계 고유 속성이 함께 놓인다.

  • 도서에 회원번호 하나만 두면 여러 회원의 대출 이력을 담지 못한다.
  • 회원에 도서번호를 반복해 두면 제1정규형을 어긴다.
  • 두 엔터티를 통합하면 회원·도서 정보가 중복된다.
문제 5
주식별자의 특성에 대한 설명으로 적절하지 않은 것은?
1유일성: 인스턴스를 유일하게 구분한다
2최소성: 여유 있게 속성을 더 포함한다
3존재성: 지정되면 반드시 값이 있다
4불변성: 지정된 값이 자주 바뀌지 않는다
정답 및 해설

최소성은 유일성을 만족하는 데 필요한 최소한의 속성으로만 주식별자를 구성해야 한다는 뜻이므로, 속성을 여유 있게 더 넣는 것은 반대 방향이다.

예를 들어 환자번호만으로 유일하다면 환자번호+환자명은 최소성을 어긴 식별자가 된다.

  • 유일성은 주식별자로 모든 인스턴스를 유일하게 구분하는 특성이다.
  • 불변성은 한번 지정된 값이 자주 변하지 않아야 한다는 특성이다.
  • 존재성은 주식별자에 반드시 값이 들어가 NULL 이 없다는 특성이다.
문제 6
BCNF(Boyce-Codd 정규형)를 만족하는 조건으로 옳은 것은?
1키가 아닌 속성 사이 종속만 없애면 된다
2모든 속성 값이 원자값이면 된다
3기본키에 대한 부분 종속을 없애면 된다
4모든 결정자가 후보키가 되어야 한다
정답 및 해설

BCNF 는 함수 종속의 모든 결정자가 후보키여야 한다는 조건으로, 제3정규형보다 강한 정규형이다.

후보키가 아닌 속성이 다른 속성을 결정하면 3NF 를 만족해도 BCNF 위반이므로 그 결정자를 기준으로 테이블을 분해한다.

  • 모든 속성 값이 원자값인 것은 제1정규형 조건이다.
  • 기본키에 대한 부분 종속 제거는 제2정규형 조건이다.
  • 키가 아닌 속성 사이의 이행 종속 제거는 제3정규형 조건이다.
문제 7
다음 ERD 에서 실선은 식별 관계, 점선은 비식별 관계이며 FK 는 부모의 주식별자를 그대로 상속한 것이다. 신청 건마다 개설된 과목의 과목명과 소속 학과명을 함께 조회할 때, 수강신청 외에 조인해야 하는 최소 테이블 조합은?

그림

1개설, 과목, 학과
2학생, 과목
3과목, 학과
4학과
정답 및 해설

수강신청은 개설의 주식별자 (학과코드, 과목번호, 학기)를 FK 로 상속받으므로 개설을 거치지 않고 과목·학과와 바로 조인하면 충분하다.

과목명은 과목에만 있어 (학과코드, 과목번호)로 과목과, 학과명은 학과코드로 학과와 조인한다.

  • 개설은 담당교수가 필요할 때만 조인하면 되므로 최소 조합이 아니다.
  • 학과만 조인하면 과목명을 얻을 수 없다.
  • 학생은 신청자 정보일 뿐 과목의 소속 학과와는 경로가 다르다.
문제 8
숙박 예약 모델의 다음 관계 중 두 엔터티의 인스턴스를 반드시 하나의 트랜잭션으로 함께 입력해야 하는 구조는?
1리뷰는 예약이 있을 때만 작성된다
2예약과 결제가 서로 필수로 참여한다
3회원은 예약 없이도 존재할 수 있다
4객실은 예약과 무관하게 등록된다
정답 및 해설

예약과 결제가 서로 필수 참여라면 어느 한쪽만 저장된 상태는 업무 규칙 위반이므로 두 인스턴스를 하나의 트랜잭션으로 함께 입력·커밋해야 한다.

한쪽만 필수인 관계는 부모를 먼저 입력해 두고 자식을 나중에 별도 트랜잭션으로 넣어도 정합성이 깨지지 않는다.

  • 예약이 없는 회원은 단독으로 입력할 수 있다.
  • 객실은 예약과 별개로 먼저 등록해 둘 수 있다.
  • 리뷰는 예약이 이미 있으면 나중에 따로 입력해도 된다.
문제 9
진료 엔터티의 속성 중 NULL 허용으로 설계하는 것이 가장 타당한 것은?
1환자번호(필수 관계의 FK)
2진료번호(주식별자)
3재진예약일(다음 방문 날짜)
4진료일시(진료 시작 시각)
정답 및 해설

재진예약일은 다음 방문이 정해지지 않은 진료에서는 값이 없을 수 있으므로 NULL 허용이 업무 규칙에 맞다.

반대로 식별자·필수 관계의 FK·업무상 반드시 생기는 값은 NOT NULL로 두어야 데이터 누락을 막는다.

  • 진료번호는 주식별자라 존재성에 따라 NULL 이 될 수 없다.
  • 진료일시는 진료가 생기는 순간 반드시 정해지는 값이다.
  • 필수 관계의 FK 인 환자번호가 NULL 이면 관계가 깨진다.
문제 10
다음 수강신청 테이블은 시퀀스로 부여한 인조식별자 신청ID 를 기본키로 쓴다. 한 학생은 같은 강좌를 한 번만 신청할 수 있을 때, 이 설계를 보완하는 방법으로 가장 적절한 것은?

수강신청

신청ID학번강좌코드신청일
12026001C102026-03-02
22026002C102026-03-02
32026001C202026-03-03
42026001C102026-03-04
1학번+강좌코드에 유니크 제약을 둔다
2신청ID 에 NOT NULL 제약을 추가한다
3신청일을 기본키로 바꾸어 사용한다
4학번 단독으로 유니크 제약을 건다
정답 및 해설

인조식별자만 기본키로 두면 같은 학생의 같은 강좌 신청이 신청ID 만 달리해 중복 입력되며, 실제로 2026001·C10 신청이 두 행 저장되었다.

본질식별자인 (학번, 강좌코드)에 유니크 제약을 걸면 인조식별자를 유지하면서도 업무상 중복을 막을 수 있다.

  • 신청일은 여러 신청이 같은 날 생기므로 유일성이 없다.
  • 신청ID 는 기본키라 이미 NOT NULL 이며 중복을 막지 못한다.
  • 학번 단독 유니크는 한 학생의 여러 강좌 신청까지 막는다.
문제 11
관계형 데이터베이스의 테이블에 대한 설명으로 적절하지 않은 것은?
1기본키로 각 행을 유일하게 식별한다
2하나의 행은 하나의 인스턴스를 뜻한다
3행 저장 순서가 조회 순서를 보장한다
4같은 열의 값은 같은 도메인을 갖는다
정답 및 해설

관계형 모델에서 테이블의 행은 순서 개념이 없는 집합이므로 저장된 순서대로 조회된다는 보장이 없고, 순서가 필요하면 ORDER BY를 써야 한다.

열은 하나의 속성으로 같은 도메인의 값을 갖고, 행은 하나의 인스턴스를 나타내며 기본키로 구분된다.

  • 같은 열의 값이 같은 도메인을 갖는 것은 테이블의 기본 성질이다.
  • 기본키는 각 행을 유일하게 식별하는 열 집합이다.
  • 행 하나는 엔터티의 인스턴스 하나에 대응한다.
문제 12
다음 SQL 에서 네 번째로 처리되는 절은?
SELECT 회원번호, COUNT(*) AS 대출건수
  FROM 대출
 WHERE 반납일 IS NULL
 GROUP BY 회원번호
HAVING COUNT(*) >= 2
 ORDER BY 대출건수 DESC;
1GROUP BY 절
2HAVING 절
3SELECT 절
4WHERE 절
정답 및 해설

SELECT 문은 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순으로 처리되므로 네 번째는 HAVING 절이다.

그래서 SELECT 절의 별칭 대출건수는 HAVING 에서 쓸 수 없고 마지막에 처리되는 ORDER BY 에서만 쓸 수 있다.

  • WHERE 절은 FROM 다음 두 번째로 처리된다.
  • GROUP BY 절은 세 번째로 처리된다.
  • SELECT 절은 HAVING 다음 다섯 번째로 처리된다.
문제 13
진료비 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

진료비

진료번호기본료검사료
1100005000
28000(null)
3(null)3000
4120002000
59000(null)
SELECT SUM(기본료 + 검사료) AS A,
       SUM(기본료) + SUM(검사료) AS B,
       COUNT(검사료) AS C
  FROM 진료비;
1
ABC
49000490003
2
ABC
29000290003
3
ABC
29000490005
4
ABC
29000490003
정답 및 해설

행 단위 덧셈은 한쪽이 NULL 이면 결과가 NULL이 되어 SUM 에서 빠지므로 A 는 두 값이 모두 있는 행의 합 15000+14000=29000이다.

B 는 열마다 NULL 을 제외하고 먼저 합한 39000+10000=49000이고, COUNT(열)은 NULL 이 아닌 3건만 센다.

  • A 를 49000으로 본 것은 NULL 을 0처럼 더한 오해다.
  • B 를 29000으로 본 것은 열별 집계가 NULL 을 먼저 제외한다는 점을 놓쳤다.
  • C 를 5로 본 것은 COUNT(*)와 COUNT(열)을 혼동한 것이다.
문제 14
예약 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

예약

예약번호인원확정인원메모
144창가
23(null)(null)
3(null)(null)(null)
452유아
SELECT 예약번호,
       COALESCE(확정인원, 인원, 0) AS P,
       NULLIF(인원, 확정인원) AS Q,
       CASE WHEN 메모 IS NULL THEN 'N' ELSE 'Y' END AS R
  FROM 예약
 ORDER BY 예약번호;
1
예약번호PQR
14(null)Y
233N
30(null)N
425Y
2
예약번호PQR
14(null)Y
23(null)N
30(null)N
425Y
3
예약번호PQR
14(null)Y
233N
30(null)N
455Y
4
예약번호PQR
144Y
233N
30(null)N
425Y
정답 및 해설

COALESCE는 왼쪽부터 처음 만나는 NULL 아닌 값을 돌려주어 예약번호 4 행은 확정인원 2, 두 값이 모두 NULL 인 예약번호 3 행은 0이 된다.

NULLIF(a, b)는 두 값이 같을 때만 NULL 이고 다르면 a 를 돌려주므로 4와 4가 같은 첫 행만 NULL, 확정인원이 NULL 인 둘째 행은 3이다.

  • 첫 행의 Q 를 4로 본 것은 같을 때 NULL 이 된다는 규칙을 뒤집은 것이다.
  • 둘째 행의 Q 를 NULL 로 본 것은 NULL 과의 비교를 같음으로 오해한 것이다.
  • 마지막 행의 P 를 5로 본 것은 COALESCE 인자 순서를 놓친 것이다.
문제 15
Oracle 기준으로, 대출일로부터 14일 뒤의 반납예정일을 다음 결과처럼 'YYYY-MM-DD' 형식 문자열로 출력하려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

대출

대출번호회원번호대출일
1112026-03-02
2122026-03-20
3112026-04-25
SELECT 대출번호,
       ( ㉠ ) AS 반납예정일
  FROM 대출
 ORDER BY 대출번호;
대출번호반납예정일
12026-03-16
22026-04-03
32026-05-09
1ADD_MONTHS(대출일, 14)
2TO_CHAR(대출일, 'YYYY-MM') || '-14'
3TO_CHAR(대출일 + 14, 'YYYY-MM-DD')
4TO_NUMBER(대출일) + 14
정답 및 해설

Oracle 에서 DATE + 숫자는 그 일수만큼 더한 날짜이므로 대출일 + 14 로 14일 뒤를 구한 다음 TO_CHAR로 'YYYY-MM-DD' 문자열을 만든다.

3월 20일은 4월 3일, 4월 25일은 5월 9일처럼 월이 바뀌는 경우도 날짜 연산이 자동으로 처리한다.

  • ADD_MONTHS 는 일이 아니라 개월 수를 더하며 결과도 문자열이 아니다.
  • 월 뒤에 '-14'를 붙이면 대출일과 무관하게 모든 행이 14일이 된다.
  • DATE 를 TO_NUMBER 로 바로 바꿀 수 없어 형변환 오류가 난다.
문제 16
Oracle 기준으로 다음 SQL 을 실행한 결과로 옳은 것은?

수강

학번강좌코드등급
2026101K1A
2026102K1B
2026103K1(null)
2026104K1C
2026105K1B
SELECT 학번,
       DECODE(등급, 'A', '우수', 'B', '보통', '미흡') AS 평가
  FROM 수강
 ORDER BY 학번;
1
학번평가
2026101우수
2026102보통
2026103미흡
2026104미흡
2026105보통
2
학번평가
2026101우수
2026102보통
2026103(null)
2026104(null)
2026105보통
3
학번평가
2026101우수
2026102보통
2026103미흡
2026104(null)
2026105보통
4
학번평가
2026101우수
2026102보통
2026103(null)
2026104미흡
2026105보통
정답 및 해설

DECODE는 등급을 검색값과 차례로 비교해 일치하는 결과를 돌려주고, 어느 것과도 일치하지 않으면 마지막 기본값 '미흡'을 돌려준다.

등급이 C 인 행과 NULL 인 행은 'A'·'B' 어느 쪽과도 일치하지 않으므로 둘 다 '미흡'이 된다.

  • NULL 행만 NULL 로 둔 것은 기본값이 NULL 에도 적용된다는 점을 놓쳤다.
  • C 행만 NULL 로 둔 것은 기본값을 NULL 전용으로 오해했다.
  • 두 행 모두 NULL 로 둔 것은 기본값 인자를 무시했다.
문제 17
WHERE 절 조건에 대한 설명으로 적절하지 않은 것은?
1= 비교에서 % 는 일반 문자로 본다
2ESCAPE 로 % 문자 자체를 찾을 수 있다
3IS NOT NULL 은 값이 있는 행을 찾는다
4NOT BETWEEN 은 양 끝값을 포함한다
정답 및 해설

NOT BETWEEN a AND b는 BETWEEN 의 부정이므로 a 미만이거나 b 초과인 행만 찾고, 양 끝값 a·b 는 결과에서 빠진다.

와일드카드 % 와 _ 는 LIKE 에서만 패턴으로 해석되며, 그 문자 자체를 찾을 때는 ESCAPE 로 지정한 문자를 앞에 붙인다.

  • LIKE '%10\%%' ESCAPE '\' 처럼 쓰면 % 기호 자체를 검색한다.
  • IS NOT NULL 은 NULL 이 아닌, 값이 들어 있는 행을 고른다.
  • = 연산자는 패턴 비교가 아니어서 % 를 글자 그대로 비교한다.
문제 18
[회원] 테이블에 다음 SQL 을 실행했을 때 조회되는 결과는?

[회원]

회원번호등급포인트
1VIP300
2일반450
3(null)200
4일반(null)
5(null)800
6VIP100
7일반500
8(null)(null)
SELECT 회원번호, 등급
  FROM 회원
 WHERE COALESCE(등급, '일반') <> 'VIP'
   AND 포인트 < 500
 ORDER BY 회원번호;
1
회원번호등급
2일반
3(null)
2
회원번호등급
2일반
3일반
3
회원번호등급
2일반
3(null)
4일반
8(null)
4
회원번호등급
2일반
정답 및 해설

등급이 NULL 인 행은 COALESCE 로 '일반'이 되어 첫 조건이 참이지만, 포인트가 NULL 이면 UNKNOWN 이라 AND 결과가 참이 되지 않아 회원 2·3 만 남는다.

회원 4·8 은 포인트 비교가 UNKNOWN 이라 빠지고 회원 5·7 은 포인트가 500 이상이며, SELECT 의 등급은 바꾸지 않았으므로 회원 3 의 등급은 NULL 그대로 출력된다.

  • 회원 3 의 등급을 '일반'으로 보인 표는 WHERE 의 COALESCE 가 출력값까지 바꾼다고 본 것이다.
  • 회원 2 만 남긴 표는 등급 NULL 행을 COALESCE 없이 비교한 결과다.
  • 회원 4·8 까지 넣은 표는 NULL 과의 비교를 참으로 계산한 것이다.
문제 19
대출 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

대출

대출번호회원번호연체일반납일
11102026-03-10
212352026-03-20
31310(null)
411(null)(null)
51425(null)
SELECT COUNT(*) AS CNT, SUM(연체일) AS S, MAX(연체일) AS M
  FROM 대출
 WHERE 반납일 IS NULL
   AND 연체일 > 30;
1
CNTSM
000
2
CNTSM
13535
3
CNTSM
0(null)(null)
4
CNTSM
정답 및 해설

GROUP BY 가 없는 집계 쿼리는 조건을 만족하는 행이 없어도 항상 한 행을 돌려주며, 이때 COUNT(*)는 0, SUM·MAX 는 NULL이다.

반납일이 NULL 인 대출은 연체일이 10, NULL, 25뿐이라 30 초과가 없고, 연체일 35인 대출은 이미 반납되어 WHERE 에서 제외된다.

  • 결과 행이 없다고 본 것은 GROUP BY 가 있을 때의 동작과 혼동한 것이다.
  • SUM·MAX 를 0으로 본 것은 빈 집합의 집계가 NULL 이라는 점을 놓쳤다.
  • 연체일 35인 행을 센 것은 반납일 조건을 빠뜨린 것이다.
문제 20
수강(학번, 강좌코드, 점수) 테이블에 대해 다음 SQL 을 실행할 때 오류가 발생하는 것을 모두 고른 것은?
㉠ SELECT 강좌코드, AVG(점수) FROM 수강
   GROUP BY 강좌코드 HAVING AVG(점수) >= 80;
㉡ SELECT 강좌코드, COUNT(*) FROM 수강
   WHERE COUNT(*) >= 2 GROUP BY 강좌코드;
㉢ SELECT 강좌코드 FROM 수강 WHERE 점수 >= 60
   GROUP BY 강좌코드 HAVING COUNT(*) >= 2;
㉣ SELECT 학번, MAX(점수) FROM 수강
   GROUP BY 강좌코드;
1㉡
2㉡, ㉣
3㉢, ㉣
4㉠, ㉡
정답 및 해설

WHERE 절은 그룹이 만들어지기 전에 행 단위로 처리되므로 집계 함수를 WHERE 에 쓸 수 없어 ㉡은 오류이며, 집계 조건은 HAVING 에 써야 한다.

㉣은 GROUP BY 에 없는 학번을 집계 없이 SELECT 해 그룹당 한 값을 정할 수 없으므로 오류가 난다.

  • ㉠은 집계 조건을 HAVING 에 둔 올바른 구문이다.
  • ㉢은 행 조건은 WHERE, 그룹 조건은 HAVING 에 둔 정상 구문이다.
  • ㉡만 고르면 GROUP BY 열 규칙을 어긴 ㉣을 놓친다.
문제 21
예약 테이블에 대해 다음 SQL 을 실행했을 때 결과 행 수는?

예약

예약번호지점객실유형예약일
1강남디럭스2026-03-02
2강남디럭스2026-03-05
3강남(null)2026-03-07
4강남(null)2026-03-09
5홍대스탠다드2026-02-27
6홍대스탠다드2026-03-03
7홍대디럭스2026-03-04
8(null)디럭스2026-03-06
9홍대(null)2026-02-20
SELECT 지점, 객실유형, COUNT(*) AS 건수
  FROM 예약
 WHERE 예약일 >= DATE '2026-03-01'
 GROUP BY 지점, 객실유형
 ORDER BY 지점, 객실유형;
14행
25행
36행
43행
정답 및 해설

WHERE 로 3월 1일 이전 예약 두 건을 먼저 제외한 뒤 (지점, 객실유형) 조합으로 묶으며, GROUP BY 는 NULL 도 하나의 그룹으로 만든다.

남는 그룹은 (강남, 디럭스), (강남, NULL), (홍대, 스탠다드), (홍대, 디럭스), (NULL, 디럭스)로 5개이다.

  • 4개는 NULL 그룹 하나를 빠뜨린 계산이다.
  • 3개는 NULL 이 들어간 그룹을 모두 제외한 계산이다.
  • 6개는 WHERE 를 무시해 (홍대, NULL) 그룹까지 센 계산이다.
문제 22
NULL 값의 정렬 위치에 대한 설명으로 옳은 것은?
1DESC 정렬에서도 NULL 은 항상 마지막이다
2Oracle 오름차순은 NULL 이 맨 뒤다
3NULLS FIRST 는 DESC 에만 쓴다
4SQL Server 는 NULL 을 최댓값으로 본다
정답 및 해설

Oracle 은 NULL 을 가장 큰 값처럼 다루어 오름차순이면 맨 뒤, 내림차순이면 맨 앞에 둔다.

SQL Server 는 반대로 NULL 을 가장 작은 값으로 보아 오름차순에서 맨 앞에 오며, Oracle 은 NULLS FIRST/LAST로 위치를 직접 정할 수 있다.

  • SQL Server 는 NULL 을 최솟값으로 취급한다.
  • NULLS FIRST 는 오름차순·내림차순 모두에 쓸 수 있다.
  • Oracle 내림차순에서는 NULL 이 맨 앞에 온다.
문제 23
등가 조인(EQUI JOIN)에 대한 설명으로 옳은 것은?
1= 연산자로 두 테이블의 값을 비교한다
2BETWEEN 으로 범위를 비교한다
3PK 와 FK 사이에서만 조인할 수 있다
4조인 키가 NULL 인 행도 결과에 남는다
정답 및 해설

등가 조인은 두 테이블의 조인 열을 = 연산자로 비교해 값이 같은 행끼리만 결합하는 방식이다.

NULL 은 어떤 값과도 같지 않으므로 조인 키가 NULL 인 행은 짝을 찾지 못해 결과에서 빠진다.

  • 조인 키가 NULL 인 행을 남기려면 OUTER JOIN 을 써야 한다.
  • 값만 비교할 수 있으면 PK·FK 관계가 없어도 조인할 수 있다.
  • BETWEEN 처럼 범위로 비교하는 것은 비등가 조인이다.
문제 24
다음 SQL 은 세 테이블을 조인하면서 대출과 도서 사이의 조인 조건을 빠뜨렸다. 실행 결과의 행 수는?

회원

회원번호이름
1한지수
2오민재
3서가은

대출

대출번호회원번호도서번호
1011B1
1021B2
1032B3
1043B1
1059B4

도서

도서번호제목분류
B1SQL 입문IT
B2봄날소설
B3파이썬 기초IT
B4고려사역사
SELECT M.이름, B.제목
  FROM 회원 M, 대출 L, 도서 B
 WHERE M.회원번호 = L.회원번호
   AND B.분류 = 'IT'
 ORDER BY M.이름, B.제목;
116행
210행
33행
48행
정답 및 해설

세 테이블 조인에는 조인 조건이 최소 2개(N−1) 필요한데 대출–도서 조건이 빠져 도서와는 카티션 곱이 생긴다.

회원과 짝이 맞는 대출은 회원번호 9 를 뺀 4건이고, 이 4건이 IT 도서 2권과 모두 짝지어 4 × 2 = 8행이 된다.

  • 3행은 대출–도서 조건까지 있을 때의 정상 조인 결과이다.
  • 10행은 회원이 없는 대출까지 IT 도서 2권과 곱한 값이다.
  • 16행은 분류 조건을 무시하고 도서 4권과 곱한 값이다.
문제 25
다음 SQL 의 실행 결과로 옳은 것은?

강좌

강좌코드강좌명
K1SQL기초
K2모델링
K3튜닝
K4파이썬

수강

학번강좌코드상태
S1K1승인
S2K1대기
S3K1승인
S1K2대기
S4K3승인
S2K3취소
SELECT C.강좌코드, COUNT(E.학번) AS 인원
  FROM 강좌 C
  LEFT OUTER JOIN 수강 E
    ON C.강좌코드 = E.강좌코드
   AND E.상태 = '승인'
 GROUP BY C.강좌코드
 ORDER BY C.강좌코드;
1
강좌코드인원
K12
K20
K31
K40
2
강좌코드인원
K13
K21
K32
K40
3
강좌코드인원
K12
K21
K31
K41
4
강좌코드인원
K12
K31
정답 및 해설

LEFT OUTER JOIN 에서 ON 절에 둔 상태 조건은 조인할 수강 행만 거를 뿐 왼쪽 강좌 행은 모두 남기므로 K2·K4 도 결과에 나타난다.

K2·K4 는 짝이 없어 수강 열이 NULL 이 되고, COUNT(E.학번)은 NULL 을 세지 않아 인원이 0이다.

  • K1·K3 만 남은 표는 상태 조건을 WHERE 에 둔 결과이다.
  • K2·K4 가 1인 표는 COUNT(*)로 NULL 행까지 센 결과이다.
  • K1 이 3인 표는 승인 조건 없이 모든 수강을 센 결과이다.
문제 26
다음 [결과]를 얻기 위해 ( ㉠ )에 들어갈 구문으로 옳은 것은?

[강의]

강의코드강의명강의실
C1자료구조A101
C2운영체제B201
C3네트워크A102

[시험]

강의코드강의실시험일
C1A1012026-06-15
C2B3012026-06-16
C3A1022026-06-17
C4A1012026-06-18
SELECT 강의코드, 강의명, 시험일
  FROM 강의 ( ㉠ )
 ORDER BY 강의코드;

[결과]

강의코드강의명시험일
C1자료구조2026-06-15
C2운영체제2026-06-16
C3네트워크2026-06-17
1JOIN 시험 USING (강의코드)
2CROSS JOIN 시험
3NATURAL JOIN 시험
4JOIN 시험 ON 강의.강의실 = 시험.강의실
정답 및 해설

결과에 C2(시험 강의실 B301)까지 시험일과 함께 나오려면 강의코드만 조인 조건으로 써야 하므로 USING (강의코드)가 맞다.

NATURAL JOIN은 이름이 같은 강의코드·강의실 두 열을 모두 같게 비교해 강의실이 다른 C2를 버린다. USING 에 쓴 열은 하나로 합쳐져 접두어 없이 조회한다.

  • NATURAL JOIN 시험: C2가 빠져 2행이 된다.
  • 강의실로 ON 조인: 강의코드가 양쪽 열로 남아 모호하다는 오류가 난다.
  • CROSS JOIN 시험: 조인 조건이 없고 강의코드도 모호해 오류가 난다.
문제 27
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[도서]

도서번호제목
B1데이터베이스 입문
B2SQL 활용
B3모델링 기초
B4통계 개론

[대출]

대출번호도서번호대출일
1B12026-02-20
2B12026-03-05
3B22026-02-10
4B32026-03-02
5B32026-03-15
6B32026-03-20
SELECT B.도서번호, COUNT(L.대출번호) AS 대출건수
  FROM 도서 B, 대출 L
 WHERE B.도서번호 = L.도서번호(+)
   AND L.대출일(+) >= DATE '2026-03-01'
 GROUP BY B.도서번호
 ORDER BY B.도서번호;
1
도서번호대출건수
B11
B21
B33
B41
2
도서번호대출건수
B11
B20
B33
B40
3
도서번호대출건수
B11
B33
4
도서번호대출건수
B12
B21
B33
B40
정답 및 해설

대출일 조건에도 (+)가 붙어 있어 이 조건은 ANSI 의 LEFT OUTER JOIN … ON 안 조건과 같고, 도서 4권이 모두 남는다.

3월 이후 대출만 짝지어져 B1은 1건, B3은 3건이고 B2·B4는 NULL 확장 행이라 COUNT(열)이 0을 센다.

  • B1·B3 두 행만 있는 표는 대출일 조건의 (+)를 빼 WHERE 필터가 된 경우다.
  • B2·B4가 1인 표는 NULL 확장 행까지 세는 COUNT(*)의 결과다.
  • B1이 2인 표는 날짜 조건을 무시하고 모든 대출을 센 경우다.
문제 28
각 의사의 평균 진료비보다 진료비가 큰 진료만 조회해 다음 [결과]를 얻으려 한다. ( ㉠ )에 들어갈 조건으로 옳은 것은?

[진료]

진료번호의사번호환자번호진료비
1D1P130000
2D1P250000
3D1P340000
4D2P120000
5D2P426000
6D3P270000
7D3P590000
SELECT A.진료번호, A.의사번호, A.진료비
  FROM 진료 A
 WHERE A.진료비 > (SELECT AVG(B.진료비)
                     FROM 진료 B
                    WHERE ( ㉠ ))
 ORDER BY A.진료번호;

[결과]

진료번호의사번호진료비
2D150000
5D226000
7D390000
1B.진료번호 = A.진료번호
2B.환자번호 = A.환자번호
3B.의사번호 = A.의사번호
4A.의사번호 IS NOT NULL
정답 및 해설

바깥 행의 의사번호를 안쪽에서 참조해야 행마다 같은 의사의 평균이 계산되므로 B.의사번호 = A.의사번호가 맞다.

연관 서브쿼리는 메인쿼리 행마다 다시 실행되어 D1 평균 40000, D2 23000, D3 80000과 비교하고 2·5·7번만 남는다.

  • 환자번호 상관: 환자별 평균과 비교해 1·6번이 나온다.
  • 진료번호 상관: 자기 자신의 평균과 같아 0행이다.
  • A.의사번호 IS NOT NULL: 전체 평균(약 46571)과 비교해 2·6·7번이 나온다.
문제 29
서브쿼리(Subquery)와 뷰에 대한 설명으로 옳은 것은?
1인라인 뷰는 WHERE 절에만 쓰는 서브쿼리다
2스칼라 서브쿼리는 한 행 한 열만 반환한다
3뷰를 만들면 데이터가 별도로 복제된다
4연관 서브쿼리는 메인쿼리 전 한 번 돈다
정답 및 해설

스칼라 서브쿼리는 SELECT 절 등에서 값 하나처럼 쓰이므로 한 행 한 열만 돌려줘야 하고, 여러 행이면 오류가 난다.

인라인 뷰는 FROM 절에 두어 테이블처럼 쓰는 서브쿼리이고, 뷰는 SQL 정의만 저장하는 가상 테이블이다.

  • 인라인 뷰는 WHERE 절이 아니라 FROM 절에 쓰는 서브쿼리다.
  • 뷰는 정의(SQL)만 저장하는 가상 테이블이라 데이터를 복제하지 않는다.
  • 연관 서브쿼리는 메인쿼리 행마다 반복 실행된다.
문제 30
다음 두 SQL 의 결과 행 수를 (㉠, ㉡) 순서로 바르게 나열한 것은?

[직원]

직원번호이름지점코드
101김하늘S1
102이도윤S1
103박서연S2
104최민준S2
105정예린S3

[지점]

지점코드지점명관리자번호
S1강남101
S2판교103
S3분당(null)
㉠ SELECT 이름 FROM 직원
    WHERE 직원번호 NOT IN (SELECT 관리자번호 FROM 지점);

㉡ SELECT 이름 FROM 직원 E
    WHERE NOT EXISTS (SELECT 1 FROM 지점 J
                       WHERE J.관리자번호 = E.직원번호);
13, 3
23, 0
30, 3
40, 0
정답 및 해설

㉠은 목록에 NULL이 섞여 직원번호 <> NULL이 UNKNOWN이 되므로 어떤 행도 참이 되지 않아 0행이다.

㉡의 NOT EXISTS는 짝이 되는 행의 존재만 따지고 NULL 관리자번호는 어느 직원과도 같지 않아 102·104·105번 3행이 나온다.

  • 둘 다 3행이라 보면 NOT IN의 NULL 비교를 놓친 것이다.
  • ㉠ 3행·㉡ 0행은 두 연산의 NULL 처리를 뒤바꾼 것이다.
  • 둘 다 0행이라 보면 NOT EXISTS도 NULL에 막힌다고 오해한 것이다.
문제 31
다음 두 테이블에 집합 연산자를 적용한 결과 행 수로 옳은 것은? (각 연산은 SELECT 과목 FROM 상반기수강 ○ SELECT 과목 FROM 하반기수강 형태)

[상반기수강]

과목
DB
DB
통계
파이썬
(null)

[하반기수강]

과목
통계
(null)
자바
1UNION: 4행
2UNION ALL: 7행
3EXCEPT: 3행
4INTERSECT: 2행
정답 및 해설

집합 연산자는 중복을 비교할 때 NULL끼리 같은 값으로 보므로 INTERSECT 결과는 통계와 NULL, 2행이다.

UNION·INTERSECT·EXCEPT(MINUS)는 중복을 제거하고 UNION ALL만 모든 행을 그대로 이어 붙인다.

  • UNION은 DB·통계·파이썬·NULL·자바로 5행이다.
  • EXCEPT는 DB 중복이 제거돼 DB·파이썬 2행이다.
  • UNION ALL은 NULL 행도 포함해 5+3=8행이다.
문제 32
다음 SQL 의 실행 결과로 옳은 것은?

[정회원]

회원번호이름등급
1한지우A
2서준호B
3윤채원A

[준회원]

회원번호이름등급
11서준호B
12강다은C
13윤채원B
SELECT 이름 AS 성명, 등급 FROM 정회원
UNION
SELECT 이름, 등급 FROM 준회원
 ORDER BY 성명, 등급;
1
성명등급
강다은C
서준호B
서준호B
윤채원A
윤채원B
한지우A
2
성명등급
강다은C
서준호B
윤채원A
윤채원B
한지우A
3
성명등급
한지우A
서준호B
윤채원A
강다은C
윤채원B
4
성명등급
강다은C
서준호B
윤채원A
한지우A
정답 및 해설

UNION은 이름과 등급이 모두 같은 행만 하나로 합치므로 서준호 B는 한 번, 등급이 다른 윤채원은 두 행으로 남아 5행이다.

결과 열 이름은 첫 SELECT의 별칭 성명을 따르고, 맨 끝 ORDER BY는 합쳐진 전체 결과를 정렬한다.

  • 윤채원이 한 행인 표는 이름만으로 중복을 판단한 경우다.
  • 정렬되지 않은 표는 ORDER BY가 마지막 SELECT에만 적용된다고 본 것이다.
  • 서준호 B가 두 번인 표는 UNION ALL의 결과다.
문제 33
다음 SQL 결과에서 채널이 NULL 이고 결제수단이 '카드'인 행의 합계는?

[주문]

주문번호채널결제수단금액
1앱카드100
2앱현금40
3웹카드70
4웹카드30
5매장현금50
6매장카드(null)
SELECT 채널, 결제수단, SUM(금액) AS 합계
  FROM 주문
 GROUP BY CUBE(채널, 결제수단)
 ORDER BY 채널, 결제수단;
1100
2140
3200
4290
정답 및 해설

CUBE(채널, 결제수단)는 채널별 소계뿐 아니라 채널을 NULL 로 둔 결제수단별 소계도 만들므로, 카드 소계는 100+70+30=200 이다.

매장의 카드 주문은 금액이 NULL 이라 SUM 에서 제외되며, 채널과 결제수단이 모두 NULL 인 총계 행은 290 이다.

  • 140 은 결제수단이 NULL 인 앱 채널 소계와 혼동한 값이다.
  • 290 은 두 열이 모두 NULL 인 총계 행의 값이다.
  • 100 은 앱 채널의 카드 상세 행 값이다.
문제 34
다음 [결과]를 얻기 위해 ( ㉠ )에 들어갈 구문으로 옳은 것은?

[학생]

학번학과학년
1경영1
2경영2
3컴공1
4컴공1
5컴공3
6통계2
SELECT 학과, 학년, GROUPING(학과) AS G, COUNT(*) AS 인원
  FROM 학생
 GROUP BY ( ㉠ )
 ORDER BY 3, 1, 2;

[결과]

학과학년G인원
경영(null)02
컴공(null)03
통계(null)01
(null)113
(null)212
(null)311
(null)(null)16
1GROUPING SETS (학과, 학년, ())
2학과, 학년
3CUBE (학과, 학년)
4ROLLUP (학과, 학년)
정답 및 해설

결과에 학과별 소계, 학년별 소계, 총계만 있고 학과·학년 상세 행이 없으므로 GROUPING SETS (학과, 학년, ())가 맞다.

GROUPING(학과)는 학과가 집계로 생긴 NULL일 때 1이어서 학년 소계와 총계 행에서 1, 학과 소계 행에서 0이다.

  • ROLLUP은 학과·학년 상세 행이 생기고 학년별 소계가 없다.
  • CUBE는 원하는 소계 외에 상세 행까지 만든다.
  • 일반 GROUP BY 학과, 학년은 상세 행만 만들고 소계가 없다.
문제 35
다음 SQL 의 실행 결과로 옳은 것은? (오름차순 정렬에서 NULL 은 마지막)

[진료실적]

월진료과건수
3내과10
3외과20
4내과30
SELECT 월, 진료과, SUM(건수) AS 합계
  FROM 진료실적
 GROUP BY ROLLUP(월, 진료과)
 ORDER BY 월, 진료과;
1
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
2
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
(null)내과40
(null)외과20
(null)(null)60
3
월진료과합계
3내과10
3외과20
4내과30
(null)내과40
(null)외과20
(null)(null)60
4
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
(null)(null)60
정답 및 해설

ROLLUP(월, 진료과)는 (월, 진료과)·(월)·() 세 단계만 만들어 월별 소계 2행과 총계 1행이 상세 3행에 더해진 6행이다.

인수 순서가 계층이 되므로 앞 열인 월 기준 소계만 생기고 진료과별 소계는 나오지 않는다.

  • 진료과 소계가 있고 월 소계가 없는 표는 인수 순서를 뒤집은 ROLLUP(진료과, 월)의 결과다.
  • 총계가 없는 표는 마지막 () 단계를 빠뜨린 것이다.
  • 양쪽 소계가 다 있는 8행 표는 CUBE의 결과다.
문제 36
다음 SQL 의 실행 결과로 옳은 것은?

[배송]

기사배송일건수
K12026-04-015
K12026-04-023
K12026-04-034
K22026-04-016
K22026-04-022
SELECT 기사, 배송일, 건수,
       SUM(건수) OVER (PARTITION BY 기사
                       ORDER BY 배송일) AS 누적
  FROM 배송
 ORDER BY 기사, 배송일;
1
기사배송일건수누적
K12026-04-0155
K12026-04-0238
K12026-04-03412
K22026-04-01618
K22026-04-02220
2
기사배송일건수누적
K12026-04-01512
K12026-04-02312
K12026-04-03412
K22026-04-0168
K22026-04-0228
3
기사배송일건수누적
K12026-04-0155
K12026-04-0238
K12026-04-03412
K22026-04-0166
K22026-04-0228
4
기사배송일건수누적
K12026-04-01512
K12026-04-0237
K12026-04-0344
K22026-04-0168
K22026-04-0222
정답 및 해설

PARTITION BY 기사로 기사마다 따로, ORDER BY 배송일 순으로 처음부터 현재 행까지 더하는 누적 합이라 K1은 5·8·12, K2는 6·8이다.

ORDER BY가 있으면 기본 프레임이 파티션 처음부터 현재 행까지여서 파티션이 바뀌는 K2 첫 행에서 다시 시작한다.

  • 18·20으로 이어지는 표는 PARTITION BY를 무시하고 전체를 누적한 것이다.
  • 12·8이 반복되는 표는 ORDER BY 없는 파티션 전체 합이다.
  • 12·7·4로 줄어드는 표는 배송일 역순으로 누적한 것이다.
문제 37
객실마다 가장 늦은 예약일의 금액을 모든 행에 붙여 다음 [결과]를 얻으려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

[예약]

예약번호객실예약일금액
1R12026-05-01120
2R12026-05-03150
3R12026-05-07130
4R22026-05-02200
5R22026-05-06180
SELECT 예약번호, 객실, 금액, ( ㉠ ) AS 마지막금액
  FROM 예약
 ORDER BY 예약번호;

[결과]

예약번호객실금액마지막금액
1R1120130
2R1150130
3R1130130
4R2200180
5R2180180

[후보]

(가) LEAD(금액) OVER (PARTITION BY 객실 ORDER BY 예약일)
(나) LAST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일)
(다) LAST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일
       ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
(라) FIRST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일 DESC)
1(다)
2(가)
3(나)
4(라)
정답 및 해설

예약일 내림차순 파티션의 첫 값이 곧 가장 늦은 예약 금액이므로 FIRST_VALUE … ORDER BY 예약일 DESC가 R1 모든 행에 130, R2 모든 행에 180을 붙인다.

ORDER BY만 둔 윈도우의 기본 프레임은 현재 행까지라서 LAST_VALUE를 그대로 쓰면 자기 금액이 나온다.

  • LEAD는 다음 예약 금액을 돌려주고 마지막 행은 NULL이다.
  • 기본 프레임의 LAST_VALUE는 현재 행 금액과 같다.
  • 1 FOLLOWING까지인 프레임은 다음 행 금액이라 예약번호 1·4가 150·180이 된다.
문제 38
다음 SQL 의 실행 결과로 옳은 것은?

[강의평가]

강의평점
SQL기초95
데이터분석88
모델링88
파이썬80
통계72
SELECT 강의, 평점,
       NTILE(2) OVER (ORDER BY 평점 DESC, 강의) AS 조,
       PERCENT_RANK() OVER (ORDER BY 평점 DESC) AS 백분위
  FROM 강의평가
 ORDER BY 평점 DESC, 강의;
1
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8810.25
파이썬8020.75
통계7221
2
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8810.25
파이썬8020.5
통계7220.75
3
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8820.25
파이썬8020.75
통계7221
4
강의평점조백분위
SQL기초9510.2
데이터분석8810.6
모델링8810.6
파이썬8020.8
통계7221
정답 및 해설

5행을 NTILE(2)로 나누면 나머지 1행이 앞 조에 붙어 3행·2행이 되고, PERCENT_RANK는 (RANK−1)/(5−1)이라 0·0.25·0.25·0.75·1이다.

평점 88 동점 두 강의는 RANK가 모두 2이고 다음 파이썬은 RANK 4라서 0.75가 된다.

  • 조가 1·1·2·2·2인 표는 나머지를 뒤 조에 준 것이다.
  • 0.5·0.75로 끝나는 표는 DENSE_RANK처럼 순위를 건너뛰지 않은 경우다.
  • 0.2·0.6으로 시작하는 표는 CUME_DIST의 값이다.
문제 39
다음 세 SQL 의 결과 행 수를 (㉠, ㉡, ㉢) 순서로 바르게 나열한 것은?

[게시글]

글번호게시판작성자
1공지관리자
2공지관리자
3자유민서
4자유도현
5자유민서
6질문하린
7질문도현
8(null)하린
㉠ SELECT 게시판, COUNT(*) FROM 게시글 GROUP BY 게시판;
㉡ SELECT 게시판, COUNT(*) OVER (PARTITION BY 게시판)
     FROM 게시글;
㉢ SELECT DISTINCT 게시판,
          COUNT(*) OVER (PARTITION BY 게시판)
     FROM 게시글;
14, 4, 4
24, 8, 8
33, 8, 3
44, 8, 4
정답 및 해설

GROUP BY는 그룹당 한 행으로 줄이지만 윈도우 함수는 원래 행을 그대로 두고 값만 붙이므로 ㉠ 4행, ㉡ 8행, ㉢ 4행이다.

게시판이 NULL인 글도 GROUP BY와 PARTITION BY에서 하나의 그룹이 되어 공지·자유·질문과 함께 4개로 묶이고, ㉢은 DISTINCT로 같은 행을 줄인다.

  • 3으로 센 것은 NULL 게시판을 그룹에서 뺀 경우다.
  • ㉡을 4행으로 본 것은 윈도우 함수가 행을 줄인다고 오해한 것이다.
  • ㉢을 8행으로 본 것은 DISTINCT의 중복 제거를 놓친 것이다.
문제 40
SQL Server 에서 [랭킹] 테이블에 ㉠~㉣ 을 실행할 때 오류가 발생하는 것은?

[랭킹]

선수기록
하늘95
바다88
구름88
들꽃72
별빛60
㉠ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC
     OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
㉡ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC
     FETCH NEXT 3 ROWS ONLY;
㉢ SELECT TOP (3) 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC;
㉣ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 2 DESC
     OFFSET 1 ROW FETCH FIRST 2 ROWS ONLY;
1㉠
2㉢
3㉡
4㉣
정답 및 해설

SQL Server 에서 FETCH 는 ORDER BY 뒤의 OFFSET 절에 딸린 선택 구문이라, OFFSET 없이 FETCH 만 쓰면 구문 오류가 난다.

처음부터 n 건을 가져오려면 OFFSET 0 ROWS 를 함께 적거나 TOP 을 쓴다.

  • OFFSET 0 ROWS 뒤에 FETCH NEXT 를 붙인 구문은 상위 3건을 가져온다.
  • TOP (3) 과 ORDER BY 를 함께 쓴 구문은 정상 실행된다.
  • FIRST·NEXT 와 ROW·ROWS 는 같은 뜻이라 열 번호 정렬과 함께 써도 정상이다.
문제 41
다음 SQL 의 실행 결과로 옳은 것은?

[실적]

사번지점매출
1강남500
2강남700
3강남500
4강남300
5판교400
6판교900
7판교650
SELECT 지점, 사번, 매출
  FROM (SELECT 지점, 사번, 매출,
               ROW_NUMBER() OVER (PARTITION BY 지점
                                  ORDER BY 매출 DESC, 사번) AS RN
          FROM 실적) T
 WHERE RN <= 2
 ORDER BY 지점, RN;
1
지점사번매출
강남2700
판교6900
2
지점사번매출
강남2700
강남1500
강남3500
판교6900
판교7650
3
지점사번매출
강남4300
강남1500
판교5400
판교7650
4
지점사번매출
강남2700
강남1500
판교6900
판교7650
정답 및 해설

ROW_NUMBER는 동점이어도 1, 2, 3처럼 고유 순번을 주므로 지점별로 정확히 2행씩, 강남 사번 2·1과 판교 사번 6·7이 나온다.

강남의 500 동점 두 명은 ORDER BY의 두 번째 기준인 사번 순으로 사번 1이 2위, 사번 3이 3위가 되어 사번 3은 빠진다.

  • 강남 사번 3까지 나온 표는 동점을 같은 순위로 주는 RANK를 쓴 경우다.
  • 매출이 낮은 사원이 나온 표는 오름차순으로 정렬한 경우다.
  • 2행뿐인 표는 PARTITION BY 없이 전체 상위 2명을 뽑은 경우다.
문제 42
Oracle 계층형 질의(Hierarchical Query)에서 루트부터 현재 행까지의 경로를 구분자로 이어 문자열로 돌려주는 것은?
1SYS_CONNECT_BY_PATH
2CONNECT_BY_ISCYCLE
3CONNECT_BY_ROOT
4LISTAGG WITHIN GROUP
정답 및 해설

SYS_CONNECT_BY_PATH(열, 구분자)는 루트에서 현재 행까지 거쳐 온 값을 구분자로 이어 붙인 경로 문자열을 돌려준다.

예를 들어 /본사/개발본부/데이터 처럼 계층 위치를 한 열로 보여 줄 때 쓰며 CONNECT BY 절과 함께만 쓸 수 있다.

  • CONNECT_BY_ROOT는 현재 행이 속한 루트 행의 값을 돌려준다.
  • CONNECT_BY_ISCYCLE은 NOCYCLE 사용 시 순환 여부를 1과 0으로 표시한다.
  • LISTAGG는 그룹 안의 값을 이어 붙이는 집계 함수로 계층 경로와 무관하다.
문제 43
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[부서]

부서코드부서명상위부서
D1본사(null)
D2영업본부D1
D3개발본부D1
D4국내영업D2
D5해외영업D2
D6백엔드D3
D7데이터D3
SELECT LEVEL, 부서명
  FROM 부서
 START WITH 상위부서 IS NULL
CONNECT BY PRIOR 부서코드 = 상위부서
 ORDER SIBLINGS BY 부서명;
1
LEVEL부서명
2개발본부
3국내영업
3데이터
3백엔드
1본사
2영업본부
3해외영업
2
LEVEL부서명
1본사
2영업본부
3국내영업
3해외영업
2개발본부
3백엔드
3데이터
3
LEVEL부서명
1본사
2개발본부
2영업본부
3국내영업
3데이터
3백엔드
3해외영업
4
LEVEL부서명
1본사
2개발본부
3데이터
3백엔드
2영업본부
3국내영업
3해외영업
정답 및 해설

ORDER SIBLINGS BY는 부모 아래 자식이 바로 이어지는 계층 순서를 지키면서 같은 부모를 둔 형제끼리만 부서명 순으로 정렬한다.

본사 아래 개발본부가 영업본부보다 앞서고, 개발본부의 자식은 데이터·백엔드, 영업본부의 자식은 국내영업·해외영업 순으로 따라온다.

  • 부서명만으로 전부 섞인 표는 일반 ORDER BY 부서명의 결과다.
  • LEVEL별로 모은 표는 너비 우선 순서로 계층 전개를 오해한 것이다.
  • 영업본부가 먼저인 표는 형제 정렬을 무시하고 부서코드 순으로 본 것이다.
문제 44
Oracle 에서 다음 SQL 을 실행한 결과 행 수는?

[분기실적]

지점Q1Q2Q3
강남1020(null)
판교(null)(null)(null)
분당5(null)15
일산789
SELECT 지점, 분기, 실적
  FROM 분기실적
UNPIVOT (실적 FOR 분기 IN (Q1, Q2, Q3))
 ORDER BY 지점, 분기;
17
212
34
49
정답 및 해설

UNPIVOT은 열 Q1~Q3을 행으로 펼치되 기본값이 EXCLUDE NULLS라서 실적이 NULL인 칸은 행으로 만들지 않아 2+0+2+3=7행이다.

세 분기가 모두 NULL인 판교는 결과에서 아예 사라진다.

  • 4행은 원본 행 수로, 열을 행으로 펼친다는 점을 놓친 값이다.
  • 9행은 판교만 빼고 나머지 NULL 칸은 남긴다고 본 값이다.
  • 12행은 INCLUDE NULLS를 지정했을 때의 행 수다.
문제 45
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[회원]

회원ID연락처
m01010-1234-5678
m0202-987-6543
m03031-55-0909
SELECT 회원ID,
       REGEXP_SUBSTR(연락처, '[0-9]+', 1, 2) AS 중간,
       REGEXP_INSTR(연락처, '-', 1, 2) AS 위치
  FROM 회원
 ORDER BY 회원ID;
1
회원ID중간위치
m0112349
m029877
m03557
2
회원ID중간위치
m0112348
m029876
m03556
3
회원ID중간위치
m0112344
m029873
m03554
4
회원ID중간위치
m01109
m0227
m03317
정답 및 해설

세 번째 인수 1은 시작 위치, 네 번째 인수 2는 두 번째 일치를 뜻하므로 숫자 묶음은 1234·987·55, 두 번째 하이픈 위치는 9·7·7이다.

REGEXP_INSTR는 문자열 첫 글자를 1로 세며, 010-1234-5678에서 두 번째 하이픈은 9번째 글자다.

  • 10·2·31이 나온 표는 2를 시작 위치로 오해해 둘째 글자부터 첫 묶음을 자른 것이다.
  • 8·6·6은 위치를 0부터 센 값이다.
  • 4·3·4는 첫 번째 하이픈의 위치다.
문제 46
DELETE, TRUNCATE, DROP 에 대한 설명으로 옳은 것은? (Oracle 기준)
1DROP은 WHERE로 일부 행만 지운다
2TRUNCATE 후에도 테이블 구조는 남는다
3TRUNCATE는 ROLLBACK으로 되돌린다
4DELETE는 테이블 구조까지 제거한다
정답 및 해설

TRUNCATE는 테이블의 모든 행을 지우고 저장 공간을 정리하지만 테이블 정의(구조)는 남겨 바로 다시 입력할 수 있다.

Oracle 에서 TRUNCATE·DROP은 DDL이라 자동 커밋되어 ROLLBACK으로 되돌릴 수 없고, DELETE는 DML이라 커밋 전 되돌릴 수 있다.

  • DELETE는 행만 지우고 구조는 그대로 둔다.
  • DROP은 테이블 자체를 없애며 WHERE 절을 쓸 수 없다.
  • TRUNCATE는 실행과 동시에 커밋돼 롤백 대상이 아니다.
문제 47
Oracle 의 한 세션에서 다음 문장을 차례로 실행했을 때 마지막 SELECT 의 결과는?
-- 대출 테이블에는 COMMIT 된 행이 2개 있다
INSERT INTO 대출 VALUES (3, 'B2', SYSDATE);
CREATE TABLE 대출백업 (대출번호 NUMBER);
INSERT INTO 대출 VALUES (4, 'B3', SYSDATE);
ROLLBACK;
SELECT COUNT(*) FROM 대출;
14
23
32
40
정답 및 해설

Oracle 은 DDL을 실행하면 그 앞의 트랜잭션을 암시적으로 COMMIT하므로 대출번호 3 INSERT는 CREATE TABLE 시점에 확정된다.

그 뒤 대출번호 4 INSERT만 새 트랜잭션에 남아 ROLLBACK으로 취소되어 행 수는 3이다.

  • 2는 DDL의 자동 커밋을 모르고 두 INSERT가 모두 취소된다고 본 값이다.
  • 4는 ROLLBACK이 아무것도 되돌리지 못한다고 본 값이다.
  • 0은 ROLLBACK이 이미 커밋된 행까지 지운다고 오해한 값이다.
문제 48
Oracle 에서 행 3개가 들어 있는 다음 [도서] 테이블에 실행했을 때 오류가 발생하는 문장은?

[도서] 제목 VARCHAR2(50)

도서번호제목저자쪽수
B1데이터베이스 입문오세린320
B2SQL 활용문태오280
B3모델링 기초오세린(null)
1ALTER TABLE 도서 MODIFY (제목 VARCHAR2(80))
2ALTER TABLE 도서 DROP COLUMN 쪽수
3ALTER TABLE 도서 ADD (분류 CHAR(2) NOT NULL)
4ALTER TABLE 도서 RENAME COLUMN 저자 TO 지은이
정답 및 해설

이미 행이 있는 테이블에 DEFAULT 없이 NOT NULL 열을 추가하면 기존 행의 새 열이 NULL이 되어 제약을 어기므로 오류가 난다.

이때는 DEFAULT 값을 함께 주거나 NULL 허용으로 추가한 뒤 값을 채우고 제약을 건다.

  • 열 길이를 늘리는 MODIFY는 기존 데이터와 충돌하지 않는다.
  • RENAME COLUMN은 열 이름만 바꾸는 정상 구문이다.
  • DROP COLUMN은 NULL이 섞인 열도 문제없이 삭제한다.
문제 49
다음 문장을 실행한 뒤 [진료] 테이블의 (전체 행 수, 환자번호가 NULL 인 행 수)로 옳은 것은?
CREATE TABLE 환자 (환자번호 INT PRIMARY KEY, 이름 VARCHAR(10));
CREATE TABLE 진료 (
  진료번호 INT PRIMARY KEY,
  환자번호 INT REFERENCES 환자(환자번호)
           ON DELETE SET NULL,
  진료과   VARCHAR(10));
-- 환자: 1, 2, 3 / 진료(진료번호, 환자번호): (1,1) (2,2) (3,2) (4,3) (5,NULL)
DELETE FROM 환자 WHERE 환자번호 = 2;
15, 1
23, 1
35, 2
45, 3
정답 및 해설

ON DELETE SET NULL은 부모 행이 지워질 때 참조하던 자식 행을 지우지 않고 외래키 값만 NULL로 바꾸므로 진료는 5행 그대로다.

환자 2를 참조하던 진료번호 2·3이 NULL이 되고 원래 NULL이던 진료번호 5까지 더해 NULL 3행이다.

  • NULL 2행은 원래 NULL이던 진료번호 5를 빠뜨린 값이다.
  • 3행·NULL 1행은 자식까지 지우는 ON DELETE CASCADE의 결과다.
  • 5행·NULL 1행은 아무 변화가 없는 경우로, RESTRICT라면 DELETE 자체가 오류다.
문제 50
DCL 에서 사용하는 롤(ROLE)에 대한 설명으로 옳은 것은?
1롤은 다른 롤에게 부여할 수 없다
2롤을 회수해도 그 권한은 남는다
3시스템 권한은 롤에 담을 수 없다
4여러 권한을 묶어 한 번에 부여한다
정답 및 해설

롤(ROLE)은 여러 권한을 하나로 묶은 이름으로, GRANT 롤 TO 사용자 한 번으로 묶인 권한을 모두 줄 수 있어 권한 관리가 쉬워진다.

롤에는 CREATE SESSION 같은 시스템 권한과 객체 권한을 모두 담을 수 있다.

  • CONNECT·RESOURCE 롤처럼 시스템 권한을 담는 것이 일반적이다.
  • 롤은 다른 롤에 부여해 계층적으로 묶을 수 있다.
  • 롤을 REVOKE하면 그 롤로 받은 권한도 함께 사라진다.
SQLD SQL 개발자 실전 모의고사모두CBT · moducbt.com
SQL 개발자 기출유형 모의고사 2회
총 50문항 · 객관식 · 정답·해설 포함
문제 1
데이터 모델링 단계 중 논리적 모델링에서 수행하는 작업으로 가장 적절한 것은?
1DBMS별 데이터 타입과 용량을 정한다
2정규화로 속성과 관계를 정제한다
3테이블스페이스와 인덱스를 정의한다
4핵심 엔터티만 추려 전사 관점을 잡는다
정답 및 해설

논리적 모델링은 개념 모델을 업무 규칙에 맞게 구체화하며 정규화로 속성과 관계를 정제하는 단계이다.

특정 DBMS 와 무관하게 키·속성·관계를 확정하므로 재사용성이 가장 높은 산출물이 나온다.

  • 테이블스페이스·인덱스 정의는 물리적 모델링에서 한다.
  • 핵심 엔터티로 전사 관점을 잡는 일은 개념적 모델링이다.
  • DBMS별 데이터 타입·용량 결정도 물리적 모델링이다.
문제 2
다음은 온라인 강의 서비스의 ERD 초안이다. 운영사에는 이 서비스를 운영하는 자사 정보 1건만 저장되며 다른 업무에서 참조하지 않는다. 엔터티 성립 조건에 비추어 엔터티로 보기 어려운 것과 그 이유를 바르게 짝지은 것은?

그림

1운영사: 인스턴스가 하나뿐이다
2수강신청: 주식별자가 두 속성이다
3강좌: 일반 속성이 두 개뿐이다
4회원: 관계가 하나만 연결된다
정답 및 해설

운영사는 자사 1건만 저장되어 인스턴스가 두 개 이상이라는 엔터티 성립 조건을 충족하지 못한다.

게다가 다른 엔터티와의 관계도 없어 업무 데이터로서 쓰임이 없으므로 설정값처럼 따로 관리하는 편이 낫다.

  • 수강신청은 회원번호·강좌코드 복합 식별자로 유일하게 구분되면 충분하다.
  • 강좌는 일반 속성이 두 개라도 속성을 가진다는 조건을 만족한다.
  • 회원은 수강신청과 관계를 맺고 있어 관계 조건을 충족한다.
문제 3
속성(Attribute)에 대한 설명으로 가장 적절한 것은?
1하나의 속성에 여러 값을 묶어 저장한다
2한 인스턴스는 속성마다 값을 하나 가진다
3한 속성은 여러 엔터티에 동시에 속한다
4속성은 엔터티 없이 단독으로 존재한다
정답 및 해설

속성은 엔터티를 설명하는 더 이상 쪼갤 수 없는 단위이며, 한 인스턴스는 각 속성에 대해 하나의 값만 가진다.

값이 여러 개라면 별도 엔터티로 분리하거나 속성을 나누어 원자성을 지켜야 한다.

  • 여러 값을 한 속성에 묶으면 제1정규형을 위반한다.
  • 속성은 반드시 어떤 엔터티에 소속되어야 의미를 가진다.
  • 하나의 속성은 하나의 엔터티에만 소속된다.
문제 4
도서관에서 한 회원은 여러 도서를 대출하고, 한 도서도 여러 회원에게 대출된다. 이 관계를 논리 모델에서 처리하는 방법으로 가장 적절한 것은?
1도서에 회원번호 속성 하나를 추가한다
2회원에 도서번호를 반복 속성으로 둔다
3대출 엔터티를 두어 1:M 둘로 푼다
4두 엔터티를 하나로 통합해 관리한다
정답 및 해설

회원과 도서는 M:N 관계이므로 논리 모델에서는 대출이라는 교차 엔터티를 두어 회원–대출, 도서–대출의 1:M 관계 둘로 해소한다.

대출에는 회원번호·도서번호가 FK 로 상속되고 대출일·반납일 같은 관계 고유 속성이 함께 놓인다.

  • 도서에 회원번호 하나만 두면 여러 회원의 대출 이력을 담지 못한다.
  • 회원에 도서번호를 반복해 두면 제1정규형을 어긴다.
  • 두 엔터티를 통합하면 회원·도서 정보가 중복된다.
문제 5
주식별자의 특성에 대한 설명으로 적절하지 않은 것은?
1유일성: 인스턴스를 유일하게 구분한다
2최소성: 여유 있게 속성을 더 포함한다
3존재성: 지정되면 반드시 값이 있다
4불변성: 지정된 값이 자주 바뀌지 않는다
정답 및 해설

최소성은 유일성을 만족하는 데 필요한 최소한의 속성으로만 주식별자를 구성해야 한다는 뜻이므로, 속성을 여유 있게 더 넣는 것은 반대 방향이다.

예를 들어 환자번호만으로 유일하다면 환자번호+환자명은 최소성을 어긴 식별자가 된다.

  • 유일성은 주식별자로 모든 인스턴스를 유일하게 구분하는 특성이다.
  • 불변성은 한번 지정된 값이 자주 변하지 않아야 한다는 특성이다.
  • 존재성은 주식별자에 반드시 값이 들어가 NULL 이 없다는 특성이다.
문제 6
BCNF(Boyce-Codd 정규형)를 만족하는 조건으로 옳은 것은?
1키가 아닌 속성 사이 종속만 없애면 된다
2모든 속성 값이 원자값이면 된다
3기본키에 대한 부분 종속을 없애면 된다
4모든 결정자가 후보키가 되어야 한다
정답 및 해설

BCNF 는 함수 종속의 모든 결정자가 후보키여야 한다는 조건으로, 제3정규형보다 강한 정규형이다.

후보키가 아닌 속성이 다른 속성을 결정하면 3NF 를 만족해도 BCNF 위반이므로 그 결정자를 기준으로 테이블을 분해한다.

  • 모든 속성 값이 원자값인 것은 제1정규형 조건이다.
  • 기본키에 대한 부분 종속 제거는 제2정규형 조건이다.
  • 키가 아닌 속성 사이의 이행 종속 제거는 제3정규형 조건이다.
문제 7
다음 ERD 에서 실선은 식별 관계, 점선은 비식별 관계이며 FK 는 부모의 주식별자를 그대로 상속한 것이다. 신청 건마다 개설된 과목의 과목명과 소속 학과명을 함께 조회할 때, 수강신청 외에 조인해야 하는 최소 테이블 조합은?

그림

1개설, 과목, 학과
2학생, 과목
3과목, 학과
4학과
정답 및 해설

수강신청은 개설의 주식별자 (학과코드, 과목번호, 학기)를 FK 로 상속받으므로 개설을 거치지 않고 과목·학과와 바로 조인하면 충분하다.

과목명은 과목에만 있어 (학과코드, 과목번호)로 과목과, 학과명은 학과코드로 학과와 조인한다.

  • 개설은 담당교수가 필요할 때만 조인하면 되므로 최소 조합이 아니다.
  • 학과만 조인하면 과목명을 얻을 수 없다.
  • 학생은 신청자 정보일 뿐 과목의 소속 학과와는 경로가 다르다.
문제 8
숙박 예약 모델의 다음 관계 중 두 엔터티의 인스턴스를 반드시 하나의 트랜잭션으로 함께 입력해야 하는 구조는?
1리뷰는 예약이 있을 때만 작성된다
2예약과 결제가 서로 필수로 참여한다
3회원은 예약 없이도 존재할 수 있다
4객실은 예약과 무관하게 등록된다
정답 및 해설

예약과 결제가 서로 필수 참여라면 어느 한쪽만 저장된 상태는 업무 규칙 위반이므로 두 인스턴스를 하나의 트랜잭션으로 함께 입력·커밋해야 한다.

한쪽만 필수인 관계는 부모를 먼저 입력해 두고 자식을 나중에 별도 트랜잭션으로 넣어도 정합성이 깨지지 않는다.

  • 예약이 없는 회원은 단독으로 입력할 수 있다.
  • 객실은 예약과 별개로 먼저 등록해 둘 수 있다.
  • 리뷰는 예약이 이미 있으면 나중에 따로 입력해도 된다.
문제 9
진료 엔터티의 속성 중 NULL 허용으로 설계하는 것이 가장 타당한 것은?
1환자번호(필수 관계의 FK)
2진료번호(주식별자)
3재진예약일(다음 방문 날짜)
4진료일시(진료 시작 시각)
정답 및 해설

재진예약일은 다음 방문이 정해지지 않은 진료에서는 값이 없을 수 있으므로 NULL 허용이 업무 규칙에 맞다.

반대로 식별자·필수 관계의 FK·업무상 반드시 생기는 값은 NOT NULL로 두어야 데이터 누락을 막는다.

  • 진료번호는 주식별자라 존재성에 따라 NULL 이 될 수 없다.
  • 진료일시는 진료가 생기는 순간 반드시 정해지는 값이다.
  • 필수 관계의 FK 인 환자번호가 NULL 이면 관계가 깨진다.
문제 10
다음 수강신청 테이블은 시퀀스로 부여한 인조식별자 신청ID 를 기본키로 쓴다. 한 학생은 같은 강좌를 한 번만 신청할 수 있을 때, 이 설계를 보완하는 방법으로 가장 적절한 것은?

수강신청

신청ID학번강좌코드신청일
12026001C102026-03-02
22026002C102026-03-02
32026001C202026-03-03
42026001C102026-03-04
1학번+강좌코드에 유니크 제약을 둔다
2신청ID 에 NOT NULL 제약을 추가한다
3신청일을 기본키로 바꾸어 사용한다
4학번 단독으로 유니크 제약을 건다
정답 및 해설

인조식별자만 기본키로 두면 같은 학생의 같은 강좌 신청이 신청ID 만 달리해 중복 입력되며, 실제로 2026001·C10 신청이 두 행 저장되었다.

본질식별자인 (학번, 강좌코드)에 유니크 제약을 걸면 인조식별자를 유지하면서도 업무상 중복을 막을 수 있다.

  • 신청일은 여러 신청이 같은 날 생기므로 유일성이 없다.
  • 신청ID 는 기본키라 이미 NOT NULL 이며 중복을 막지 못한다.
  • 학번 단독 유니크는 한 학생의 여러 강좌 신청까지 막는다.
문제 11
관계형 데이터베이스의 테이블에 대한 설명으로 적절하지 않은 것은?
1기본키로 각 행을 유일하게 식별한다
2하나의 행은 하나의 인스턴스를 뜻한다
3행 저장 순서가 조회 순서를 보장한다
4같은 열의 값은 같은 도메인을 갖는다
정답 및 해설

관계형 모델에서 테이블의 행은 순서 개념이 없는 집합이므로 저장된 순서대로 조회된다는 보장이 없고, 순서가 필요하면 ORDER BY를 써야 한다.

열은 하나의 속성으로 같은 도메인의 값을 갖고, 행은 하나의 인스턴스를 나타내며 기본키로 구분된다.

  • 같은 열의 값이 같은 도메인을 갖는 것은 테이블의 기본 성질이다.
  • 기본키는 각 행을 유일하게 식별하는 열 집합이다.
  • 행 하나는 엔터티의 인스턴스 하나에 대응한다.
문제 12
다음 SQL 에서 네 번째로 처리되는 절은?
SELECT 회원번호, COUNT(*) AS 대출건수
  FROM 대출
 WHERE 반납일 IS NULL
 GROUP BY 회원번호
HAVING COUNT(*) >= 2
 ORDER BY 대출건수 DESC;
1GROUP BY 절
2HAVING 절
3SELECT 절
4WHERE 절
정답 및 해설

SELECT 문은 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순으로 처리되므로 네 번째는 HAVING 절이다.

그래서 SELECT 절의 별칭 대출건수는 HAVING 에서 쓸 수 없고 마지막에 처리되는 ORDER BY 에서만 쓸 수 있다.

  • WHERE 절은 FROM 다음 두 번째로 처리된다.
  • GROUP BY 절은 세 번째로 처리된다.
  • SELECT 절은 HAVING 다음 다섯 번째로 처리된다.
문제 13
진료비 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

진료비

진료번호기본료검사료
1100005000
28000(null)
3(null)3000
4120002000
59000(null)
SELECT SUM(기본료 + 검사료) AS A,
       SUM(기본료) + SUM(검사료) AS B,
       COUNT(검사료) AS C
  FROM 진료비;
1
ABC
49000490003
2
ABC
29000290003
3
ABC
29000490005
4
ABC
29000490003
정답 및 해설

행 단위 덧셈은 한쪽이 NULL 이면 결과가 NULL이 되어 SUM 에서 빠지므로 A 는 두 값이 모두 있는 행의 합 15000+14000=29000이다.

B 는 열마다 NULL 을 제외하고 먼저 합한 39000+10000=49000이고, COUNT(열)은 NULL 이 아닌 3건만 센다.

  • A 를 49000으로 본 것은 NULL 을 0처럼 더한 오해다.
  • B 를 29000으로 본 것은 열별 집계가 NULL 을 먼저 제외한다는 점을 놓쳤다.
  • C 를 5로 본 것은 COUNT(*)와 COUNT(열)을 혼동한 것이다.
문제 14
예약 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

예약

예약번호인원확정인원메모
144창가
23(null)(null)
3(null)(null)(null)
452유아
SELECT 예약번호,
       COALESCE(확정인원, 인원, 0) AS P,
       NULLIF(인원, 확정인원) AS Q,
       CASE WHEN 메모 IS NULL THEN 'N' ELSE 'Y' END AS R
  FROM 예약
 ORDER BY 예약번호;
1
예약번호PQR
14(null)Y
233N
30(null)N
425Y
2
예약번호PQR
14(null)Y
23(null)N
30(null)N
425Y
3
예약번호PQR
14(null)Y
233N
30(null)N
455Y
4
예약번호PQR
144Y
233N
30(null)N
425Y
정답 및 해설

COALESCE는 왼쪽부터 처음 만나는 NULL 아닌 값을 돌려주어 예약번호 4 행은 확정인원 2, 두 값이 모두 NULL 인 예약번호 3 행은 0이 된다.

NULLIF(a, b)는 두 값이 같을 때만 NULL 이고 다르면 a 를 돌려주므로 4와 4가 같은 첫 행만 NULL, 확정인원이 NULL 인 둘째 행은 3이다.

  • 첫 행의 Q 를 4로 본 것은 같을 때 NULL 이 된다는 규칙을 뒤집은 것이다.
  • 둘째 행의 Q 를 NULL 로 본 것은 NULL 과의 비교를 같음으로 오해한 것이다.
  • 마지막 행의 P 를 5로 본 것은 COALESCE 인자 순서를 놓친 것이다.
문제 15
Oracle 기준으로, 대출일로부터 14일 뒤의 반납예정일을 다음 결과처럼 'YYYY-MM-DD' 형식 문자열로 출력하려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

대출

대출번호회원번호대출일
1112026-03-02
2122026-03-20
3112026-04-25
SELECT 대출번호,
       ( ㉠ ) AS 반납예정일
  FROM 대출
 ORDER BY 대출번호;
대출번호반납예정일
12026-03-16
22026-04-03
32026-05-09
1ADD_MONTHS(대출일, 14)
2TO_CHAR(대출일, 'YYYY-MM') || '-14'
3TO_CHAR(대출일 + 14, 'YYYY-MM-DD')
4TO_NUMBER(대출일) + 14
정답 및 해설

Oracle 에서 DATE + 숫자는 그 일수만큼 더한 날짜이므로 대출일 + 14 로 14일 뒤를 구한 다음 TO_CHAR로 'YYYY-MM-DD' 문자열을 만든다.

3월 20일은 4월 3일, 4월 25일은 5월 9일처럼 월이 바뀌는 경우도 날짜 연산이 자동으로 처리한다.

  • ADD_MONTHS 는 일이 아니라 개월 수를 더하며 결과도 문자열이 아니다.
  • 월 뒤에 '-14'를 붙이면 대출일과 무관하게 모든 행이 14일이 된다.
  • DATE 를 TO_NUMBER 로 바로 바꿀 수 없어 형변환 오류가 난다.
문제 16
Oracle 기준으로 다음 SQL 을 실행한 결과로 옳은 것은?

수강

학번강좌코드등급
2026101K1A
2026102K1B
2026103K1(null)
2026104K1C
2026105K1B
SELECT 학번,
       DECODE(등급, 'A', '우수', 'B', '보통', '미흡') AS 평가
  FROM 수강
 ORDER BY 학번;
1
학번평가
2026101우수
2026102보통
2026103미흡
2026104미흡
2026105보통
2
학번평가
2026101우수
2026102보통
2026103(null)
2026104(null)
2026105보통
3
학번평가
2026101우수
2026102보통
2026103미흡
2026104(null)
2026105보통
4
학번평가
2026101우수
2026102보통
2026103(null)
2026104미흡
2026105보통
정답 및 해설

DECODE는 등급을 검색값과 차례로 비교해 일치하는 결과를 돌려주고, 어느 것과도 일치하지 않으면 마지막 기본값 '미흡'을 돌려준다.

등급이 C 인 행과 NULL 인 행은 'A'·'B' 어느 쪽과도 일치하지 않으므로 둘 다 '미흡'이 된다.

  • NULL 행만 NULL 로 둔 것은 기본값이 NULL 에도 적용된다는 점을 놓쳤다.
  • C 행만 NULL 로 둔 것은 기본값을 NULL 전용으로 오해했다.
  • 두 행 모두 NULL 로 둔 것은 기본값 인자를 무시했다.
문제 17
WHERE 절 조건에 대한 설명으로 적절하지 않은 것은?
1= 비교에서 % 는 일반 문자로 본다
2ESCAPE 로 % 문자 자체를 찾을 수 있다
3IS NOT NULL 은 값이 있는 행을 찾는다
4NOT BETWEEN 은 양 끝값을 포함한다
정답 및 해설

NOT BETWEEN a AND b는 BETWEEN 의 부정이므로 a 미만이거나 b 초과인 행만 찾고, 양 끝값 a·b 는 결과에서 빠진다.

와일드카드 % 와 _ 는 LIKE 에서만 패턴으로 해석되며, 그 문자 자체를 찾을 때는 ESCAPE 로 지정한 문자를 앞에 붙인다.

  • LIKE '%10\%%' ESCAPE '\' 처럼 쓰면 % 기호 자체를 검색한다.
  • IS NOT NULL 은 NULL 이 아닌, 값이 들어 있는 행을 고른다.
  • = 연산자는 패턴 비교가 아니어서 % 를 글자 그대로 비교한다.
문제 18
[회원] 테이블에 다음 SQL 을 실행했을 때 조회되는 결과는?

[회원]

회원번호등급포인트
1VIP300
2일반450
3(null)200
4일반(null)
5(null)800
6VIP100
7일반500
8(null)(null)
SELECT 회원번호, 등급
  FROM 회원
 WHERE COALESCE(등급, '일반') <> 'VIP'
   AND 포인트 < 500
 ORDER BY 회원번호;
1
회원번호등급
2일반
3(null)
2
회원번호등급
2일반
3일반
3
회원번호등급
2일반
3(null)
4일반
8(null)
4
회원번호등급
2일반
정답 및 해설

등급이 NULL 인 행은 COALESCE 로 '일반'이 되어 첫 조건이 참이지만, 포인트가 NULL 이면 UNKNOWN 이라 AND 결과가 참이 되지 않아 회원 2·3 만 남는다.

회원 4·8 은 포인트 비교가 UNKNOWN 이라 빠지고 회원 5·7 은 포인트가 500 이상이며, SELECT 의 등급은 바꾸지 않았으므로 회원 3 의 등급은 NULL 그대로 출력된다.

  • 회원 3 의 등급을 '일반'으로 보인 표는 WHERE 의 COALESCE 가 출력값까지 바꾼다고 본 것이다.
  • 회원 2 만 남긴 표는 등급 NULL 행을 COALESCE 없이 비교한 결과다.
  • 회원 4·8 까지 넣은 표는 NULL 과의 비교를 참으로 계산한 것이다.
문제 19
대출 테이블에 대해 다음 SQL 을 실행한 결과로 옳은 것은?

대출

대출번호회원번호연체일반납일
11102026-03-10
212352026-03-20
31310(null)
411(null)(null)
51425(null)
SELECT COUNT(*) AS CNT, SUM(연체일) AS S, MAX(연체일) AS M
  FROM 대출
 WHERE 반납일 IS NULL
   AND 연체일 > 30;
1
CNTSM
000
2
CNTSM
13535
3
CNTSM
0(null)(null)
4
CNTSM
정답 및 해설

GROUP BY 가 없는 집계 쿼리는 조건을 만족하는 행이 없어도 항상 한 행을 돌려주며, 이때 COUNT(*)는 0, SUM·MAX 는 NULL이다.

반납일이 NULL 인 대출은 연체일이 10, NULL, 25뿐이라 30 초과가 없고, 연체일 35인 대출은 이미 반납되어 WHERE 에서 제외된다.

  • 결과 행이 없다고 본 것은 GROUP BY 가 있을 때의 동작과 혼동한 것이다.
  • SUM·MAX 를 0으로 본 것은 빈 집합의 집계가 NULL 이라는 점을 놓쳤다.
  • 연체일 35인 행을 센 것은 반납일 조건을 빠뜨린 것이다.
문제 20
수강(학번, 강좌코드, 점수) 테이블에 대해 다음 SQL 을 실행할 때 오류가 발생하는 것을 모두 고른 것은?
㉠ SELECT 강좌코드, AVG(점수) FROM 수강
   GROUP BY 강좌코드 HAVING AVG(점수) >= 80;
㉡ SELECT 강좌코드, COUNT(*) FROM 수강
   WHERE COUNT(*) >= 2 GROUP BY 강좌코드;
㉢ SELECT 강좌코드 FROM 수강 WHERE 점수 >= 60
   GROUP BY 강좌코드 HAVING COUNT(*) >= 2;
㉣ SELECT 학번, MAX(점수) FROM 수강
   GROUP BY 강좌코드;
1㉡
2㉡, ㉣
3㉢, ㉣
4㉠, ㉡
정답 및 해설

WHERE 절은 그룹이 만들어지기 전에 행 단위로 처리되므로 집계 함수를 WHERE 에 쓸 수 없어 ㉡은 오류이며, 집계 조건은 HAVING 에 써야 한다.

㉣은 GROUP BY 에 없는 학번을 집계 없이 SELECT 해 그룹당 한 값을 정할 수 없으므로 오류가 난다.

  • ㉠은 집계 조건을 HAVING 에 둔 올바른 구문이다.
  • ㉢은 행 조건은 WHERE, 그룹 조건은 HAVING 에 둔 정상 구문이다.
  • ㉡만 고르면 GROUP BY 열 규칙을 어긴 ㉣을 놓친다.
문제 21
예약 테이블에 대해 다음 SQL 을 실행했을 때 결과 행 수는?

예약

예약번호지점객실유형예약일
1강남디럭스2026-03-02
2강남디럭스2026-03-05
3강남(null)2026-03-07
4강남(null)2026-03-09
5홍대스탠다드2026-02-27
6홍대스탠다드2026-03-03
7홍대디럭스2026-03-04
8(null)디럭스2026-03-06
9홍대(null)2026-02-20
SELECT 지점, 객실유형, COUNT(*) AS 건수
  FROM 예약
 WHERE 예약일 >= DATE '2026-03-01'
 GROUP BY 지점, 객실유형
 ORDER BY 지점, 객실유형;
14행
25행
36행
43행
정답 및 해설

WHERE 로 3월 1일 이전 예약 두 건을 먼저 제외한 뒤 (지점, 객실유형) 조합으로 묶으며, GROUP BY 는 NULL 도 하나의 그룹으로 만든다.

남는 그룹은 (강남, 디럭스), (강남, NULL), (홍대, 스탠다드), (홍대, 디럭스), (NULL, 디럭스)로 5개이다.

  • 4개는 NULL 그룹 하나를 빠뜨린 계산이다.
  • 3개는 NULL 이 들어간 그룹을 모두 제외한 계산이다.
  • 6개는 WHERE 를 무시해 (홍대, NULL) 그룹까지 센 계산이다.
문제 22
NULL 값의 정렬 위치에 대한 설명으로 옳은 것은?
1DESC 정렬에서도 NULL 은 항상 마지막이다
2Oracle 오름차순은 NULL 이 맨 뒤다
3NULLS FIRST 는 DESC 에만 쓴다
4SQL Server 는 NULL 을 최댓값으로 본다
정답 및 해설

Oracle 은 NULL 을 가장 큰 값처럼 다루어 오름차순이면 맨 뒤, 내림차순이면 맨 앞에 둔다.

SQL Server 는 반대로 NULL 을 가장 작은 값으로 보아 오름차순에서 맨 앞에 오며, Oracle 은 NULLS FIRST/LAST로 위치를 직접 정할 수 있다.

  • SQL Server 는 NULL 을 최솟값으로 취급한다.
  • NULLS FIRST 는 오름차순·내림차순 모두에 쓸 수 있다.
  • Oracle 내림차순에서는 NULL 이 맨 앞에 온다.
문제 23
등가 조인(EQUI JOIN)에 대한 설명으로 옳은 것은?
1= 연산자로 두 테이블의 값을 비교한다
2BETWEEN 으로 범위를 비교한다
3PK 와 FK 사이에서만 조인할 수 있다
4조인 키가 NULL 인 행도 결과에 남는다
정답 및 해설

등가 조인은 두 테이블의 조인 열을 = 연산자로 비교해 값이 같은 행끼리만 결합하는 방식이다.

NULL 은 어떤 값과도 같지 않으므로 조인 키가 NULL 인 행은 짝을 찾지 못해 결과에서 빠진다.

  • 조인 키가 NULL 인 행을 남기려면 OUTER JOIN 을 써야 한다.
  • 값만 비교할 수 있으면 PK·FK 관계가 없어도 조인할 수 있다.
  • BETWEEN 처럼 범위로 비교하는 것은 비등가 조인이다.
문제 24
다음 SQL 은 세 테이블을 조인하면서 대출과 도서 사이의 조인 조건을 빠뜨렸다. 실행 결과의 행 수는?

회원

회원번호이름
1한지수
2오민재
3서가은

대출

대출번호회원번호도서번호
1011B1
1021B2
1032B3
1043B1
1059B4

도서

도서번호제목분류
B1SQL 입문IT
B2봄날소설
B3파이썬 기초IT
B4고려사역사
SELECT M.이름, B.제목
  FROM 회원 M, 대출 L, 도서 B
 WHERE M.회원번호 = L.회원번호
   AND B.분류 = 'IT'
 ORDER BY M.이름, B.제목;
116행
210행
33행
48행
정답 및 해설

세 테이블 조인에는 조인 조건이 최소 2개(N−1) 필요한데 대출–도서 조건이 빠져 도서와는 카티션 곱이 생긴다.

회원과 짝이 맞는 대출은 회원번호 9 를 뺀 4건이고, 이 4건이 IT 도서 2권과 모두 짝지어 4 × 2 = 8행이 된다.

  • 3행은 대출–도서 조건까지 있을 때의 정상 조인 결과이다.
  • 10행은 회원이 없는 대출까지 IT 도서 2권과 곱한 값이다.
  • 16행은 분류 조건을 무시하고 도서 4권과 곱한 값이다.
문제 25
다음 SQL 의 실행 결과로 옳은 것은?

강좌

강좌코드강좌명
K1SQL기초
K2모델링
K3튜닝
K4파이썬

수강

학번강좌코드상태
S1K1승인
S2K1대기
S3K1승인
S1K2대기
S4K3승인
S2K3취소
SELECT C.강좌코드, COUNT(E.학번) AS 인원
  FROM 강좌 C
  LEFT OUTER JOIN 수강 E
    ON C.강좌코드 = E.강좌코드
   AND E.상태 = '승인'
 GROUP BY C.강좌코드
 ORDER BY C.강좌코드;
1
강좌코드인원
K12
K20
K31
K40
2
강좌코드인원
K13
K21
K32
K40
3
강좌코드인원
K12
K21
K31
K41
4
강좌코드인원
K12
K31
정답 및 해설

LEFT OUTER JOIN 에서 ON 절에 둔 상태 조건은 조인할 수강 행만 거를 뿐 왼쪽 강좌 행은 모두 남기므로 K2·K4 도 결과에 나타난다.

K2·K4 는 짝이 없어 수강 열이 NULL 이 되고, COUNT(E.학번)은 NULL 을 세지 않아 인원이 0이다.

  • K1·K3 만 남은 표는 상태 조건을 WHERE 에 둔 결과이다.
  • K2·K4 가 1인 표는 COUNT(*)로 NULL 행까지 센 결과이다.
  • K1 이 3인 표는 승인 조건 없이 모든 수강을 센 결과이다.
문제 26
다음 [결과]를 얻기 위해 ( ㉠ )에 들어갈 구문으로 옳은 것은?

[강의]

강의코드강의명강의실
C1자료구조A101
C2운영체제B201
C3네트워크A102

[시험]

강의코드강의실시험일
C1A1012026-06-15
C2B3012026-06-16
C3A1022026-06-17
C4A1012026-06-18
SELECT 강의코드, 강의명, 시험일
  FROM 강의 ( ㉠ )
 ORDER BY 강의코드;

[결과]

강의코드강의명시험일
C1자료구조2026-06-15
C2운영체제2026-06-16
C3네트워크2026-06-17
1JOIN 시험 USING (강의코드)
2CROSS JOIN 시험
3NATURAL JOIN 시험
4JOIN 시험 ON 강의.강의실 = 시험.강의실
정답 및 해설

결과에 C2(시험 강의실 B301)까지 시험일과 함께 나오려면 강의코드만 조인 조건으로 써야 하므로 USING (강의코드)가 맞다.

NATURAL JOIN은 이름이 같은 강의코드·강의실 두 열을 모두 같게 비교해 강의실이 다른 C2를 버린다. USING 에 쓴 열은 하나로 합쳐져 접두어 없이 조회한다.

  • NATURAL JOIN 시험: C2가 빠져 2행이 된다.
  • 강의실로 ON 조인: 강의코드가 양쪽 열로 남아 모호하다는 오류가 난다.
  • CROSS JOIN 시험: 조인 조건이 없고 강의코드도 모호해 오류가 난다.
문제 27
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[도서]

도서번호제목
B1데이터베이스 입문
B2SQL 활용
B3모델링 기초
B4통계 개론

[대출]

대출번호도서번호대출일
1B12026-02-20
2B12026-03-05
3B22026-02-10
4B32026-03-02
5B32026-03-15
6B32026-03-20
SELECT B.도서번호, COUNT(L.대출번호) AS 대출건수
  FROM 도서 B, 대출 L
 WHERE B.도서번호 = L.도서번호(+)
   AND L.대출일(+) >= DATE '2026-03-01'
 GROUP BY B.도서번호
 ORDER BY B.도서번호;
1
도서번호대출건수
B11
B21
B33
B41
2
도서번호대출건수
B11
B20
B33
B40
3
도서번호대출건수
B11
B33
4
도서번호대출건수
B12
B21
B33
B40
정답 및 해설

대출일 조건에도 (+)가 붙어 있어 이 조건은 ANSI 의 LEFT OUTER JOIN … ON 안 조건과 같고, 도서 4권이 모두 남는다.

3월 이후 대출만 짝지어져 B1은 1건, B3은 3건이고 B2·B4는 NULL 확장 행이라 COUNT(열)이 0을 센다.

  • B1·B3 두 행만 있는 표는 대출일 조건의 (+)를 빼 WHERE 필터가 된 경우다.
  • B2·B4가 1인 표는 NULL 확장 행까지 세는 COUNT(*)의 결과다.
  • B1이 2인 표는 날짜 조건을 무시하고 모든 대출을 센 경우다.
문제 28
각 의사의 평균 진료비보다 진료비가 큰 진료만 조회해 다음 [결과]를 얻으려 한다. ( ㉠ )에 들어갈 조건으로 옳은 것은?

[진료]

진료번호의사번호환자번호진료비
1D1P130000
2D1P250000
3D1P340000
4D2P120000
5D2P426000
6D3P270000
7D3P590000
SELECT A.진료번호, A.의사번호, A.진료비
  FROM 진료 A
 WHERE A.진료비 > (SELECT AVG(B.진료비)
                     FROM 진료 B
                    WHERE ( ㉠ ))
 ORDER BY A.진료번호;

[결과]

진료번호의사번호진료비
2D150000
5D226000
7D390000
1B.진료번호 = A.진료번호
2B.환자번호 = A.환자번호
3B.의사번호 = A.의사번호
4A.의사번호 IS NOT NULL
정답 및 해설

바깥 행의 의사번호를 안쪽에서 참조해야 행마다 같은 의사의 평균이 계산되므로 B.의사번호 = A.의사번호가 맞다.

연관 서브쿼리는 메인쿼리 행마다 다시 실행되어 D1 평균 40000, D2 23000, D3 80000과 비교하고 2·5·7번만 남는다.

  • 환자번호 상관: 환자별 평균과 비교해 1·6번이 나온다.
  • 진료번호 상관: 자기 자신의 평균과 같아 0행이다.
  • A.의사번호 IS NOT NULL: 전체 평균(약 46571)과 비교해 2·6·7번이 나온다.
문제 29
서브쿼리(Subquery)와 뷰에 대한 설명으로 옳은 것은?
1인라인 뷰는 WHERE 절에만 쓰는 서브쿼리다
2스칼라 서브쿼리는 한 행 한 열만 반환한다
3뷰를 만들면 데이터가 별도로 복제된다
4연관 서브쿼리는 메인쿼리 전 한 번 돈다
정답 및 해설

스칼라 서브쿼리는 SELECT 절 등에서 값 하나처럼 쓰이므로 한 행 한 열만 돌려줘야 하고, 여러 행이면 오류가 난다.

인라인 뷰는 FROM 절에 두어 테이블처럼 쓰는 서브쿼리이고, 뷰는 SQL 정의만 저장하는 가상 테이블이다.

  • 인라인 뷰는 WHERE 절이 아니라 FROM 절에 쓰는 서브쿼리다.
  • 뷰는 정의(SQL)만 저장하는 가상 테이블이라 데이터를 복제하지 않는다.
  • 연관 서브쿼리는 메인쿼리 행마다 반복 실행된다.
문제 30
다음 두 SQL 의 결과 행 수를 (㉠, ㉡) 순서로 바르게 나열한 것은?

[직원]

직원번호이름지점코드
101김하늘S1
102이도윤S1
103박서연S2
104최민준S2
105정예린S3

[지점]

지점코드지점명관리자번호
S1강남101
S2판교103
S3분당(null)
㉠ SELECT 이름 FROM 직원
    WHERE 직원번호 NOT IN (SELECT 관리자번호 FROM 지점);

㉡ SELECT 이름 FROM 직원 E
    WHERE NOT EXISTS (SELECT 1 FROM 지점 J
                       WHERE J.관리자번호 = E.직원번호);
13, 3
23, 0
30, 3
40, 0
정답 및 해설

㉠은 목록에 NULL이 섞여 직원번호 <> NULL이 UNKNOWN이 되므로 어떤 행도 참이 되지 않아 0행이다.

㉡의 NOT EXISTS는 짝이 되는 행의 존재만 따지고 NULL 관리자번호는 어느 직원과도 같지 않아 102·104·105번 3행이 나온다.

  • 둘 다 3행이라 보면 NOT IN의 NULL 비교를 놓친 것이다.
  • ㉠ 3행·㉡ 0행은 두 연산의 NULL 처리를 뒤바꾼 것이다.
  • 둘 다 0행이라 보면 NOT EXISTS도 NULL에 막힌다고 오해한 것이다.
문제 31
다음 두 테이블에 집합 연산자를 적용한 결과 행 수로 옳은 것은? (각 연산은 SELECT 과목 FROM 상반기수강 ○ SELECT 과목 FROM 하반기수강 형태)

[상반기수강]

과목
DB
DB
통계
파이썬
(null)

[하반기수강]

과목
통계
(null)
자바
1UNION: 4행
2UNION ALL: 7행
3EXCEPT: 3행
4INTERSECT: 2행
정답 및 해설

집합 연산자는 중복을 비교할 때 NULL끼리 같은 값으로 보므로 INTERSECT 결과는 통계와 NULL, 2행이다.

UNION·INTERSECT·EXCEPT(MINUS)는 중복을 제거하고 UNION ALL만 모든 행을 그대로 이어 붙인다.

  • UNION은 DB·통계·파이썬·NULL·자바로 5행이다.
  • EXCEPT는 DB 중복이 제거돼 DB·파이썬 2행이다.
  • UNION ALL은 NULL 행도 포함해 5+3=8행이다.
문제 32
다음 SQL 의 실행 결과로 옳은 것은?

[정회원]

회원번호이름등급
1한지우A
2서준호B
3윤채원A

[준회원]

회원번호이름등급
11서준호B
12강다은C
13윤채원B
SELECT 이름 AS 성명, 등급 FROM 정회원
UNION
SELECT 이름, 등급 FROM 준회원
 ORDER BY 성명, 등급;
1
성명등급
강다은C
서준호B
서준호B
윤채원A
윤채원B
한지우A
2
성명등급
강다은C
서준호B
윤채원A
윤채원B
한지우A
3
성명등급
한지우A
서준호B
윤채원A
강다은C
윤채원B
4
성명등급
강다은C
서준호B
윤채원A
한지우A
정답 및 해설

UNION은 이름과 등급이 모두 같은 행만 하나로 합치므로 서준호 B는 한 번, 등급이 다른 윤채원은 두 행으로 남아 5행이다.

결과 열 이름은 첫 SELECT의 별칭 성명을 따르고, 맨 끝 ORDER BY는 합쳐진 전체 결과를 정렬한다.

  • 윤채원이 한 행인 표는 이름만으로 중복을 판단한 경우다.
  • 정렬되지 않은 표는 ORDER BY가 마지막 SELECT에만 적용된다고 본 것이다.
  • 서준호 B가 두 번인 표는 UNION ALL의 결과다.
문제 33
다음 SQL 결과에서 채널이 NULL 이고 결제수단이 '카드'인 행의 합계는?

[주문]

주문번호채널결제수단금액
1앱카드100
2앱현금40
3웹카드70
4웹카드30
5매장현금50
6매장카드(null)
SELECT 채널, 결제수단, SUM(금액) AS 합계
  FROM 주문
 GROUP BY CUBE(채널, 결제수단)
 ORDER BY 채널, 결제수단;
1100
2140
3200
4290
정답 및 해설

CUBE(채널, 결제수단)는 채널별 소계뿐 아니라 채널을 NULL 로 둔 결제수단별 소계도 만들므로, 카드 소계는 100+70+30=200 이다.

매장의 카드 주문은 금액이 NULL 이라 SUM 에서 제외되며, 채널과 결제수단이 모두 NULL 인 총계 행은 290 이다.

  • 140 은 결제수단이 NULL 인 앱 채널 소계와 혼동한 값이다.
  • 290 은 두 열이 모두 NULL 인 총계 행의 값이다.
  • 100 은 앱 채널의 카드 상세 행 값이다.
문제 34
다음 [결과]를 얻기 위해 ( ㉠ )에 들어갈 구문으로 옳은 것은?

[학생]

학번학과학년
1경영1
2경영2
3컴공1
4컴공1
5컴공3
6통계2
SELECT 학과, 학년, GROUPING(학과) AS G, COUNT(*) AS 인원
  FROM 학생
 GROUP BY ( ㉠ )
 ORDER BY 3, 1, 2;

[결과]

학과학년G인원
경영(null)02
컴공(null)03
통계(null)01
(null)113
(null)212
(null)311
(null)(null)16
1GROUPING SETS (학과, 학년, ())
2학과, 학년
3CUBE (학과, 학년)
4ROLLUP (학과, 학년)
정답 및 해설

결과에 학과별 소계, 학년별 소계, 총계만 있고 학과·학년 상세 행이 없으므로 GROUPING SETS (학과, 학년, ())가 맞다.

GROUPING(학과)는 학과가 집계로 생긴 NULL일 때 1이어서 학년 소계와 총계 행에서 1, 학과 소계 행에서 0이다.

  • ROLLUP은 학과·학년 상세 행이 생기고 학년별 소계가 없다.
  • CUBE는 원하는 소계 외에 상세 행까지 만든다.
  • 일반 GROUP BY 학과, 학년은 상세 행만 만들고 소계가 없다.
문제 35
다음 SQL 의 실행 결과로 옳은 것은? (오름차순 정렬에서 NULL 은 마지막)

[진료실적]

월진료과건수
3내과10
3외과20
4내과30
SELECT 월, 진료과, SUM(건수) AS 합계
  FROM 진료실적
 GROUP BY ROLLUP(월, 진료과)
 ORDER BY 월, 진료과;
1
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
2
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
(null)내과40
(null)외과20
(null)(null)60
3
월진료과합계
3내과10
3외과20
4내과30
(null)내과40
(null)외과20
(null)(null)60
4
월진료과합계
3내과10
3외과20
3(null)30
4내과30
4(null)30
(null)(null)60
정답 및 해설

ROLLUP(월, 진료과)는 (월, 진료과)·(월)·() 세 단계만 만들어 월별 소계 2행과 총계 1행이 상세 3행에 더해진 6행이다.

인수 순서가 계층이 되므로 앞 열인 월 기준 소계만 생기고 진료과별 소계는 나오지 않는다.

  • 진료과 소계가 있고 월 소계가 없는 표는 인수 순서를 뒤집은 ROLLUP(진료과, 월)의 결과다.
  • 총계가 없는 표는 마지막 () 단계를 빠뜨린 것이다.
  • 양쪽 소계가 다 있는 8행 표는 CUBE의 결과다.
문제 36
다음 SQL 의 실행 결과로 옳은 것은?

[배송]

기사배송일건수
K12026-04-015
K12026-04-023
K12026-04-034
K22026-04-016
K22026-04-022
SELECT 기사, 배송일, 건수,
       SUM(건수) OVER (PARTITION BY 기사
                       ORDER BY 배송일) AS 누적
  FROM 배송
 ORDER BY 기사, 배송일;
1
기사배송일건수누적
K12026-04-0155
K12026-04-0238
K12026-04-03412
K22026-04-01618
K22026-04-02220
2
기사배송일건수누적
K12026-04-01512
K12026-04-02312
K12026-04-03412
K22026-04-0168
K22026-04-0228
3
기사배송일건수누적
K12026-04-0155
K12026-04-0238
K12026-04-03412
K22026-04-0166
K22026-04-0228
4
기사배송일건수누적
K12026-04-01512
K12026-04-0237
K12026-04-0344
K22026-04-0168
K22026-04-0222
정답 및 해설

PARTITION BY 기사로 기사마다 따로, ORDER BY 배송일 순으로 처음부터 현재 행까지 더하는 누적 합이라 K1은 5·8·12, K2는 6·8이다.

ORDER BY가 있으면 기본 프레임이 파티션 처음부터 현재 행까지여서 파티션이 바뀌는 K2 첫 행에서 다시 시작한다.

  • 18·20으로 이어지는 표는 PARTITION BY를 무시하고 전체를 누적한 것이다.
  • 12·8이 반복되는 표는 ORDER BY 없는 파티션 전체 합이다.
  • 12·7·4로 줄어드는 표는 배송일 역순으로 누적한 것이다.
문제 37
객실마다 가장 늦은 예약일의 금액을 모든 행에 붙여 다음 [결과]를 얻으려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

[예약]

예약번호객실예약일금액
1R12026-05-01120
2R12026-05-03150
3R12026-05-07130
4R22026-05-02200
5R22026-05-06180
SELECT 예약번호, 객실, 금액, ( ㉠ ) AS 마지막금액
  FROM 예약
 ORDER BY 예약번호;

[결과]

예약번호객실금액마지막금액
1R1120130
2R1150130
3R1130130
4R2200180
5R2180180

[후보]

(가) LEAD(금액) OVER (PARTITION BY 객실 ORDER BY 예약일)
(나) LAST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일)
(다) LAST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일
       ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
(라) FIRST_VALUE(금액) OVER (PARTITION BY 객실 ORDER BY 예약일 DESC)
1(다)
2(가)
3(나)
4(라)
정답 및 해설

예약일 내림차순 파티션의 첫 값이 곧 가장 늦은 예약 금액이므로 FIRST_VALUE … ORDER BY 예약일 DESC가 R1 모든 행에 130, R2 모든 행에 180을 붙인다.

ORDER BY만 둔 윈도우의 기본 프레임은 현재 행까지라서 LAST_VALUE를 그대로 쓰면 자기 금액이 나온다.

  • LEAD는 다음 예약 금액을 돌려주고 마지막 행은 NULL이다.
  • 기본 프레임의 LAST_VALUE는 현재 행 금액과 같다.
  • 1 FOLLOWING까지인 프레임은 다음 행 금액이라 예약번호 1·4가 150·180이 된다.
문제 38
다음 SQL 의 실행 결과로 옳은 것은?

[강의평가]

강의평점
SQL기초95
데이터분석88
모델링88
파이썬80
통계72
SELECT 강의, 평점,
       NTILE(2) OVER (ORDER BY 평점 DESC, 강의) AS 조,
       PERCENT_RANK() OVER (ORDER BY 평점 DESC) AS 백분위
  FROM 강의평가
 ORDER BY 평점 DESC, 강의;
1
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8810.25
파이썬8020.75
통계7221
2
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8810.25
파이썬8020.5
통계7220.75
3
강의평점조백분위
SQL기초9510
데이터분석8810.25
모델링8820.25
파이썬8020.75
통계7221
4
강의평점조백분위
SQL기초9510.2
데이터분석8810.6
모델링8810.6
파이썬8020.8
통계7221
정답 및 해설

5행을 NTILE(2)로 나누면 나머지 1행이 앞 조에 붙어 3행·2행이 되고, PERCENT_RANK는 (RANK−1)/(5−1)이라 0·0.25·0.25·0.75·1이다.

평점 88 동점 두 강의는 RANK가 모두 2이고 다음 파이썬은 RANK 4라서 0.75가 된다.

  • 조가 1·1·2·2·2인 표는 나머지를 뒤 조에 준 것이다.
  • 0.5·0.75로 끝나는 표는 DENSE_RANK처럼 순위를 건너뛰지 않은 경우다.
  • 0.2·0.6으로 시작하는 표는 CUME_DIST의 값이다.
문제 39
다음 세 SQL 의 결과 행 수를 (㉠, ㉡, ㉢) 순서로 바르게 나열한 것은?

[게시글]

글번호게시판작성자
1공지관리자
2공지관리자
3자유민서
4자유도현
5자유민서
6질문하린
7질문도현
8(null)하린
㉠ SELECT 게시판, COUNT(*) FROM 게시글 GROUP BY 게시판;
㉡ SELECT 게시판, COUNT(*) OVER (PARTITION BY 게시판)
     FROM 게시글;
㉢ SELECT DISTINCT 게시판,
          COUNT(*) OVER (PARTITION BY 게시판)
     FROM 게시글;
14, 4, 4
24, 8, 8
33, 8, 3
44, 8, 4
정답 및 해설

GROUP BY는 그룹당 한 행으로 줄이지만 윈도우 함수는 원래 행을 그대로 두고 값만 붙이므로 ㉠ 4행, ㉡ 8행, ㉢ 4행이다.

게시판이 NULL인 글도 GROUP BY와 PARTITION BY에서 하나의 그룹이 되어 공지·자유·질문과 함께 4개로 묶이고, ㉢은 DISTINCT로 같은 행을 줄인다.

  • 3으로 센 것은 NULL 게시판을 그룹에서 뺀 경우다.
  • ㉡을 4행으로 본 것은 윈도우 함수가 행을 줄인다고 오해한 것이다.
  • ㉢을 8행으로 본 것은 DISTINCT의 중복 제거를 놓친 것이다.
문제 40
SQL Server 에서 [랭킹] 테이블에 ㉠~㉣ 을 실행할 때 오류가 발생하는 것은?

[랭킹]

선수기록
하늘95
바다88
구름88
들꽃72
별빛60
㉠ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC
     OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
㉡ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC
     FETCH NEXT 3 ROWS ONLY;
㉢ SELECT TOP (3) 선수, 기록 FROM 랭킹
     ORDER BY 기록 DESC;
㉣ SELECT 선수, 기록 FROM 랭킹
     ORDER BY 2 DESC
     OFFSET 1 ROW FETCH FIRST 2 ROWS ONLY;
1㉠
2㉢
3㉡
4㉣
정답 및 해설

SQL Server 에서 FETCH 는 ORDER BY 뒤의 OFFSET 절에 딸린 선택 구문이라, OFFSET 없이 FETCH 만 쓰면 구문 오류가 난다.

처음부터 n 건을 가져오려면 OFFSET 0 ROWS 를 함께 적거나 TOP 을 쓴다.

  • OFFSET 0 ROWS 뒤에 FETCH NEXT 를 붙인 구문은 상위 3건을 가져온다.
  • TOP (3) 과 ORDER BY 를 함께 쓴 구문은 정상 실행된다.
  • FIRST·NEXT 와 ROW·ROWS 는 같은 뜻이라 열 번호 정렬과 함께 써도 정상이다.
문제 41
다음 SQL 의 실행 결과로 옳은 것은?

[실적]

사번지점매출
1강남500
2강남700
3강남500
4강남300
5판교400
6판교900
7판교650
SELECT 지점, 사번, 매출
  FROM (SELECT 지점, 사번, 매출,
               ROW_NUMBER() OVER (PARTITION BY 지점
                                  ORDER BY 매출 DESC, 사번) AS RN
          FROM 실적) T
 WHERE RN <= 2
 ORDER BY 지점, RN;
1
지점사번매출
강남2700
판교6900
2
지점사번매출
강남2700
강남1500
강남3500
판교6900
판교7650
3
지점사번매출
강남4300
강남1500
판교5400
판교7650
4
지점사번매출
강남2700
강남1500
판교6900
판교7650
정답 및 해설

ROW_NUMBER는 동점이어도 1, 2, 3처럼 고유 순번을 주므로 지점별로 정확히 2행씩, 강남 사번 2·1과 판교 사번 6·7이 나온다.

강남의 500 동점 두 명은 ORDER BY의 두 번째 기준인 사번 순으로 사번 1이 2위, 사번 3이 3위가 되어 사번 3은 빠진다.

  • 강남 사번 3까지 나온 표는 동점을 같은 순위로 주는 RANK를 쓴 경우다.
  • 매출이 낮은 사원이 나온 표는 오름차순으로 정렬한 경우다.
  • 2행뿐인 표는 PARTITION BY 없이 전체 상위 2명을 뽑은 경우다.
문제 42
Oracle 계층형 질의(Hierarchical Query)에서 루트부터 현재 행까지의 경로를 구분자로 이어 문자열로 돌려주는 것은?
1SYS_CONNECT_BY_PATH
2CONNECT_BY_ISCYCLE
3CONNECT_BY_ROOT
4LISTAGG WITHIN GROUP
정답 및 해설

SYS_CONNECT_BY_PATH(열, 구분자)는 루트에서 현재 행까지 거쳐 온 값을 구분자로 이어 붙인 경로 문자열을 돌려준다.

예를 들어 /본사/개발본부/데이터 처럼 계층 위치를 한 열로 보여 줄 때 쓰며 CONNECT BY 절과 함께만 쓸 수 있다.

  • CONNECT_BY_ROOT는 현재 행이 속한 루트 행의 값을 돌려준다.
  • CONNECT_BY_ISCYCLE은 NOCYCLE 사용 시 순환 여부를 1과 0으로 표시한다.
  • LISTAGG는 그룹 안의 값을 이어 붙이는 집계 함수로 계층 경로와 무관하다.
문제 43
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[부서]

부서코드부서명상위부서
D1본사(null)
D2영업본부D1
D3개발본부D1
D4국내영업D2
D5해외영업D2
D6백엔드D3
D7데이터D3
SELECT LEVEL, 부서명
  FROM 부서
 START WITH 상위부서 IS NULL
CONNECT BY PRIOR 부서코드 = 상위부서
 ORDER SIBLINGS BY 부서명;
1
LEVEL부서명
2개발본부
3국내영업
3데이터
3백엔드
1본사
2영업본부
3해외영업
2
LEVEL부서명
1본사
2영업본부
3국내영업
3해외영업
2개발본부
3백엔드
3데이터
3
LEVEL부서명
1본사
2개발본부
2영업본부
3국내영업
3데이터
3백엔드
3해외영업
4
LEVEL부서명
1본사
2개발본부
3데이터
3백엔드
2영업본부
3국내영업
3해외영업
정답 및 해설

ORDER SIBLINGS BY는 부모 아래 자식이 바로 이어지는 계층 순서를 지키면서 같은 부모를 둔 형제끼리만 부서명 순으로 정렬한다.

본사 아래 개발본부가 영업본부보다 앞서고, 개발본부의 자식은 데이터·백엔드, 영업본부의 자식은 국내영업·해외영업 순으로 따라온다.

  • 부서명만으로 전부 섞인 표는 일반 ORDER BY 부서명의 결과다.
  • LEVEL별로 모은 표는 너비 우선 순서로 계층 전개를 오해한 것이다.
  • 영업본부가 먼저인 표는 형제 정렬을 무시하고 부서코드 순으로 본 것이다.
문제 44
Oracle 에서 다음 SQL 을 실행한 결과 행 수는?

[분기실적]

지점Q1Q2Q3
강남1020(null)
판교(null)(null)(null)
분당5(null)15
일산789
SELECT 지점, 분기, 실적
  FROM 분기실적
UNPIVOT (실적 FOR 분기 IN (Q1, Q2, Q3))
 ORDER BY 지점, 분기;
17
212
34
49
정답 및 해설

UNPIVOT은 열 Q1~Q3을 행으로 펼치되 기본값이 EXCLUDE NULLS라서 실적이 NULL인 칸은 행으로 만들지 않아 2+0+2+3=7행이다.

세 분기가 모두 NULL인 판교는 결과에서 아예 사라진다.

  • 4행은 원본 행 수로, 열을 행으로 펼친다는 점을 놓친 값이다.
  • 9행은 판교만 빼고 나머지 NULL 칸은 남긴다고 본 값이다.
  • 12행은 INCLUDE NULLS를 지정했을 때의 행 수다.
문제 45
Oracle 에서 다음 SQL 을 실행한 결과로 옳은 것은?

[회원]

회원ID연락처
m01010-1234-5678
m0202-987-6543
m03031-55-0909
SELECT 회원ID,
       REGEXP_SUBSTR(연락처, '[0-9]+', 1, 2) AS 중간,
       REGEXP_INSTR(연락처, '-', 1, 2) AS 위치
  FROM 회원
 ORDER BY 회원ID;
1
회원ID중간위치
m0112349
m029877
m03557
2
회원ID중간위치
m0112348
m029876
m03556
3
회원ID중간위치
m0112344
m029873
m03554
4
회원ID중간위치
m01109
m0227
m03317
정답 및 해설

세 번째 인수 1은 시작 위치, 네 번째 인수 2는 두 번째 일치를 뜻하므로 숫자 묶음은 1234·987·55, 두 번째 하이픈 위치는 9·7·7이다.

REGEXP_INSTR는 문자열 첫 글자를 1로 세며, 010-1234-5678에서 두 번째 하이픈은 9번째 글자다.

  • 10·2·31이 나온 표는 2를 시작 위치로 오해해 둘째 글자부터 첫 묶음을 자른 것이다.
  • 8·6·6은 위치를 0부터 센 값이다.
  • 4·3·4는 첫 번째 하이픈의 위치다.
문제 46
DELETE, TRUNCATE, DROP 에 대한 설명으로 옳은 것은? (Oracle 기준)
1DROP은 WHERE로 일부 행만 지운다
2TRUNCATE 후에도 테이블 구조는 남는다
3TRUNCATE는 ROLLBACK으로 되돌린다
4DELETE는 테이블 구조까지 제거한다
정답 및 해설

TRUNCATE는 테이블의 모든 행을 지우고 저장 공간을 정리하지만 테이블 정의(구조)는 남겨 바로 다시 입력할 수 있다.

Oracle 에서 TRUNCATE·DROP은 DDL이라 자동 커밋되어 ROLLBACK으로 되돌릴 수 없고, DELETE는 DML이라 커밋 전 되돌릴 수 있다.

  • DELETE는 행만 지우고 구조는 그대로 둔다.
  • DROP은 테이블 자체를 없애며 WHERE 절을 쓸 수 없다.
  • TRUNCATE는 실행과 동시에 커밋돼 롤백 대상이 아니다.
문제 47
Oracle 의 한 세션에서 다음 문장을 차례로 실행했을 때 마지막 SELECT 의 결과는?
-- 대출 테이블에는 COMMIT 된 행이 2개 있다
INSERT INTO 대출 VALUES (3, 'B2', SYSDATE);
CREATE TABLE 대출백업 (대출번호 NUMBER);
INSERT INTO 대출 VALUES (4, 'B3', SYSDATE);
ROLLBACK;
SELECT COUNT(*) FROM 대출;
14
23
32
40
정답 및 해설

Oracle 은 DDL을 실행하면 그 앞의 트랜잭션을 암시적으로 COMMIT하므로 대출번호 3 INSERT는 CREATE TABLE 시점에 확정된다.

그 뒤 대출번호 4 INSERT만 새 트랜잭션에 남아 ROLLBACK으로 취소되어 행 수는 3이다.

  • 2는 DDL의 자동 커밋을 모르고 두 INSERT가 모두 취소된다고 본 값이다.
  • 4는 ROLLBACK이 아무것도 되돌리지 못한다고 본 값이다.
  • 0은 ROLLBACK이 이미 커밋된 행까지 지운다고 오해한 값이다.
문제 48
Oracle 에서 행 3개가 들어 있는 다음 [도서] 테이블에 실행했을 때 오류가 발생하는 문장은?

[도서] 제목 VARCHAR2(50)

도서번호제목저자쪽수
B1데이터베이스 입문오세린320
B2SQL 활용문태오280
B3모델링 기초오세린(null)
1ALTER TABLE 도서 MODIFY (제목 VARCHAR2(80))
2ALTER TABLE 도서 DROP COLUMN 쪽수
3ALTER TABLE 도서 ADD (분류 CHAR(2) NOT NULL)
4ALTER TABLE 도서 RENAME COLUMN 저자 TO 지은이
정답 및 해설

이미 행이 있는 테이블에 DEFAULT 없이 NOT NULL 열을 추가하면 기존 행의 새 열이 NULL이 되어 제약을 어기므로 오류가 난다.

이때는 DEFAULT 값을 함께 주거나 NULL 허용으로 추가한 뒤 값을 채우고 제약을 건다.

  • 열 길이를 늘리는 MODIFY는 기존 데이터와 충돌하지 않는다.
  • RENAME COLUMN은 열 이름만 바꾸는 정상 구문이다.
  • DROP COLUMN은 NULL이 섞인 열도 문제없이 삭제한다.
문제 49
다음 문장을 실행한 뒤 [진료] 테이블의 (전체 행 수, 환자번호가 NULL 인 행 수)로 옳은 것은?
CREATE TABLE 환자 (환자번호 INT PRIMARY KEY, 이름 VARCHAR(10));
CREATE TABLE 진료 (
  진료번호 INT PRIMARY KEY,
  환자번호 INT REFERENCES 환자(환자번호)
           ON DELETE SET NULL,
  진료과   VARCHAR(10));
-- 환자: 1, 2, 3 / 진료(진료번호, 환자번호): (1,1) (2,2) (3,2) (4,3) (5,NULL)
DELETE FROM 환자 WHERE 환자번호 = 2;
15, 1
23, 1
35, 2
45, 3
정답 및 해설

ON DELETE SET NULL은 부모 행이 지워질 때 참조하던 자식 행을 지우지 않고 외래키 값만 NULL로 바꾸므로 진료는 5행 그대로다.

환자 2를 참조하던 진료번호 2·3이 NULL이 되고 원래 NULL이던 진료번호 5까지 더해 NULL 3행이다.

  • NULL 2행은 원래 NULL이던 진료번호 5를 빠뜨린 값이다.
  • 3행·NULL 1행은 자식까지 지우는 ON DELETE CASCADE의 결과다.
  • 5행·NULL 1행은 아무 변화가 없는 경우로, RESTRICT라면 DELETE 자체가 오류다.
문제 50
DCL 에서 사용하는 롤(ROLE)에 대한 설명으로 옳은 것은?
1롤은 다른 롤에게 부여할 수 없다
2롤을 회수해도 그 권한은 남는다
3시스템 권한은 롤에 담을 수 없다
4여러 권한을 묶어 한 번에 부여한다
정답 및 해설

롤(ROLE)은 여러 권한을 하나로 묶은 이름으로, GRANT 롤 TO 사용자 한 번으로 묶인 권한을 모두 줄 수 있어 권한 관리가 쉬워진다.

롤에는 CREATE SESSION 같은 시스템 권한과 객체 권한을 모두 담을 수 있다.

  • CONNECT·RESOURCE 롤처럼 시스템 권한을 담는 것이 일반적이다.
  • 롤은 다른 롤에 부여해 계층적으로 묶을 수 있다.
  • 롤을 REVOKE하면 그 롤로 받은 권한도 함께 사라진다.