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

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

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

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

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

총 50문항 · 객관식 · 정답·해설 포함
문제 1
데이터 모델링의 특징 중 "대상의 애매모호함을 제거하고 현상을 정확하게 기술하는 것"에 해당하는 것은?
1명확화
2정규화
3단순화
4추상화
정답 및 해설

대상의 애매모호함을 없애고 현상을 정확하게 기술하는 특징은 명확화이다.

모델링의 세 특징은 현실을 일정한 형식으로 표현하는 추상화, 제한된 표기법으로 쉽게 이해하게 하는 단순화, 그리고 명확화이다.

  • 추상화는 현실 세계를 일정한 형식에 맞추어 표현하는 것이다.
  • 단순화는 제한된 표기법과 언어로 쉽게 이해하도록 표현하는 것이다.
  • 정규화는 이상 현상을 없애는 설계 기법으로 세 특징에 들지 않는다.
문제 2
영화 예매 시스템의 ERD를 작성할 때, 엔터티 간 관계를 설정하고 관계명을 기술한 바로 다음에 수행하는 단계는?
1관계 참여도 기술
2관계 설정
3엔터티 배치
4관계 필수여부 기술
정답 및 해설

ERD 는 엔터티 도출·배치 → 관계 설정 → 관계명 기술 → 관계 참여도 기술 → 관계 필수여부 기술 순으로 작성한다.

관계명을 붙인 뒤에는 한 인스턴스가 상대 인스턴스 몇 개와 관계를 맺는지(1 또는 N)를 먼저 표시하고, 마지막에 반드시·선택 여부를 표시한다.

  • 엔터티 배치는 관계를 설정하기 전에 하는 단계다.
  • 관계 설정은 관계명 기술보다 앞선 단계다.
  • 관계 필수여부 기술은 참여도 기술 다음의 마지막 단계다.
문제 3
영화 예매 시스템의 속성 이름을 정하는 원칙으로 적절하지 않은 것은?
1현업에서 쓰는 업무 용어로 짓는다
2모델 전체에서 유일하게 짓는다
3뜻이 드러나게 서술식으로 짓는다
4약어 사용은 가급적 제한한다
정답 및 해설

속성 이름은 명사형의 간결한 업무 용어로 지어야 하며 서술식 속성명(예: 고객이 예매한 좌석의 번호)은 쓰지 않는다.

속성명은 해당 업무에서 쓰는 용어를 따르고, 약어를 줄이며, 데이터 모델 전체에서 유일하게 지어야 혼동이 없다.

  • 현업에서 실제로 쓰는 용어를 속성명으로 쓰는 것이 원칙이다.
  • 약어는 의미 전달을 어렵게 하므로 가급적 제한한다.
  • 같은 이름이 여러 엔터티에서 다른 뜻으로 쓰이지 않게 유일하게 짓는다.
문제 4
다음 ERD를 읽은 내용으로 옳은 것은?

그림

1모든 상영에는 예매가 반드시 존재한다
2예매 1건은 여러 상영과 관계를 맺는다
3상영이 편성되지 않은 영화도 있을 수 있다
4모든 회원은 예매를 1건 이상 한다
정답 및 해설

영화 쪽에서 상영 끝에 원(O)과 까마귀발이 있으므로 영화 하나는 상영을 0개 이상 가지며, 상영이 없는 영화도 존재할 수 있다.

관계선 끝의 원은 선택 참여, 바(|)는 필수 참여, 까마귀발은 N 을 뜻하며 상대편 끝의 기호를 읽는다.

  • 회원 쪽에서 본 예매 끝에 원이 있어 예매가 없는 회원도 있다.
  • 예매 쪽에서 본 상영 끝은 까마귀발 없이 바만 있어 예매 1건은 상영 1개에만 속한다.
  • 상영 쪽에서 본 예매 끝에 원이 있어 예매 없는 상영도 가능하다.
문제 5
다음 ERD에 대한 설명으로 옳은 것은? (회원의 이메일은 회원마다 다르고 NULL 이 없다)

그림

1상영순번은 상영의 외부식별자이다
2회원의 이메일은 보조식별자에 해당한다
3상영의 주식별자는 단일식별자이다
4예매의 영화코드는 내부식별자이다
정답 및 해설

이메일은 회원 인스턴스를 유일하게 구분할 수 있지만 주식별자로 쓰이지 않는 속성이므로 보조식별자에 해당한다.

상영은 영화에서 식별 관계로 받은 영화코드와 스스로 만든 상영순번을 합친 복합식별자이며, 관계로 받아 온 속성은 외부식별자이다.

  • 상영의 주식별자는 두 속성으로 이루어진 복합식별자다.
  • 예매의 영화코드는 상영과의 관계로 받은 외부식별자다.
  • 상영순번은 상영이 스스로 생성한 내부식별자다.
문제 6
다음 ERD의 [상영좌석] 엔터티에 함수 종속 (상영번호, 좌석번호) → 판매가, 상영번호 → 상영관번호, 상영관번호 → 상영관명 이 성립한다. [상영좌석]의 정규형으로 옳은 것은? (모든 속성은 원자값이다)

그림

1부분 종속이 남아 제1정규형이다
2제3정규형까지 모두 만족한다
3이행 종속만 남은 제2정규형이다
4제1정규형도 만족하지 못한다
정답 및 해설

상영관번호가 주식별자의 일부인 상영번호에만 종속되는 부분 함수 종속이 있으므로 [상영좌석]은 제1정규형이지만 제2정규형은 아니다.

속성이 모두 원자값이라 1NF 는 만족하며, 상영관번호·상영관명을 상영 쪽으로 분리해야 2NF 가 되고 상영관명의 이행 함수 종속은 그다음 단계에서 제거한다.

  • 모든 속성이 원자값이므로 1NF 는 만족한다.
  • 부분 함수 종속이 남아 있어 2NF 를 만족하지 못한다.
  • 2NF 도 아니므로 3NF 까지 만족할 수 없다.
문제 7
영화 장르를 [장르](장르코드, 장르명, 상위장르코드) 하나로 두고 상위장르코드가 같은 엔터티의 장르코드를 참조하게 모델링했다. 이 모델의 특징으로 옳은 것은?
1단계가 늘어도 엔터티 구조는 그대로다
2한 장르가 여러 상위 장르를 가진다
3상위 장르명은 별도 테이블로 조회한다
4최상위 장르의 상위장르코드는 필수다
정답 및 해설

자기참조(재귀) 관계로 만든 계층 모델은 대분류·중분류처럼 단계가 늘어나도 행만 추가하면 되므로 엔터티 구조를 바꾸지 않는다.

상위 장르명은 같은 테이블을 별칭으로 두 번 쓰는 셀프 조인으로 조회하며, 최상위 장르는 부모가 없어 상위장르코드가 NULL 이다.

  • 최상위 장르는 상위가 없으므로 상위장르코드가 NULL 이어야 한다.
  • 같은 테이블을 셀프 조인하면 되므로 다른 테이블이 없어도 된다.
  • 상위장르코드 속성이 하나뿐이라 부모는 최대 하나다.
문제 8
예매 1건은 예매좌석 여러 건으로 구성되며, 두 엔터티는 항상 함께 생성되고 예매 취소 시 함께 삭제된다. 이에 대한 설명으로 적절하지 않은 것은?
1취소 시 둘 다 지워야 일관성이 유지된다
2좌석 삭제는 별도 트랜잭션으로 나눈다
3두 엔터티는 서로 필수 관계로 표현한다
4일부만 반영되면 작업 전체를 취소한다
정답 및 해설

항상 함께 생성·삭제되는 예매와 예매좌석은 업무상 하나의 단위이므로 하나의 트랜잭션으로 묶어야 하며 좌석 삭제만 따로 떼면 안 된다.

별도 트랜잭션으로 나누면 예매만 지워지고 좌석이 남는 중간 상태가 생겨 원자성과 일관성이 깨진다.

  • 함께 존재해야 하므로 양쪽 모두 필수 참여 관계로 표현한다.
  • 취소할 때 예매와 좌석을 모두 지워야 데이터가 맞는다.
  • 한쪽만 처리되면 전체를 롤백해 작업 전 상태로 되돌린다.
문제 9
다음과 같이 [관람평]의 한줄평(가변 길이 문자형)에 값을 입력한 뒤 SELECT COUNT(*) FROM 관람평 WHERE 한줄평 IS NULL; 을 실행했다. Oracle 과 SQL Server 의 결과를 차례대로 나타낸 것은?

[관람평]

관람평번호입력한 한줄평 값
1'재밌음'
2'' (빈 문자열)
3NULL
4' ' (공백 1칸)
12, 2
23, 1
32, 1
41, 1
정답 및 해설

Oracle 은 빈 문자열을 NULL 로 저장하므로 관람평번호 2·3 이 IS NULL 에 해당해 2이고, SQL Server 는 빈 문자열을 길이 0 문자열로 따로 저장해 3만 세어 1이다.

공백 1칸은 길이 1인 문자 값이므로 두 DBMS 모두 NULL 이 아니다.

  • Oracle 에서 빈 문자열이 NULL 로 바뀌는 점을 놓치면 1로 본다.
  • 공백 1칸까지 NULL 로 보면 Oracle 이 3이 되지만 공백은 값이다.
  • SQL Server 는 빈 문자열을 NULL 로 바꾸지 않아 2가 아니다.
문제 10
영화 예매 모델에서 식별자를 대체 여부에 따라 본질식별자와 인조식별자로 나눌 때, 설명으로 옳은 것은?
1인조식별자는 부모에게서 상속받는다
2인조식별자는 반드시 복합키로 구성된다
3본질식별자는 순번으로만 부여한다
4업무에 의해 생긴 식별자는 본질식별자다
정답 및 해설

대체 여부 기준에서 업무 규칙에 의해 자연스럽게 만들어지는 식별자가 본질식별자이고, 원조식별자가 복잡해 인위적으로 만든 것이 인조식별자이다.

예를 들어 (회원번호, 상영번호, 좌석번호) 대신 시스템이 붙인 예매번호는 인조식별자이며 보통 단일 순번 속성으로 만든다.

  • 인조식별자는 대개 한 속성짜리 일련번호여서 복합키일 필요가 없다.
  • 본질식별자는 업무 값으로 정해지며 순번으로 부여하는 것은 인조식별자의 방식이다.
  • 부모에게서 상속받는지는 내부·외부식별자 구분 기준이다.
문제 11
[회원] 테이블에서 회원번호와 이메일은 각각 단독으로 모든 행을 유일하게 식별하며 최소성을 만족한다. 회원번호를 기본키로 정했을 때 이메일은 어떤 키에 해당하는가?
1대체키(Alternate Key)
2외래키(Foreign Key)
3복합키(Composite Key)
4인조키(Surrogate Key)
정답 및 해설

유일성과 최소성을 갖춘 후보키 중 기본키로 뽑히지 않은 나머지를 대체키(Alternate Key)라 하므로 이메일은 대체키이다.

후보키는 회원번호와 이메일 둘이고 그중 회원번호가 기본키가 되었으며, 대체키에는 보통 UNIQUE 제약을 걸어 유일성을 지킨다.

  • 외래키는 다른 테이블의 기본키를 참조하는 열이다.
  • 복합키는 두 개 이상의 열을 묶은 키인데 이메일은 단일 열이다.
  • 인조키는 업무와 무관하게 시스템이 만든 일련번호 같은 키이다.
문제 12
다음 SQL의 실행 결과로 옳은 것은?

[예매]

예매번호인원단가할인
12120001000
2112000(null)
3(null)90000
4390003000
SELECT 예매번호,
       인원 * 단가 AS 정가합,
       인원 * 단가 - 할인 AS 결제액
  FROM 예매
 ORDER BY 예매번호;
1
예매번호정가합결제액
12400023000
212000(null)
3(null)(null)
42700024000
2
예매번호정가합결제액
12400023000
21200012000
3(null)(null)
42700024000
3
예매번호정가합결제액
12400023000
212000(null)
300
42700024000
4
예매번호정가합결제액
12400022000
212000(null)
3(null)(null)
42700018000
정답 및 해설

산술식에 NULL 이 하나라도 있으면 결과는 NULL이므로 할인이 NULL 인 예매번호 2 는 결제액이, 인원이 NULL 인 3 은 정가합과 결제액이 모두 NULL 이다.

곱셈이 뺄셈보다 먼저 계산되어 1은 24000-1000=23000, 4는 27000-3000=24000 이다.

  • NULL 을 0으로 보고 빼면 2의 결제액이 12000 이 되지만 실제는 NULL 이다.
  • NULL 과의 곱도 0이 아니라 NULL 이므로 3을 0으로 보면 틀린다.
  • 단가-할인을 먼저 계산하면 22000·18000 이 나오지만 우선순위와 다르다.
문제 13
Oracle 기준으로 SELECT 문의 FROM 절과 별칭에 대한 설명으로 옳은 것은?
1WHERE 절에서 열 별칭을 참조한다
2SELECT * 는 열 순서를 임의로 바꾼다
3별칭을 준 뒤에도 테이블명으로 한정한다
4테이블 별칭 앞에는 AS 를 쓸 수 없다
정답 및 해설

Oracle 은 열 별칭에는 AS 를 허용하지만 테이블 별칭 앞에는 AS 를 쓸 수 없어 FROM 상영 S 처럼 바로 붙여 쓴다.

또 SELECT 절의 열 별칭은 WHERE 절보다 늦게 정해지므로 WHERE 에서는 쓸 수 없고 ORDER BY 에서만 쓸 수 있다.

  • WHERE 절은 SELECT 보다 먼저 처리되어 열 별칭을 참조하면 오류가 난다.
  • 테이블에 별칭을 주면 열은 그 별칭으로 한정해야 하고 원래 테이블명을 쓰면 오류가 난다.
  • SELECT * 는 테이블에 정의된 열 순서대로 모든 열을 돌려준다.
문제 14
Oracle 기준으로, 상영코드(지점-관번호-시각)에서 관번호 두 자리만 다음 결과처럼 꺼내려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

[상영]

상영번호상영코드
1강남-07-1930
2신촌역-03-2100
3홍대-12-1015
4일산호수-05-0900
SELECT 상영번호, ( ㉠ ) AS 관번호
  FROM 상영
 ORDER BY 상영번호;

[원하는 결과]

상영번호관번호
107
203
312
405
1SUBSTR(상영코드, INSTR(상영코드, '-') + 1, 2)
2SUBSTR(상영코드, 4, 2)
3LTRIM(SUBSTR(상영코드, 3, 3), '-')
4SUBSTR(상영코드, LENGTH(상영코드) - 6)
정답 및 해설

INSTR(상영코드, '-') 가 첫 하이픈 위치를 돌려주므로 그 다음 위치부터 2글자를 자르면 지점명 길이와 관계없이 07·03·12·05 가 나온다.

지점명이 2~4글자로 달라 관번호의 시작 위치가 행마다 다르므로 고정 위치가 아닌 구분자 위치를 기준으로 잘라야 한다.

  • 길이를 생략한 SUBSTR 은 끝까지 잘라 07-1930 처럼 시각까지 나온다.
  • 3번째부터 3글자는 지점명이 2글자일 때만 맞고 신촌역은 '역-0' 이 된다.
  • 4번째부터 2글자도 지점명이 2글자인 행에서만 관번호가 나온다.
문제 15
다음 SQL의 실행 결과로 옳은 것은?

[회원]

회원번호휴대폰이메일포인트
1010-11kim@a.kr3500
2(null)lee@a.kr1200
3(null)(null)(null)
4010-44(null)800
SELECT 회원번호,
       COALESCE(휴대폰, 이메일, '미등록') AS 연락처,
       CASE WHEN 포인트 >= 1000 THEN 'VIP'
            WHEN 포인트 >= 3000 THEN 'VVIP'
            ELSE '일반' END AS 등급
  FROM 회원
 ORDER BY 회원번호;
1
회원번호연락처등급
1010-11VIP
2미등록VIP
3미등록일반
4010-44일반
2
회원번호연락처등급
1010-11VVIP
2lee@a.krVIP
3미등록일반
4010-44일반
3
회원번호연락처등급
1010-11VIP
2lee@a.krVIP
3미등록일반
4010-44일반
4
회원번호연락처등급
1010-11VIP
2lee@a.krVIP
3미등록(null)
4010-44일반
정답 및 해설

COALESCE 는 왼쪽부터 처음 만난 NOT NULL 값을 돌려주므로 2는 이메일, 3은 '미등록'이 되고, 검색 CASE 는 처음 참인 WHEN 에서 멈춰 3500 포인트인 1도 VIP 가 된다.

포인트가 NULL 인 3은 두 비교가 모두 UNKNOWN 이라 ELSE 의 '일반'을 받는다.

  • 더 높은 조건을 찾아 VVIP 를 주지 않으며, 앞선 WHEN 이 먼저 참이 된다.
  • ELSE 가 있으므로 NULL 비교 행도 NULL 이 아니라 '일반'이다.
  • 휴대폰이 NULL 이면 다음 인수인 이메일을 보므로 2는 '미등록'이 아니다.
문제 16
Oracle 기준으로, 가입 후 한 달 쿠폰의 만료일을 구하는 다음 SQL의 실행 결과로 옳은 것은?

[회원]

회원번호가입일
12026-01-31
22026-02-28
32026-03-15
42026-04-30
52026-05-30
SELECT 회원번호,
       TO_CHAR(ADD_MONTHS(가입일, 1), 'YYYY-MM-DD') AS 만료일
  FROM 회원
 ORDER BY 회원번호;
1
회원번호만료일
12026-03-02
22026-03-30
32026-04-14
42026-05-30
52026-06-29
2
회원번호만료일
12026-02-28
22026-03-31
32026-04-15
42026-05-31
52026-06-30
3
회원번호만료일
12026-02-28
22026-03-28
32026-04-15
42026-05-30
52026-06-30
4
회원번호만료일
12026-03-03
22026-03-31
32026-04-15
42026-05-31
52026-06-30
정답 및 해설

ADD_MONTHS 는 입력일이 그 달의 말일이면 결과도 결과 월의 말일로 맞추므로 2월 28일은 3월 31일, 4월 30일은 5월 31일이 된다.

1월 31일처럼 결과 월에 같은 날이 없으면 그 달 말일인 2월 28일이 되고, 말일이 아닌 3월 15일·5월 30일은 날짜만 그대로 옮겨진다.

  • 말일 규칙을 빼고 같은 날짜로만 옮기면 3월 28일·5월 30일이 나온다.
  • 존재하지 않는 2월 31일을 넘겨 3월로 보내지 않고 2월 말일에서 멈춘다.
  • 한 달 더하기는 30일 더하기가 아니므로 3월 2일 같은 값이 나오지 않는다.
문제 17
다음 SQL의 실행 결과 행 수는?

[영화]

영화번호제목관람등급
1파도12
2여름밤19
3유리새(null)
4서울역15
5모래성(null)
6달무리전체
SELECT 영화번호, 제목
  FROM 영화
 WHERE NOT (관람등급 = '19')
    OR 관람등급 = NULL
 ORDER BY 영화번호;
16
22
33
45
정답 및 해설

관람등급이 NULL 인 행은 관람등급 = '19' 가 UNKNOWN 이고 NOT 을 붙여도 UNKNOWN 이며, = NULL 비교 역시 항상 UNKNOWN 이라 제외된다.

결국 등급이 있고 19가 아닌 파도·서울역·달무리 3행만 남으며, NULL 행을 찾으려면 IS NULL 을 써야 한다.

  • = NULL 이 NULL 행을 찾는다고 보면 5행이 되지만 결과는 없다.
  • NULL 비교를 참으로 보아 모든 행이 나온다고 보면 6행이다.
  • 문자 '전체'도 '19'와 다른 값이므로 빠지지 않아 2행이 아니다.
문제 18
다음 [조건] 중 나머지 셋과 결과가 다른 것은? (장르·평점에 NULL 은 없다)

[조건]

㉠ WHERE NOT 장르 = '액션' AND 평점 >= 4
㉡ WHERE 장르 <> '액션' AND 평점 >= 4
㉢ WHERE 평점 >= 4 AND NOT 장르 = '액션'
㉣ WHERE NOT (장르 = '액션' AND 평점 >= 4)
1㉠
2㉣
3㉡
4㉢
정답 및 해설

논리 연산자는 NOT → AND → OR 순으로 결합하므로 괄호 없는 NOT 은 바로 뒤의 장르 = '액션' 하나만 부정한다.

그래서 세 조건은 모두 '액션이 아니면서 평점 4 이상'이지만, ㉣은 괄호 전체를 부정해 액션이 아니거나 평점 4 미만인 행을 고른다.

  • ㉠은 NOT 이 장르 비교에만 걸려 액션 외 장르 중 평점 4 이상을 고른다.
  • ㉡은 <> 로 같은 조건을 직접 쓴 것이다.
  • ㉢은 AND 양쪽의 순서만 바꾼 것으로 결과가 같다.
문제 19
다음 [관람평]에서 SELECT ( 식 ) AS 평균 FROM 관람평; 의 식 자리에 넣었을 때 결과가 나머지 셋과 다른 것은?

[관람평]

관람평번호영화번호평점
114
21(null)
325
423
53(null)

[식]

㉠ AVG(평점)
㉡ SUM(평점) / COUNT(평점)
㉢ AVG(평점 + 0)
㉣ AVG(COALESCE(평점, 0))
1㉡
2㉣
3㉠
4㉢
정답 및 해설

COALESCE(평점, 0) 은 NULL 을 0으로 바꿔 다섯 행 모두를 평균에 넣으므로 12/5=2.4 가 되어 나머지와 다르다.

집계 함수는 NULL 을 제외하고 계산하므로 AVG(평점)과 SUM/COUNT(평점)은 12/3=4 이고, 평점 + 0 도 NULL 행은 NULL 그대로라 4이다.

  • ㉠의 AVG 는 NULL 두 행을 빼고 세 값의 평균 4를 낸다.
  • ㉡의 COUNT(평점)도 NULL 을 세지 않아 12/3=4 이다.
  • ㉢의 평점 + 0 은 NULL 이 그대로 NULL 이라 ㉠과 같은 4이다.
문제 20
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호상영관관객수
1IMAX120
2IMAX(null)
32D90
4IMAX200
5(null)150
62D(null)
SELECT COUNT(*) AS 회차,
       COUNT(관객수) AS 집계,
       SUM(관객수) AS 합계
  FROM 상영
 WHERE 상영관 = 'IMAX'
HAVING SUM(관객수) > 300;
1
회차집계합계
32320
2
회차집계합계
33320
3
회차집계합계
4
회차집계합계
22320
정답 및 해설

WHERE 로 IMAX 세 행(120·NULL·200)만 남고, GROUP BY 가 없으므로 이 세 행 전체가 하나의 그룹이 되어 HAVING 합계 320 > 300 이 참이라 1행이 나온다.

COUNT(*)는 NULL 행도 세어 3, COUNT(관객수)는 NULL 을 빼 2이며 SELECT 에는 집계 함수만 있어 그룹 키 없이도 실행된다.

  • COUNT(관객수)는 NULL 을 세지 않으므로 3이 아니다.
  • COUNT(*)는 관객수가 NULL 인 행도 포함하므로 2가 아니다.
  • HAVING 은 GROUP BY 없이도 전체를 한 그룹으로 보고 평가하므로 0행이 아니다.
문제 21
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호영화번호관객수
1M180
2M140
3M160
4M230
5M290
6M3(null)
7M370
8M355
9M4100
SELECT 영화번호, COUNT(*) AS 회차, SUM(관객수) AS 관객
  FROM 상영
 WHERE 관객수 >= 50
 GROUP BY 영화번호
HAVING COUNT(*) >= 2
 ORDER BY 영화번호;
1
영화번호회차관객
M12140
M33125
2
영화번호회차관객
M12140
M2190
M32125
3
영화번호회차관객
M13180
M22120
M33125
4
영화번호회차관객
M12140
M32125
정답 및 해설

WHERE 가 그룹화보다 먼저 실행되어 관객수 50 미만과 NULL 행(2·4·6)이 빠진 뒤 HAVING 이 남은 행 수를 센다.

그 결과 M1(80·60)과 M3(70·55)만 2회가 되어 남고, M2·M4 는 한 행만 남아 HAVING 에서 탈락한다.

  • M2 는 WHERE 뒤 90 한 행만 남아 COUNT 가 1이므로 결과에 없다.
  • NULL 은 50 이상 비교가 UNKNOWN 이라 M3 의 회차는 3이 아니다.
  • WHERE 를 무시하고 모든 행을 센 결과는 실행 순서와 맞지 않는다.
문제 22
다음 SQL의 실행 결과로 옳은 것은?

[영화]

영화번호제목상영시간개봉일
1파도1282026-03-04
2서울역1152026-03-11
3모래성1022026-03-11
4여름밤952026-02-25
5유리새1152026-03-04
SELECT 제목, 상영시간 AS 러닝
  FROM 영화
 ORDER BY 개봉일 DESC, 2;
1
제목러닝
모래성102
서울역115
유리새115
파도128
여름밤95
2
제목러닝
여름밤95
유리새115
파도128
모래성102
서울역115
3
제목러닝
서울역115
모래성102
파도128
유리새115
여름밤95
4
제목러닝
여름밤95
모래성102
서울역115
유리새115
파도128
정답 및 해설

개봉일은 SELECT 목록에 없어도 정렬 키로 쓸 수 있으며, 최신 개봉일(3월 11일)부터 내림차순으로 놓인다.

DESC 는 개봉일에만 적용되고 열 번호 2인 러닝은 기본 ASC 라 같은 날 개봉한 모래성(102)·서울역(115), 유리새(115)·파도(128) 순이 된다.

  • 러닝까지 내림차순으로 보면 서울역이 모래성보다 앞서지만 둘째 키는 ASC 이다.
  • 개봉일을 오름차순으로 보면 여름밤이 먼저 오지만 DESC 가 지정되어 있다.
  • 러닝만으로 정렬한 결과로, 첫째 키인 개봉일을 무시했다.
문제 23
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호시작시
19
210
315
422
523
6(null)

[요금구간]

구간명시작끝
조조710
일반1022
심야2327
SELECT S.상영번호, G.구간명
  FROM 상영 S, 요금구간 G
 WHERE S.시작시 >= G.시작
   AND S.시작시 < G.끝
 ORDER BY S.상영번호;
1
상영번호구간명
1조조
3일반
5심야
2
상영번호구간명
1조조
2조조
2일반
3일반
5심야
3
상영번호구간명
1조조
2일반
3일반
5심야
4
상영번호구간명
1조조
2일반
3일반
4일반
5심야
정답 및 해설

조건이 시작 이상·끝 미만이라 10시는 조조(끝 10)가 아닌 일반에만, 22시는 일반(끝 22)에도 심야(시작 23)에도 들지 않아 빠진다.

시작시가 NULL 인 상영번호 6은 비교가 UNKNOWN 이라 NON-EQUI 조인 결과에 없고, 최종 4행이 남는다.

  • 끝값까지 포함해야 10시가 조조와 일반 두 곳에 매칭되지만 < 는 끝을 뺀다.
  • 10시는 일반의 시작값과 같아 >= 조건을 만족하므로 빠지지 않는다.
  • 22시는 일반의 끝값과 같아 < 조건에서 탈락한다.
문제 24
[영화] 5행 중 관람등급이 '전체'인 행이 2행, [상영관] 3행, [시간대] 4행일 때 다음 SQL의 결과 행 수는?
SELECT *
  FROM 영화 M, 상영관 H, 시간대 T
 WHERE M.관람등급 = '전체';
160행
224행
312행
49행
정답 및 해설

세 테이블 사이에 조인 조건이 하나도 없으므로 카티션 곱이 만들어지고, WHERE 는 영화 쪽 행만 2행으로 줄인다.

따라서 결과는 2 × 3 × 4 = 24행이며 조건이 없는 상영관·시간대는 모든 행이 곱해진다.

  • 필터를 무시하고 5×3×4 로 곱하면 60행이 된다.
  • 행 수를 더한 2+3+4 는 조인 결과와 무관하다.
  • 영화 조건만 남고 영화 행을 곱에서 빼면 12행이 되지만 2행이 곱해진다.
문제 25
다음 [원하는 결과]를 얻기 위해 ( ㉠ )에 들어갈 조인으로 옳은 것은?

[영화]

영화번호제목
1파도
2여름밤
3유리새

[상영]

상영번호영화번호상영관
1111관
1213관
1322관
1491관
SELECT M.제목, S.상영관
  FROM 상영 S ( ㉠ ) 영화 M
    ON S.영화번호 = M.영화번호
 ORDER BY M.영화번호, S.상영번호;

[원하는 결과]

제목상영관
파도1관
파도3관
여름밤2관
유리새(null)
1LEFT OUTER JOIN
2FULL OUTER JOIN
3RIGHT OUTER JOIN
4INNER JOIN
정답 및 해설

원하는 결과에는 상영이 없는 유리새가 상영관 NULL 로 남고 영화번호 9 인 상영은 없으므로, 오른쪽에 쓴 영화를 모두 보존하는 RIGHT OUTER JOIN 이다.

FROM 에 상영을 먼저 썼으므로 상영이 왼쪽, 영화가 오른쪽이며 보존되는 쪽은 조인 키워드의 방향으로 정해진다.

  • INNER JOIN 은 상영이 없는 유리새를 결과에서 뺀다.
  • LEFT OUTER JOIN 은 상영 쪽을 보존해 영화가 없는 상영 14 가 제목 NULL 로 나온다.
  • FULL OUTER JOIN 은 유리새와 상영 14 를 모두 남겨 한 행이 더 생긴다.
문제 26
다음 SQL 의 실행 결과로 옳은 것은?

[영화]

영화번호제목장르
1파도액션
2정원드라마
3추적액션
4별빛애니

[상영]

상영번호영화번호관번호
10111
10212
10321
10443
SELECT M.제목, S.상영번호
  FROM 영화 M
  LEFT OUTER JOIN 상영 S
    ON M.영화번호 = S.영화번호
   AND M.장르 = '액션'
 ORDER BY M.영화번호, S.상영번호;
1
제목상영번호
파도101
파도102
정원(null)
추적(null)
별빛(null)
2
제목상영번호
파도101
파도102
추적(null)
3
제목상영번호
파도101
파도102
정원103
추적(null)
별빛104
4
제목상영번호
파도101
파도102
정답 및 해설

LEFT OUTER JOIN 의 ON 절 조건은 결합 여부만 정하므로, 왼쪽 테이블에 건 M.장르 = '액션' 도 영화 행을 거르지 않고 매칭만 막는다.

액션인 파도는 101·102 와 결합하고, 상영이 없는 추적과 액션이 아닌 정원·별빛은 상영번호가 NULL 인 한 행씩 남아 5행이 된다.

  • 3행 표는 장르 조건을 WHERE 절에 둔 결과로, 정원·별빛이 빠진다.
  • 정원 103·별빛 104 가 붙은 표는 장르 조건을 무시한 결과이다.
  • 2행 표는 INNER JOIN 처럼 결합된 행만 남긴 결과이다.
문제 27
다음 SQL 의 실행 결과로 옳은 것은?

[상영]

상영번호관번호시작시각
201110:00
202213:00
203(null)15:00
204118:00

[상영관]

관번호관이름
11관
22관
3IMAX
SELECT *
  FROM 상영 JOIN 상영관 USING (관번호)
 ORDER BY 상영번호;
1
상영번호관번호시작시각관이름
201110:001관
202213:002관
204118:001관
2
관번호상영번호시작시각관이름
120110:001관
220213:002관
(null)20315:00(null)
120418:001관
3
상영번호관번호시작시각관번호관이름
201110:0011관
202213:0022관
204118:0011관
4
관번호상영번호시작시각관이름
120110:001관
220213:002관
120418:001관
정답 및 해설

USING 으로 조인하면 공통 열 관번호가 결과에 한 번만, 맨 앞에 나오고 나머지 열은 상영·상영관 순으로 이어진다.

INNER 조인이므로 관번호가 NULL 인 203 은 짝이 없어 빠지고, 상영이 없는 IMAX 도 나오지 않아 3행이다.

  • 관번호가 상영 테이블 순서대로 두 번째에 오는 표는 공통 열의 위치를 잘못 본 것이다.
  • 203 이 NULL 로 남은 표는 OUTER JOIN 결과이다.
  • 관번호가 두 번 나오는 표는 ON 절 조인의 SELECT * 결과이다.
문제 28
예매 금액을 서브쿼리 결과와 비교하는 다중행 연산자에 대한 설명으로 적절하지 않은 것은?
SELECT 예매번호, 금액
  FROM 예매
 WHERE 금액 연산자 (SELECT 금액
                     FROM 예매
                    WHERE 회원번호 = 7);
1< ANY 는 최솟값보다 작은 행만 찾는다
2> ALL 은 최댓값보다 큰 행만 찾는다
3= ANY 는 IN 과 같은 결과를 낸다
4= 에 여러 행이 오면 오류가 난다
정답 및 해설

< ANY 는 서브쿼리 결과 중 어느 하나보다만 작으면 참이므로, 실제로는 결과의 최댓값보다 작은 행을 모두 찾는다.

최솟값 미만인 행만 남기려면 전체 값과 비교하는 < ALL 을 써야 한다.

  • = ANY 는 목록 중 하나와 같으면 참이라 IN 과 같은 결과를 낸다.
  • > ALL 은 모든 값보다 커야 하므로 최댓값보다 큰 행만 남는다.
  • 단일행 연산자 = 에 여러 행이 반환되면 실행 오류가 발생한다.
문제 29
다음 SQL 의 실행 결과로 옳은 것은?

[예매]

예매번호상영번호인원
11012
21014
31014
41023
5102(null)
61031
71032
SELECT A.예매번호, A.상영번호, A.인원
  FROM 예매 A
 WHERE A.인원 = (SELECT MAX(B.인원)
                   FROM 예매 B
                  WHERE B.상영번호 = A.상영번호)
 ORDER BY A.예매번호;
1
예매번호상영번호인원
21014
41023
71032
2
예매번호상영번호인원
21014
31014
41023
5102(null)
71032
3
예매번호상영번호인원
21014
31014
4
예매번호상영번호인원
21014
31014
41023
71032
정답 및 해설

연관 서브쿼리는 바깥 행의 상영번호마다 MAX(인원) 을 다시 구하므로, 상영별 최댓값과 같은 행이 동점까지 모두 남아 4행이다.

상영 101 은 인원 4 인 예매 2·3, 102 는 3 인 예매 4, 103 은 2 인 예매 7 이 남고, 인원이 NULL 인 예매 5 는 비교 결과가 UNKNOWN 이라 빠진다.

  • 예매 2·3 만 남은 표는 상관 조건 없이 전체 최댓값과 비교한 결과이다.
  • 상영별 한 행만 남긴 표는 동점 행을 하나로 줄인 것이다.
  • 예매 5 가 포함된 표는 NULL 과의 비교를 참으로 본 것이다.
문제 30
영화별 예매 건수를 다음 결과처럼 구하려 한다. ㉠에 들어갈 조건으로 옳은 것은?

[영화]

영화번호제목
1파도
2정원
3추적

[예매]

예매번호영화번호
111
121
133
141
15(null)
SELECT M.제목,
       (SELECT COUNT(*)
          FROM 예매 R
         WHERE ( ㉠ )) AS 건수
  FROM 영화 M
 ORDER BY M.영화번호;
제목건수
파도3
정원0
추적1
1M.영화번호 IN (1, 3)
2영화번호 IS NOT NULL
3R.영화번호 = M.영화번호
41 = 1
정답 및 해설

바깥 영화 행마다 같은 영화의 예매만 세려면 스칼라 서브쿼리의 조건이 바깥 별칭 M 을 가리키는 상관 조건 R.영화번호 = M.영화번호 여야 한다.

예매가 없는 정원은 COUNT(*) 가 0 을 돌려 0 으로 나오고, 영화번호가 NULL 인 15번은 어느 영화에도 세지지 않는다.

  • 한정자 없는 영화번호는 가장 가까운 R 의 열로 해석되어 NULL 이 아닌 예매 4건이 모든 영화에 세어진다.
  • 1 = 1 은 상관 조건이 없어 모든 영화에 예매 5건이 그대로 세어진다.
  • IN (1, 3) 은 파도·추적에 5, 정원에 0 을 주어 예매 건수와 다르다.
문제 31
다음 SQL 의 실행 결과로 옳은 것은?

[온라인예매]

회원번호금액
712000
39000

[현장예매]

회원번호금액
512000
39000
SELECT 회원번호 AS 회원, 금액 FROM 온라인예매
UNION ALL
SELECT 회원번호, 금액 FROM 현장예매
 ORDER BY 금액 DESC, 회원;
1
회원번호금액
512000
712000
39000
39000
2
회원금액
512000
712000
39000
39000
3
회원금액
712000
39000
512000
39000
4
회원금액
512000
712000
39000
정답 및 해설

집합 연산의 ORDER BY 는 맨 끝에 한 번만 쓰여 합쳐진 전체 결과를 정렬하고, 결과 열 이름과 정렬 키는 첫 SELECT 의 별칭 회원을 따른다.

UNION ALL 은 중복을 지우지 않아 (3, 9000) 두 행이 모두 남고, 금액 내림차순 뒤 회원 오름차순으로 5·7·3·3 순이 된다.

  • 온라인 행 뒤에 현장 행이 붙은 표는 정렬이 각 SELECT 에만 적용된다고 본 것이다.
  • 3행 표는 UNION 처럼 중복을 제거한 결과이다.
  • 열 이름이 회원번호인 표는 첫 SELECT 의 별칭을 무시한 것이다.
문제 32
두 SELECT 를 합친 결과에 중복 행이 전혀 없다고 보장될 때, UNION 과 UNION ALL 에 대한 설명으로 옳은 것은?
1UNION 은 NULL 이 포함된 행을 결과에서 뺀다
2UNION ALL 쪽 결과 행 수가 더 많다
3UNION ALL 은 중복 제거를 하지 않는다
4UNION 은 결과 정렬을 항상 보장한다
정답 및 해설

UNION ALL 은 중복 제거 단계를 거치지 않으므로, 중복이 없다고 보장되면 UNION 과 결과는 같으면서 정렬·비교 부담이 없다.

UNION 은 중복을 찾기 위해 정렬이나 해시 작업을 하지만, 그 결과의 순서를 보장하지는 않는다.

  • 중복이 없으면 두 연산자의 결과 행 수는 같다.
  • 순서가 필요하면 맨 끝에 ORDER BY 를 따로 써야 한다.
  • UNION 은 NULL 을 같은 값으로 보아 합칠 뿐 NULL 행을 빼지 않는다.
문제 33
다음 결과처럼 상영관별 소계는 있고 전체 총계는 없도록 집계하려 한다. ㉠에 들어갈 구문으로 옳은 것은?

[상영실적]

관이름장르관객수
1관액션120
1관드라마80
1관액션40
2관액션90
2관애니60
SELECT 관이름, 장르, SUM(관객수) AS 관객
  FROM 상영실적
 GROUP BY ( ㉠ )
 ORDER BY 관이름, 장르;
관이름장르관객
1관드라마80
1관액션160
1관(null)240
2관애니60
2관액션90
2관(null)150
1ROLLUP(관이름, 장르)
2GROUPING SETS(관이름, 장르)
3CUBE(관이름, 장르)
4관이름, ROLLUP(장르)
정답 및 해설

GROUP BY 관이름, ROLLUP(장르) 는 관이름을 늘 묶은 채 장르만 롤업하는 부분 ROLLUP 이라, 상세 행과 관별 소계만 만들고 총계는 만들지 않는다.

결과는 1관 드라마·액션과 소계 240, 2관 애니·액션과 소계 150 의 6행이며 소계 행의 장르가 NULL 이다.

  • ROLLUP(관이름, 장르) 는 마지막에 전체 총계 390 행이 더 붙는다.
  • GROUPING SETS(관이름, 장르) 는 관별·장르별 소계만 만들고 상세 행이 없다.
  • CUBE 는 장르별 소계와 총계까지 모두 만든다.
문제 34
다음 SQL 을 실행했을 때 결과 행 수는?

[예매집계]

요일관종류인원
토일반3
토IMAX2
일일반4
일(null)1
토일반2
SELECT 요일, 관종류, SUM(인원) AS 인원
  FROM 예매집계
 GROUP BY CUBE(요일, 관종류)
 ORDER BY 요일, 관종류;
17
210
312
49
정답 및 해설

CUBE(요일, 관종류) 는 데이터에 실제로 있는 조합별 행 4개, 요일별 소계 2개, 관종류별 소계 3개, 총계 1개를 만들어 10행이 된다.

조합은 (토,일반)·(토,IMAX)·(일,일반)·(일,NULL) 이고, 원래 NULL 인 관종류도 하나의 값이라 관종류별 소계가 일반·IMAX·NULL 3개다.

  • 7행은 관종류별 소계가 없는 ROLLUP 의 행 수이다.
  • 9행은 원래 NULL 인 관종류의 소계를 빼고 센 값이다.
  • 12행은 없는 조합까지 모두 만든다고 본 값이다.
문제 35
다음 SQL 을 실행했을 때 결과 행 수는?

[상영실적]

관이름장르관객수
1관액션50
1관(null)30
2관액션40
2관액션20
SELECT 관이름, 장르, SUM(관객수) AS 관객
  FROM 상영실적
 GROUP BY GROUPING SETS ((관이름, 장르), (관이름), ())
HAVING GROUPING(장르) = 1
 ORDER BY 관이름, 장르;
14
22
36
43
정답 및 해설

GROUPING(장르) 는 장르가 집계로 인해 NULL 이 된 행에서만 1 이므로, HAVING 조건은 1관·2관 소계와 총계 3행만 남긴다.

GROUPING SETS 가 만든 행은 상세 3, 관별 소계 2, 총계 1 의 6행이며, 1관의 장르 NULL 상세 행은 원래 데이터의 NULL 이라 GROUPING 값이 0 이다.

  • 2행은 총계 행의 GROUPING(장르) 도 1 이라는 점을 놓친 값이다.
  • 4행은 원래 NULL 인 장르 상세 행까지 포함한 값이다.
  • 6행은 HAVING 조건을 적용하기 전의 전체 행 수이다.
문제 36
Oracle 기준으로 다음 SQL 의 실행 결과로 옳은 것은?

[상영]

상영번호관이름관객수
11관30
21관50
31관20
42관40
52관(null)
62관60
SELECT 상영번호,
       RATIO_TO_REPORT(관객수)
         OVER (PARTITION BY 관이름) AS 비율
  FROM 상영
 ORDER BY 상영번호;
1
상영번호비율
10.3
20.8
31
40.4
5(null)
61
2
상영번호비율
10.3
20.5
30.2
40.4
5(null)
60.6
3
상영번호비율
10.3
20.5
30.2
40.4
50
60.6
4
상영번호비율
10.15
20.25
30.1
40.2
5(null)
60.3
정답 및 해설

RATIO_TO_REPORT 는 각 행 값을 파티션 합계로 나눈 비율로, 1관은 합 100 기준 0.3·0.5·0.2, 2관은 NULL 을 뺀 합 100 기준 0.4·0.6 이다.

관객수가 NULL 인 상영 5 는 나눌 값이 없어 비율도 NULL 이며, 합계 계산에서도 제외된다.

  • 0.15 부터 시작하는 표는 PARTITION BY 없이 전체 합 200 으로 나눈 결과이다.
  • 상영 5 가 0 인 표는 NULL 을 0 으로 바꿔 계산한 것이다.
  • 0.8·1 이 나오는 표는 누적 비율로 오해한 결과이다.
문제 37
다음 ㉠과 ㉡의 결과 행 수를 순서대로 나열한 것은?

[상영]

상영번호관이름관객수
1A관40
2A관20
3B관35
4B관(null)
5C관50
6A관30
7B관60

㉠

SELECT 관이름,
       COUNT(*) OVER (PARTITION BY 관이름) AS 횟수
  FROM 상영
 WHERE 관객수 >= 30;

㉡

SELECT DISTINCT 관이름,
       COUNT(*) OVER (PARTITION BY 관이름) AS 횟수
  FROM 상영
 WHERE 관객수 >= 30;
15, 5
27, 3
35, 3
43, 3
정답 및 해설

WHERE 가 먼저 관객수 30 이상인 1·3·5·6·7번 5행을 남기고, 윈도우 함수는 행을 줄이지 않으므로 ㉠은 5행이다.

㉡은 같은 관이름의 행이 같은 횟수 값을 가져 DISTINCT 로 A관 2·B관 2·C관 1 의 3행으로 줄어든다.

  • 7은 WHERE 이전의 전체 행 수로, NULL 과 20 인 행도 빠진다.
  • ㉡을 5행으로 본 것은 DISTINCT 가 중복 행을 합친다는 점을 놓친 것이다.
  • ㉠을 3행으로 본 것은 윈도우 함수를 GROUP BY 처럼 그룹당 1행으로 본 것이다.
문제 38
다음 결과를 얻기 위해 ㉠에 들어갈 함수로 옳은 것은? (DBMS 는 DESC 정렬에서 NULL 을 맨 앞에 둔다)

[상영]

상영번호관이름관객수
1A관50
2A관40
3A관40
4A관20
5B관30
6B관(null)
7B관30
SELECT 관이름, 상영번호, 관객수,
       ( ㉠ ) OVER (PARTITION BY 관이름
                    ORDER BY 관객수 DESC) AS 순위
  FROM 상영
 ORDER BY 관이름, 순위, 상영번호;
관이름상영번호관객수순위
A관1501
A관2402
A관3402
A관4203
B관6(null)1
B관5302
B관7302
1DENSE_RANK()
2ROW_NUMBER()
3RANK()
4PERCENT_RANK()
정답 및 해설

결과에서 A관은 1·2·2·3, B관은 1·2·2 로 동점은 같은 순위를 받고 다음 순위가 건너뛰지 않으므로 DENSE_RANK 이다.

B관은 DESC 정렬에서 NULL 이 맨 앞에 와 6번이 1위가 되고, 관객수 30 인 5·7번이 공동 2위가 된다.

  • RANK 는 동점 다음 순위를 건너뛰어 A관 20 이 4위가 된다.
  • ROW_NUMBER 는 동점에도 서로 다른 번호를 매겨 2·3 처럼 나뉜다.
  • PERCENT_RANK 는 0 과 1 사이의 비율 값을 돌려준다.
문제 39
다음 SQL 의 실행 결과로 옳은 것은?

[일별관객]

관이름상영일자관객수
A관2026-03-01100
A관2026-03-0280
A관2026-03-03120
B관2026-03-0150
B관2026-03-02(null)
B관2026-03-0370
SELECT 관이름, 상영일자,
       SUM(관객수) OVER (PARTITION BY 관이름
                         ORDER BY 상영일자
                         ROWS BETWEEN 1 PRECEDING
                                  AND CURRENT ROW) AS 이동합
  FROM 일별관객
 ORDER BY 관이름, 상영일자;
1
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-0150
B관2026-03-02(null)
B관2026-03-03(null)
2
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03300
B관2026-03-0150
B관2026-03-0250
B관2026-03-03120
3
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-0150
B관2026-03-0250
B관2026-03-0370
4
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-01170
B관2026-03-0250
B관2026-03-0370
정답 및 해설

ROWS BETWEEN 1 PRECEDING AND CURRENT ROW 는 파티션 안에서 직전 1행과 현재 행만 더하는 이동 합이라 A관은 100·180·200 이다.

B관 둘째 날은 50 과 NULL 중 NULL 을 건너뛰어 50, 셋째 날은 NULL 과 70 이라 70 이 되며 첫 행은 직전 행이 없어 자기 값이다.

  • 300·120 이 나온 표는 처음부터 누적한 합으로 본 결과이다.
  • B관에 NULL 이 이어지는 표는 SUM 이 NULL 을 전파한다고 본 것이다.
  • B관 첫 행이 170 인 표는 파티션을 무시하고 A관 마지막 행을 더한 것이다.
문제 40
다음 SQL 의 실행 결과로 옳은 것은?

[예매]

예매번호회원번호금액상태
1715000완료
2712000취소
379000완료
4820000취소
5811000완료
6811000완료
798000완료
SELECT 회원번호, 예매번호, 금액
  FROM (SELECT 회원번호, 예매번호, 금액, 상태,
               ROW_NUMBER() OVER (PARTITION BY 회원번호
                                  ORDER BY 금액 DESC, 예매번호) AS RN
          FROM 예매) T
 WHERE RN <= 2
   AND 상태 = '완료'
 ORDER BY 회원번호, 예매번호;
1
회원번호예매번호금액
7115000
2
회원번호예매번호금액
7115000
8511000
978000
3
회원번호예매번호금액
7115000
8511000
8611000
978000
4
회원번호예매번호금액
7115000
739000
8511000
8611000
978000
정답 및 해설

ROW_NUMBER 는 인라인 뷰 안에서 취소 건까지 포함해 회원별로 매겨지고, 상태 조건은 그 뒤 바깥 WHERE 에서 적용되므로 결과는 3행이다.

회원 7 은 1·2위가 예매 1·2 인데 2 가 취소라 1 만, 회원 8 은 1위 4 가 취소라 2위 5 만, 회원 9 는 7 만 남는다.

  • 5행 표는 취소 건을 먼저 거른 뒤 순번을 매긴 결과이다.
  • 회원 8 이 두 행인 표는 보조 정렬 예매번호를 무시하고 동점 11000 을 같은 순위로 본 결과이다.
  • 1행 표는 PARTITION BY 없이 전체 상위 2건만 본 결과이다.
문제 41
Oracle 에서 관객수 2~3위 영화를 구하려 한다. 의도한 두 행을 정확히 돌려주는 SQL 은? (관객수에 NULL·동점은 없다)

[영화]

제목관객수
파도900
정원700
추적800
별빛500
노을600
㉠ SELECT 제목, 관객수
     FROM (SELECT 제목, 관객수 FROM 영화
            ORDER BY 관객수 DESC)
    WHERE ROWNUM BETWEEN 2 AND 3;

㉡ SELECT 제목, 관객수
     FROM 영화
    WHERE ROWNUM <= 3 AND ROWNUM >= 2
    ORDER BY 관객수 DESC;

㉢ SELECT 제목, 관객수
     FROM (SELECT ROWNUM AS RN, A.*
             FROM (SELECT 제목, 관객수 FROM 영화
                    ORDER BY 관객수 DESC) A)
    WHERE RN BETWEEN 2 AND 3;

㉣ SELECT ROWNUM AS RN, 제목, 관객수
     FROM (SELECT 제목, 관객수 FROM 영화
            ORDER BY 관객수 DESC)
    WHERE RN BETWEEN 2 AND 3;
1㉠
2㉡
3㉣
4㉢
정답 및 해설

ROWNUM 은 조건을 통과한 행에 1부터 차례로 붙으므로 첫 행이 1 이 되지 못하면 다음 행도 1 이 되어 ROWNUM >= 2 류 조건은 0건이 된다.

㉢처럼 정렬한 인라인 뷰에 ROWNUM 을 별칭 RN 으로 고정한 뒤 바깥에서 RN 범위를 걸어야 추적·정원 두 행이 나온다.

  • ㉠은 ROWNUM BETWEEN 2 AND 3 이라 첫 행부터 탈락해 결과가 없다.
  • ㉡도 ROWNUM >= 2 를 만족하는 행이 없고 정렬도 번호 부여 뒤에 일어난다.
  • ㉣은 같은 쿼리 블록의 WHERE 에서 SELECT 별칭 RN 을 쓸 수 없어 오류가 난다.
문제 42
Oracle 에서 다음 계층형 질의에 대한 설명으로 옳은 것은?

[장르분류]

분류코드분류명상위코드
A영화(null)
A1액션A
A2드라마A
A11첩보A1
SELECT LEVEL, 분류명
  FROM 장르분류
 START WITH 분류코드 = 'A1'
 CONNECT BY PRIOR 분류코드 = 상위코드;
1시작 행 액션의 LEVEL 값은 0 이다
2첩보에서 영화로 올라가는 역방향이다
3시작 행의 상위인 영화도 함께 나온다
4위에서 아래로 내려가는 순방향 전개다
정답 및 해설

PRIOR 분류코드 = 상위코드 는 앞서 읽은 행의 분류코드를 상위코드로 가진 자식을 찾으므로 순방향(부모→자식) 전개다.

결과는 시작 행 액션(LEVEL 1)과 그 하위 첩보(LEVEL 2) 두 행이며, 시작 행 위쪽은 탐색하지 않는다.

  • LEVEL 은 시작 행을 1 로 세며 0 부터 시작하지 않는다.
  • 역방향은 PRIOR 상위코드 = 분류코드 처럼 PRIOR 를 자식 쪽 열에 둘 때이다.
  • 순방향이므로 시작 행의 상위인 영화는 결과에 나오지 않는다.
문제 43
Oracle 계층형 질의에서 더 이상 하위 분류가 없는 최하위 분류만 남기려 한다. ㉠에 알맞은 조건은?
SELECT 분류명
  FROM 장르분류
 WHERE ( ㉠ )
 START WITH 상위코드 IS NULL
 CONNECT BY PRIOR 분류코드 = 상위코드;
1LEVEL = 1
2ROWNUM = 1
3상위코드 IS NOT NULL
4CONNECT_BY_ISLEAF = 1
정답 및 해설

CONNECT_BY_ISLEAF 는 현재 행에 자식이 없으면 1, 있으면 0 을 돌려주므로 최하위 분류만 남기려면 = 1 조건을 쓴다.

계층형 질의의 WHERE 절은 계층 전개가 끝난 뒤 결과 행을 거르는 데 쓰인다.

  • LEVEL = 1 은 START WITH 로 시작한 최상위 분류만 남긴다.
  • 상위코드 IS NOT NULL 은 하위가 있는 중간 분류까지 함께 남긴다.
  • ROWNUM = 1 은 전개 결과의 첫 행인 최상위 분류 하나만 남긴다.
문제 44
다음 SQL 의 실행 결과로 옳은 것은? (요일은 가나다순으로 금·일·토 순서이다)

[예매]

예매번호제목요일인원
1파도토2
2파도일3
3파도일(null)
4정원토4
5정원금1
6추적금2
SELECT 제목,
       SUM(CASE WHEN 요일 = '토' THEN 인원 ELSE 0 END) AS 토,
       SUM(CASE WHEN 요일 = '일' THEN 인원 ELSE 0 END) AS 일
  FROM 예매
 GROUP BY 제목, 요일
 ORDER BY 제목, 요일;
1
제목토일
정원40
추적00
파도23
2
제목토일
정원00
정원40
파도03
파도20
3
제목토일
정원00
정원40
추적00
파도0(null)
파도20
4
제목토일
정원00
정원40
추적00
파도03
파도20
정답 및 해설

GROUP BY 에 피벗 대상인 요일까지 포함했으므로 (제목, 요일) 조합마다 한 행이 생겨 피벗되지 않고 5행이 된다.

정원은 금·토 두 행, 추적은 금 한 행(토·일 모두 0), 파도는 일 행에서 3, 토 행에서 2 가 나온다.

  • 제목당 한 행인 표는 GROUP BY 에 제목만 둔 올바른 피벗 결과이다.
  • 파도 일 칸이 NULL 인 표는 SUM 이 NULL 인원 행 때문에 NULL 이 된다고 본 것이다.
  • 추적 행이 없는 표는 토·일 예매가 없는 그룹이 사라진다고 본 것이다.
문제 45
Oracle 기준으로 다음 SQL 의 결과 행 수는?

[예매]

예매번호좌석
1H-07
2J 12
3K1,K2
4VIP3
5A_5
6B12
SELECT 예매번호, 좌석
  FROM 예매
 WHERE REGEXP_LIKE(좌석, '[[:space:][:punct:]]');
13
22
35
44
정답 및 해설

[[:space:][:punct:]] 는 공백 또는 구두점 한 글자와 일치하는 문자 목록이고 앵커가 없어 어디에 있든 하나만 있으면 참이므로 4행이다.

하이픈의 H-07, 공백의 J 12, 쉼표의 K1,K2, 밑줄의 A_5 가 일치하고 영숫자뿐인 VIP3·B12 는 빠진다.

  • 3행은 밑줄(_)을 구두점이 아니라고 본 값이다.
  • 2행은 공백 클래스만 또는 구두점 중 일부만 적용한 값이다.
  • 5행은 숫자가 섞인 VIP3 까지 일치한다고 본 값이다.
문제 46
다음 MERGE 문을 실행한 뒤 요금표의 행 수와, MERGE 가 갱신·삽입으로 처리한 행 수를 순서대로 나열한 것은? (단위: 행)

[요금표]

상영관요금
1관12000
2관13000
3관15000

[신규요금]

상영관요금
2관14000
3관15000
4관18000
MERGE INTO 요금표 T
USING 신규요금 S
   ON (T.상영관 = S.상영관)
 WHEN MATCHED THEN
   UPDATE SET T.요금 = S.요금
 WHEN NOT MATCHED THEN
   INSERT (상영관, 요금)
   VALUES (S.상영관, S.요금);
13, 2
24, 2
34, 3
46, 3
정답 및 해설

ON 조건에 맞는 2관·3관은 WHEN MATCHED 로 갱신되고 짝이 없는 4관은 WHEN NOT MATCHED 로 삽입되어 처리 행 수는 3, 요금표는 4행이 된다.

3관은 바뀌기 전후 요금이 같지만 조건에 맞았으므로 UPDATE 대상으로 처리되고, 원본에 없는 1관은 영향을 받지 않는다.

  • 처리 2행은 값이 같은 3관을 갱신 대상에서 뺀 값이다.
  • 요금표 3행은 4관이 삽입된다는 점을 놓친 값이다.
  • 요금표 6행은 원본 행을 모두 새로 붙인다고 본 값이다.
문제 47
Oracle 에서 다음 순서로 실행했을 때 ㉠ 시점 세션 B 의 SELECT 결과로 옳은 것은?
-- 예매번호 10 의 인원은 처음에 2 이다
[세션 A] UPDATE 예매 SET 인원 = 5 WHERE 예매번호 = 10;
[세션 B] SELECT 인원 FROM 예매 WHERE 예매번호 = 10;  -- ㉠
[세션 A] COMMIT;
1잠금 충돌로 오류가 난다
2변경 전 값 2 를 읽는다
3A 가 끝날 때까지 기다린다
4변경 후 값 5 를 읽는다
정답 및 해설

Oracle 은 읽기 일관성을 보장해 커밋되지 않은 다른 세션의 변경을 보여 주지 않으므로, 세션 B 는 변경 전 값 2 를 읽는다.

조회는 행 잠금을 기다리지 않고 언두(Undo) 정보로 변경 전 데이터를 만들어 돌려준다.

  • 미커밋 값 5 를 읽는 것은 Dirty Read 로 Oracle 에서는 일어나지 않는다.
  • 잠금은 같은 행을 수정하려는 DML 끼리만 기다리게 한다.
  • 단순 조회는 잠금 충돌 오류를 일으키지 않는다.
문제 48
다음 테이블에 상영번호 1 행이 이미 입력된 상태에서 ㉠~㉣을 차례로 실행할 때, 제약조건 위반으로 실패하는 것은?
CREATE TABLE 상영관 (관번호 INT PRIMARY KEY, 좌석수 INT);
-- 상영관: (1, 100), (2, 80)

CREATE TABLE 상영 (
  상영번호 INT PRIMARY KEY,
  관번호   INT REFERENCES 상영관(관번호),
  시작시각 CHAR(5) NOT NULL,
  요금     INT DEFAULT 10000
           CHECK (요금 BETWEEN 5000 AND 20000),
  UNIQUE (관번호, 시작시각)
);
-- 상영: (1, 1, '10:00', 12000)

㉠ INSERT INTO 상영 VALUES (2, NULL, '10:00', 9000);
㉡ INSERT INTO 상영 (상영번호, 관번호, 시작시각)
   VALUES (3, 2, '10:00');
㉢ INSERT INTO 상영 VALUES (4, 1, '13:00', 20000);
㉣ INSERT INTO 상영 VALUES (5, 1, '10:00', 8000);
1㉣
2㉡
3㉢
4㉠
정답 및 해설

㉣은 관번호 1·시작시각 '10:00' 조합이 기존 상영번호 1 행과 같아 복합 UNIQUE 제약 (관번호, 시작시각) 을 위반한다.

복합 UNIQUE 는 두 열 값이 모두 같을 때만 막으며, 한 열만 같거나 NULL 이 섞인 행은 허용한다.

  • ㉠은 FK 열이 NULL 이라 참조 검사를 하지 않고, UNIQUE 도 NULL 이 섞여 통과한다.
  • ㉡은 생략한 요금에 DEFAULT 10000 이 들어가 CHECK 를 만족한다.
  • ㉢의 20000 은 BETWEEN 의 끝값이라 포함되어 통과한다.
문제 49
Oracle 에서 다음 두 테이블에 데이터가 들어 있을 때, 실행하면 오류가 발생하는 문장은?
CREATE TABLE 영화 (
  영화번호 NUMBER PRIMARY KEY,
  제목     VARCHAR2(50)
);
CREATE TABLE 상영 (
  상영번호 NUMBER PRIMARY KEY,
  영화번호 NUMBER REFERENCES 영화(영화번호),
  상영일시 DATE
);
1TRUNCATE TABLE 상영;
2DROP TABLE 영화 PURGE;
3ALTER TABLE 상영 DROP COLUMN 상영일시;
4DROP TABLE 영화 CASCADE CONSTRAINTS;
정답 및 해설

영화 테이블의 기본키를 상영 테이블의 외래키가 참조하고 있으므로, 옵션 없이 부모인 영화를 DROP 하면 참조 제약 때문에 오류(ORA-02449)가 난다.

PURGE 는 휴지통을 거치지 않고 바로 지우라는 뜻일 뿐 참조 제약 검사는 그대로 받으며, 부모를 지우려면 CASCADE CONSTRAINTS 로 자식의 FK 제약을 함께 없애야 한다.

  • 상영 테이블의 일반 열인 상영일시는 제약과 무관해 DROP COLUMN 으로 지울 수 있다.
  • 자식 테이블을 TRUNCATE 하는 것은 참조 제약에 걸리지 않는다.
  • CASCADE CONSTRAINTS 를 붙이면 상영의 FK 제약이 삭제되며 영화가 지워진다.
문제 50
Oracle 에서 시스템 권한 CREATE TABLE 을 받은 사용자가 그 권한을 다른 사용자에게 다시 줄 수 있게 하려 한다. ㉠에 알맞은 것은?
GRANT CREATE TABLE TO 매니저 WITH ( ㉠ ) OPTION;
1GRANT
2ADMIN
3CHECK
4CASCADE
정답 및 해설

CREATE TABLE 같은 시스템 권한을 재부여할 수 있게 주려면 WITH ADMIN OPTION 을 붙인다.

SELECT ON 테이블 같은 오브젝트 권한을 재부여 가능하게 줄 때는 WITH GRANT OPTION 을 쓴다.

  • WITH GRANT OPTION 은 오브젝트 권한에만 쓰는 옵션이다.
  • WITH CHECK OPTION 은 뷰를 통한 입력·수정을 뷰 조건으로 제한한다.
  • WITH CASCADE OPTION 이라는 권한 부여 구문은 없다.
SQLD SQL 개발자 실전 모의고사모두CBT · moducbt.com
SQL 개발자 기출유형 모의고사 9회
총 50문항 · 객관식 · 정답·해설 포함
문제 1
데이터 모델링의 특징 중 "대상의 애매모호함을 제거하고 현상을 정확하게 기술하는 것"에 해당하는 것은?
1명확화
2정규화
3단순화
4추상화
정답 및 해설

대상의 애매모호함을 없애고 현상을 정확하게 기술하는 특징은 명확화이다.

모델링의 세 특징은 현실을 일정한 형식으로 표현하는 추상화, 제한된 표기법으로 쉽게 이해하게 하는 단순화, 그리고 명확화이다.

  • 추상화는 현실 세계를 일정한 형식에 맞추어 표현하는 것이다.
  • 단순화는 제한된 표기법과 언어로 쉽게 이해하도록 표현하는 것이다.
  • 정규화는 이상 현상을 없애는 설계 기법으로 세 특징에 들지 않는다.
문제 2
영화 예매 시스템의 ERD를 작성할 때, 엔터티 간 관계를 설정하고 관계명을 기술한 바로 다음에 수행하는 단계는?
1관계 참여도 기술
2관계 설정
3엔터티 배치
4관계 필수여부 기술
정답 및 해설

ERD 는 엔터티 도출·배치 → 관계 설정 → 관계명 기술 → 관계 참여도 기술 → 관계 필수여부 기술 순으로 작성한다.

관계명을 붙인 뒤에는 한 인스턴스가 상대 인스턴스 몇 개와 관계를 맺는지(1 또는 N)를 먼저 표시하고, 마지막에 반드시·선택 여부를 표시한다.

  • 엔터티 배치는 관계를 설정하기 전에 하는 단계다.
  • 관계 설정은 관계명 기술보다 앞선 단계다.
  • 관계 필수여부 기술은 참여도 기술 다음의 마지막 단계다.
문제 3
영화 예매 시스템의 속성 이름을 정하는 원칙으로 적절하지 않은 것은?
1현업에서 쓰는 업무 용어로 짓는다
2모델 전체에서 유일하게 짓는다
3뜻이 드러나게 서술식으로 짓는다
4약어 사용은 가급적 제한한다
정답 및 해설

속성 이름은 명사형의 간결한 업무 용어로 지어야 하며 서술식 속성명(예: 고객이 예매한 좌석의 번호)은 쓰지 않는다.

속성명은 해당 업무에서 쓰는 용어를 따르고, 약어를 줄이며, 데이터 모델 전체에서 유일하게 지어야 혼동이 없다.

  • 현업에서 실제로 쓰는 용어를 속성명으로 쓰는 것이 원칙이다.
  • 약어는 의미 전달을 어렵게 하므로 가급적 제한한다.
  • 같은 이름이 여러 엔터티에서 다른 뜻으로 쓰이지 않게 유일하게 짓는다.
문제 4
다음 ERD를 읽은 내용으로 옳은 것은?

그림

1모든 상영에는 예매가 반드시 존재한다
2예매 1건은 여러 상영과 관계를 맺는다
3상영이 편성되지 않은 영화도 있을 수 있다
4모든 회원은 예매를 1건 이상 한다
정답 및 해설

영화 쪽에서 상영 끝에 원(O)과 까마귀발이 있으므로 영화 하나는 상영을 0개 이상 가지며, 상영이 없는 영화도 존재할 수 있다.

관계선 끝의 원은 선택 참여, 바(|)는 필수 참여, 까마귀발은 N 을 뜻하며 상대편 끝의 기호를 읽는다.

  • 회원 쪽에서 본 예매 끝에 원이 있어 예매가 없는 회원도 있다.
  • 예매 쪽에서 본 상영 끝은 까마귀발 없이 바만 있어 예매 1건은 상영 1개에만 속한다.
  • 상영 쪽에서 본 예매 끝에 원이 있어 예매 없는 상영도 가능하다.
문제 5
다음 ERD에 대한 설명으로 옳은 것은? (회원의 이메일은 회원마다 다르고 NULL 이 없다)

그림

1상영순번은 상영의 외부식별자이다
2회원의 이메일은 보조식별자에 해당한다
3상영의 주식별자는 단일식별자이다
4예매의 영화코드는 내부식별자이다
정답 및 해설

이메일은 회원 인스턴스를 유일하게 구분할 수 있지만 주식별자로 쓰이지 않는 속성이므로 보조식별자에 해당한다.

상영은 영화에서 식별 관계로 받은 영화코드와 스스로 만든 상영순번을 합친 복합식별자이며, 관계로 받아 온 속성은 외부식별자이다.

  • 상영의 주식별자는 두 속성으로 이루어진 복합식별자다.
  • 예매의 영화코드는 상영과의 관계로 받은 외부식별자다.
  • 상영순번은 상영이 스스로 생성한 내부식별자다.
문제 6
다음 ERD의 [상영좌석] 엔터티에 함수 종속 (상영번호, 좌석번호) → 판매가, 상영번호 → 상영관번호, 상영관번호 → 상영관명 이 성립한다. [상영좌석]의 정규형으로 옳은 것은? (모든 속성은 원자값이다)

그림

1부분 종속이 남아 제1정규형이다
2제3정규형까지 모두 만족한다
3이행 종속만 남은 제2정규형이다
4제1정규형도 만족하지 못한다
정답 및 해설

상영관번호가 주식별자의 일부인 상영번호에만 종속되는 부분 함수 종속이 있으므로 [상영좌석]은 제1정규형이지만 제2정규형은 아니다.

속성이 모두 원자값이라 1NF 는 만족하며, 상영관번호·상영관명을 상영 쪽으로 분리해야 2NF 가 되고 상영관명의 이행 함수 종속은 그다음 단계에서 제거한다.

  • 모든 속성이 원자값이므로 1NF 는 만족한다.
  • 부분 함수 종속이 남아 있어 2NF 를 만족하지 못한다.
  • 2NF 도 아니므로 3NF 까지 만족할 수 없다.
문제 7
영화 장르를 [장르](장르코드, 장르명, 상위장르코드) 하나로 두고 상위장르코드가 같은 엔터티의 장르코드를 참조하게 모델링했다. 이 모델의 특징으로 옳은 것은?
1단계가 늘어도 엔터티 구조는 그대로다
2한 장르가 여러 상위 장르를 가진다
3상위 장르명은 별도 테이블로 조회한다
4최상위 장르의 상위장르코드는 필수다
정답 및 해설

자기참조(재귀) 관계로 만든 계층 모델은 대분류·중분류처럼 단계가 늘어나도 행만 추가하면 되므로 엔터티 구조를 바꾸지 않는다.

상위 장르명은 같은 테이블을 별칭으로 두 번 쓰는 셀프 조인으로 조회하며, 최상위 장르는 부모가 없어 상위장르코드가 NULL 이다.

  • 최상위 장르는 상위가 없으므로 상위장르코드가 NULL 이어야 한다.
  • 같은 테이블을 셀프 조인하면 되므로 다른 테이블이 없어도 된다.
  • 상위장르코드 속성이 하나뿐이라 부모는 최대 하나다.
문제 8
예매 1건은 예매좌석 여러 건으로 구성되며, 두 엔터티는 항상 함께 생성되고 예매 취소 시 함께 삭제된다. 이에 대한 설명으로 적절하지 않은 것은?
1취소 시 둘 다 지워야 일관성이 유지된다
2좌석 삭제는 별도 트랜잭션으로 나눈다
3두 엔터티는 서로 필수 관계로 표현한다
4일부만 반영되면 작업 전체를 취소한다
정답 및 해설

항상 함께 생성·삭제되는 예매와 예매좌석은 업무상 하나의 단위이므로 하나의 트랜잭션으로 묶어야 하며 좌석 삭제만 따로 떼면 안 된다.

별도 트랜잭션으로 나누면 예매만 지워지고 좌석이 남는 중간 상태가 생겨 원자성과 일관성이 깨진다.

  • 함께 존재해야 하므로 양쪽 모두 필수 참여 관계로 표현한다.
  • 취소할 때 예매와 좌석을 모두 지워야 데이터가 맞는다.
  • 한쪽만 처리되면 전체를 롤백해 작업 전 상태로 되돌린다.
문제 9
다음과 같이 [관람평]의 한줄평(가변 길이 문자형)에 값을 입력한 뒤 SELECT COUNT(*) FROM 관람평 WHERE 한줄평 IS NULL; 을 실행했다. Oracle 과 SQL Server 의 결과를 차례대로 나타낸 것은?

[관람평]

관람평번호입력한 한줄평 값
1'재밌음'
2'' (빈 문자열)
3NULL
4' ' (공백 1칸)
12, 2
23, 1
32, 1
41, 1
정답 및 해설

Oracle 은 빈 문자열을 NULL 로 저장하므로 관람평번호 2·3 이 IS NULL 에 해당해 2이고, SQL Server 는 빈 문자열을 길이 0 문자열로 따로 저장해 3만 세어 1이다.

공백 1칸은 길이 1인 문자 값이므로 두 DBMS 모두 NULL 이 아니다.

  • Oracle 에서 빈 문자열이 NULL 로 바뀌는 점을 놓치면 1로 본다.
  • 공백 1칸까지 NULL 로 보면 Oracle 이 3이 되지만 공백은 값이다.
  • SQL Server 는 빈 문자열을 NULL 로 바꾸지 않아 2가 아니다.
문제 10
영화 예매 모델에서 식별자를 대체 여부에 따라 본질식별자와 인조식별자로 나눌 때, 설명으로 옳은 것은?
1인조식별자는 부모에게서 상속받는다
2인조식별자는 반드시 복합키로 구성된다
3본질식별자는 순번으로만 부여한다
4업무에 의해 생긴 식별자는 본질식별자다
정답 및 해설

대체 여부 기준에서 업무 규칙에 의해 자연스럽게 만들어지는 식별자가 본질식별자이고, 원조식별자가 복잡해 인위적으로 만든 것이 인조식별자이다.

예를 들어 (회원번호, 상영번호, 좌석번호) 대신 시스템이 붙인 예매번호는 인조식별자이며 보통 단일 순번 속성으로 만든다.

  • 인조식별자는 대개 한 속성짜리 일련번호여서 복합키일 필요가 없다.
  • 본질식별자는 업무 값으로 정해지며 순번으로 부여하는 것은 인조식별자의 방식이다.
  • 부모에게서 상속받는지는 내부·외부식별자 구분 기준이다.
문제 11
[회원] 테이블에서 회원번호와 이메일은 각각 단독으로 모든 행을 유일하게 식별하며 최소성을 만족한다. 회원번호를 기본키로 정했을 때 이메일은 어떤 키에 해당하는가?
1대체키(Alternate Key)
2외래키(Foreign Key)
3복합키(Composite Key)
4인조키(Surrogate Key)
정답 및 해설

유일성과 최소성을 갖춘 후보키 중 기본키로 뽑히지 않은 나머지를 대체키(Alternate Key)라 하므로 이메일은 대체키이다.

후보키는 회원번호와 이메일 둘이고 그중 회원번호가 기본키가 되었으며, 대체키에는 보통 UNIQUE 제약을 걸어 유일성을 지킨다.

  • 외래키는 다른 테이블의 기본키를 참조하는 열이다.
  • 복합키는 두 개 이상의 열을 묶은 키인데 이메일은 단일 열이다.
  • 인조키는 업무와 무관하게 시스템이 만든 일련번호 같은 키이다.
문제 12
다음 SQL의 실행 결과로 옳은 것은?

[예매]

예매번호인원단가할인
12120001000
2112000(null)
3(null)90000
4390003000
SELECT 예매번호,
       인원 * 단가 AS 정가합,
       인원 * 단가 - 할인 AS 결제액
  FROM 예매
 ORDER BY 예매번호;
1
예매번호정가합결제액
12400023000
212000(null)
3(null)(null)
42700024000
2
예매번호정가합결제액
12400023000
21200012000
3(null)(null)
42700024000
3
예매번호정가합결제액
12400023000
212000(null)
300
42700024000
4
예매번호정가합결제액
12400022000
212000(null)
3(null)(null)
42700018000
정답 및 해설

산술식에 NULL 이 하나라도 있으면 결과는 NULL이므로 할인이 NULL 인 예매번호 2 는 결제액이, 인원이 NULL 인 3 은 정가합과 결제액이 모두 NULL 이다.

곱셈이 뺄셈보다 먼저 계산되어 1은 24000-1000=23000, 4는 27000-3000=24000 이다.

  • NULL 을 0으로 보고 빼면 2의 결제액이 12000 이 되지만 실제는 NULL 이다.
  • NULL 과의 곱도 0이 아니라 NULL 이므로 3을 0으로 보면 틀린다.
  • 단가-할인을 먼저 계산하면 22000·18000 이 나오지만 우선순위와 다르다.
문제 13
Oracle 기준으로 SELECT 문의 FROM 절과 별칭에 대한 설명으로 옳은 것은?
1WHERE 절에서 열 별칭을 참조한다
2SELECT * 는 열 순서를 임의로 바꾼다
3별칭을 준 뒤에도 테이블명으로 한정한다
4테이블 별칭 앞에는 AS 를 쓸 수 없다
정답 및 해설

Oracle 은 열 별칭에는 AS 를 허용하지만 테이블 별칭 앞에는 AS 를 쓸 수 없어 FROM 상영 S 처럼 바로 붙여 쓴다.

또 SELECT 절의 열 별칭은 WHERE 절보다 늦게 정해지므로 WHERE 에서는 쓸 수 없고 ORDER BY 에서만 쓸 수 있다.

  • WHERE 절은 SELECT 보다 먼저 처리되어 열 별칭을 참조하면 오류가 난다.
  • 테이블에 별칭을 주면 열은 그 별칭으로 한정해야 하고 원래 테이블명을 쓰면 오류가 난다.
  • SELECT * 는 테이블에 정의된 열 순서대로 모든 열을 돌려준다.
문제 14
Oracle 기준으로, 상영코드(지점-관번호-시각)에서 관번호 두 자리만 다음 결과처럼 꺼내려 한다. ( ㉠ )에 들어갈 식으로 옳은 것은?

[상영]

상영번호상영코드
1강남-07-1930
2신촌역-03-2100
3홍대-12-1015
4일산호수-05-0900
SELECT 상영번호, ( ㉠ ) AS 관번호
  FROM 상영
 ORDER BY 상영번호;

[원하는 결과]

상영번호관번호
107
203
312
405
1SUBSTR(상영코드, INSTR(상영코드, '-') + 1, 2)
2SUBSTR(상영코드, 4, 2)
3LTRIM(SUBSTR(상영코드, 3, 3), '-')
4SUBSTR(상영코드, LENGTH(상영코드) - 6)
정답 및 해설

INSTR(상영코드, '-') 가 첫 하이픈 위치를 돌려주므로 그 다음 위치부터 2글자를 자르면 지점명 길이와 관계없이 07·03·12·05 가 나온다.

지점명이 2~4글자로 달라 관번호의 시작 위치가 행마다 다르므로 고정 위치가 아닌 구분자 위치를 기준으로 잘라야 한다.

  • 길이를 생략한 SUBSTR 은 끝까지 잘라 07-1930 처럼 시각까지 나온다.
  • 3번째부터 3글자는 지점명이 2글자일 때만 맞고 신촌역은 '역-0' 이 된다.
  • 4번째부터 2글자도 지점명이 2글자인 행에서만 관번호가 나온다.
문제 15
다음 SQL의 실행 결과로 옳은 것은?

[회원]

회원번호휴대폰이메일포인트
1010-11kim@a.kr3500
2(null)lee@a.kr1200
3(null)(null)(null)
4010-44(null)800
SELECT 회원번호,
       COALESCE(휴대폰, 이메일, '미등록') AS 연락처,
       CASE WHEN 포인트 >= 1000 THEN 'VIP'
            WHEN 포인트 >= 3000 THEN 'VVIP'
            ELSE '일반' END AS 등급
  FROM 회원
 ORDER BY 회원번호;
1
회원번호연락처등급
1010-11VIP
2미등록VIP
3미등록일반
4010-44일반
2
회원번호연락처등급
1010-11VVIP
2lee@a.krVIP
3미등록일반
4010-44일반
3
회원번호연락처등급
1010-11VIP
2lee@a.krVIP
3미등록일반
4010-44일반
4
회원번호연락처등급
1010-11VIP
2lee@a.krVIP
3미등록(null)
4010-44일반
정답 및 해설

COALESCE 는 왼쪽부터 처음 만난 NOT NULL 값을 돌려주므로 2는 이메일, 3은 '미등록'이 되고, 검색 CASE 는 처음 참인 WHEN 에서 멈춰 3500 포인트인 1도 VIP 가 된다.

포인트가 NULL 인 3은 두 비교가 모두 UNKNOWN 이라 ELSE 의 '일반'을 받는다.

  • 더 높은 조건을 찾아 VVIP 를 주지 않으며, 앞선 WHEN 이 먼저 참이 된다.
  • ELSE 가 있으므로 NULL 비교 행도 NULL 이 아니라 '일반'이다.
  • 휴대폰이 NULL 이면 다음 인수인 이메일을 보므로 2는 '미등록'이 아니다.
문제 16
Oracle 기준으로, 가입 후 한 달 쿠폰의 만료일을 구하는 다음 SQL의 실행 결과로 옳은 것은?

[회원]

회원번호가입일
12026-01-31
22026-02-28
32026-03-15
42026-04-30
52026-05-30
SELECT 회원번호,
       TO_CHAR(ADD_MONTHS(가입일, 1), 'YYYY-MM-DD') AS 만료일
  FROM 회원
 ORDER BY 회원번호;
1
회원번호만료일
12026-03-02
22026-03-30
32026-04-14
42026-05-30
52026-06-29
2
회원번호만료일
12026-02-28
22026-03-31
32026-04-15
42026-05-31
52026-06-30
3
회원번호만료일
12026-02-28
22026-03-28
32026-04-15
42026-05-30
52026-06-30
4
회원번호만료일
12026-03-03
22026-03-31
32026-04-15
42026-05-31
52026-06-30
정답 및 해설

ADD_MONTHS 는 입력일이 그 달의 말일이면 결과도 결과 월의 말일로 맞추므로 2월 28일은 3월 31일, 4월 30일은 5월 31일이 된다.

1월 31일처럼 결과 월에 같은 날이 없으면 그 달 말일인 2월 28일이 되고, 말일이 아닌 3월 15일·5월 30일은 날짜만 그대로 옮겨진다.

  • 말일 규칙을 빼고 같은 날짜로만 옮기면 3월 28일·5월 30일이 나온다.
  • 존재하지 않는 2월 31일을 넘겨 3월로 보내지 않고 2월 말일에서 멈춘다.
  • 한 달 더하기는 30일 더하기가 아니므로 3월 2일 같은 값이 나오지 않는다.
문제 17
다음 SQL의 실행 결과 행 수는?

[영화]

영화번호제목관람등급
1파도12
2여름밤19
3유리새(null)
4서울역15
5모래성(null)
6달무리전체
SELECT 영화번호, 제목
  FROM 영화
 WHERE NOT (관람등급 = '19')
    OR 관람등급 = NULL
 ORDER BY 영화번호;
16
22
33
45
정답 및 해설

관람등급이 NULL 인 행은 관람등급 = '19' 가 UNKNOWN 이고 NOT 을 붙여도 UNKNOWN 이며, = NULL 비교 역시 항상 UNKNOWN 이라 제외된다.

결국 등급이 있고 19가 아닌 파도·서울역·달무리 3행만 남으며, NULL 행을 찾으려면 IS NULL 을 써야 한다.

  • = NULL 이 NULL 행을 찾는다고 보면 5행이 되지만 결과는 없다.
  • NULL 비교를 참으로 보아 모든 행이 나온다고 보면 6행이다.
  • 문자 '전체'도 '19'와 다른 값이므로 빠지지 않아 2행이 아니다.
문제 18
다음 [조건] 중 나머지 셋과 결과가 다른 것은? (장르·평점에 NULL 은 없다)

[조건]

㉠ WHERE NOT 장르 = '액션' AND 평점 >= 4
㉡ WHERE 장르 <> '액션' AND 평점 >= 4
㉢ WHERE 평점 >= 4 AND NOT 장르 = '액션'
㉣ WHERE NOT (장르 = '액션' AND 평점 >= 4)
1㉠
2㉣
3㉡
4㉢
정답 및 해설

논리 연산자는 NOT → AND → OR 순으로 결합하므로 괄호 없는 NOT 은 바로 뒤의 장르 = '액션' 하나만 부정한다.

그래서 세 조건은 모두 '액션이 아니면서 평점 4 이상'이지만, ㉣은 괄호 전체를 부정해 액션이 아니거나 평점 4 미만인 행을 고른다.

  • ㉠은 NOT 이 장르 비교에만 걸려 액션 외 장르 중 평점 4 이상을 고른다.
  • ㉡은 <> 로 같은 조건을 직접 쓴 것이다.
  • ㉢은 AND 양쪽의 순서만 바꾼 것으로 결과가 같다.
문제 19
다음 [관람평]에서 SELECT ( 식 ) AS 평균 FROM 관람평; 의 식 자리에 넣었을 때 결과가 나머지 셋과 다른 것은?

[관람평]

관람평번호영화번호평점
114
21(null)
325
423
53(null)

[식]

㉠ AVG(평점)
㉡ SUM(평점) / COUNT(평점)
㉢ AVG(평점 + 0)
㉣ AVG(COALESCE(평점, 0))
1㉡
2㉣
3㉠
4㉢
정답 및 해설

COALESCE(평점, 0) 은 NULL 을 0으로 바꿔 다섯 행 모두를 평균에 넣으므로 12/5=2.4 가 되어 나머지와 다르다.

집계 함수는 NULL 을 제외하고 계산하므로 AVG(평점)과 SUM/COUNT(평점)은 12/3=4 이고, 평점 + 0 도 NULL 행은 NULL 그대로라 4이다.

  • ㉠의 AVG 는 NULL 두 행을 빼고 세 값의 평균 4를 낸다.
  • ㉡의 COUNT(평점)도 NULL 을 세지 않아 12/3=4 이다.
  • ㉢의 평점 + 0 은 NULL 이 그대로 NULL 이라 ㉠과 같은 4이다.
문제 20
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호상영관관객수
1IMAX120
2IMAX(null)
32D90
4IMAX200
5(null)150
62D(null)
SELECT COUNT(*) AS 회차,
       COUNT(관객수) AS 집계,
       SUM(관객수) AS 합계
  FROM 상영
 WHERE 상영관 = 'IMAX'
HAVING SUM(관객수) > 300;
1
회차집계합계
32320
2
회차집계합계
33320
3
회차집계합계
4
회차집계합계
22320
정답 및 해설

WHERE 로 IMAX 세 행(120·NULL·200)만 남고, GROUP BY 가 없으므로 이 세 행 전체가 하나의 그룹이 되어 HAVING 합계 320 > 300 이 참이라 1행이 나온다.

COUNT(*)는 NULL 행도 세어 3, COUNT(관객수)는 NULL 을 빼 2이며 SELECT 에는 집계 함수만 있어 그룹 키 없이도 실행된다.

  • COUNT(관객수)는 NULL 을 세지 않으므로 3이 아니다.
  • COUNT(*)는 관객수가 NULL 인 행도 포함하므로 2가 아니다.
  • HAVING 은 GROUP BY 없이도 전체를 한 그룹으로 보고 평가하므로 0행이 아니다.
문제 21
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호영화번호관객수
1M180
2M140
3M160
4M230
5M290
6M3(null)
7M370
8M355
9M4100
SELECT 영화번호, COUNT(*) AS 회차, SUM(관객수) AS 관객
  FROM 상영
 WHERE 관객수 >= 50
 GROUP BY 영화번호
HAVING COUNT(*) >= 2
 ORDER BY 영화번호;
1
영화번호회차관객
M12140
M33125
2
영화번호회차관객
M12140
M2190
M32125
3
영화번호회차관객
M13180
M22120
M33125
4
영화번호회차관객
M12140
M32125
정답 및 해설

WHERE 가 그룹화보다 먼저 실행되어 관객수 50 미만과 NULL 행(2·4·6)이 빠진 뒤 HAVING 이 남은 행 수를 센다.

그 결과 M1(80·60)과 M3(70·55)만 2회가 되어 남고, M2·M4 는 한 행만 남아 HAVING 에서 탈락한다.

  • M2 는 WHERE 뒤 90 한 행만 남아 COUNT 가 1이므로 결과에 없다.
  • NULL 은 50 이상 비교가 UNKNOWN 이라 M3 의 회차는 3이 아니다.
  • WHERE 를 무시하고 모든 행을 센 결과는 실행 순서와 맞지 않는다.
문제 22
다음 SQL의 실행 결과로 옳은 것은?

[영화]

영화번호제목상영시간개봉일
1파도1282026-03-04
2서울역1152026-03-11
3모래성1022026-03-11
4여름밤952026-02-25
5유리새1152026-03-04
SELECT 제목, 상영시간 AS 러닝
  FROM 영화
 ORDER BY 개봉일 DESC, 2;
1
제목러닝
모래성102
서울역115
유리새115
파도128
여름밤95
2
제목러닝
여름밤95
유리새115
파도128
모래성102
서울역115
3
제목러닝
서울역115
모래성102
파도128
유리새115
여름밤95
4
제목러닝
여름밤95
모래성102
서울역115
유리새115
파도128
정답 및 해설

개봉일은 SELECT 목록에 없어도 정렬 키로 쓸 수 있으며, 최신 개봉일(3월 11일)부터 내림차순으로 놓인다.

DESC 는 개봉일에만 적용되고 열 번호 2인 러닝은 기본 ASC 라 같은 날 개봉한 모래성(102)·서울역(115), 유리새(115)·파도(128) 순이 된다.

  • 러닝까지 내림차순으로 보면 서울역이 모래성보다 앞서지만 둘째 키는 ASC 이다.
  • 개봉일을 오름차순으로 보면 여름밤이 먼저 오지만 DESC 가 지정되어 있다.
  • 러닝만으로 정렬한 결과로, 첫째 키인 개봉일을 무시했다.
문제 23
다음 SQL의 실행 결과로 옳은 것은?

[상영]

상영번호시작시
19
210
315
422
523
6(null)

[요금구간]

구간명시작끝
조조710
일반1022
심야2327
SELECT S.상영번호, G.구간명
  FROM 상영 S, 요금구간 G
 WHERE S.시작시 >= G.시작
   AND S.시작시 < G.끝
 ORDER BY S.상영번호;
1
상영번호구간명
1조조
3일반
5심야
2
상영번호구간명
1조조
2조조
2일반
3일반
5심야
3
상영번호구간명
1조조
2일반
3일반
5심야
4
상영번호구간명
1조조
2일반
3일반
4일반
5심야
정답 및 해설

조건이 시작 이상·끝 미만이라 10시는 조조(끝 10)가 아닌 일반에만, 22시는 일반(끝 22)에도 심야(시작 23)에도 들지 않아 빠진다.

시작시가 NULL 인 상영번호 6은 비교가 UNKNOWN 이라 NON-EQUI 조인 결과에 없고, 최종 4행이 남는다.

  • 끝값까지 포함해야 10시가 조조와 일반 두 곳에 매칭되지만 < 는 끝을 뺀다.
  • 10시는 일반의 시작값과 같아 >= 조건을 만족하므로 빠지지 않는다.
  • 22시는 일반의 끝값과 같아 < 조건에서 탈락한다.
문제 24
[영화] 5행 중 관람등급이 '전체'인 행이 2행, [상영관] 3행, [시간대] 4행일 때 다음 SQL의 결과 행 수는?
SELECT *
  FROM 영화 M, 상영관 H, 시간대 T
 WHERE M.관람등급 = '전체';
160행
224행
312행
49행
정답 및 해설

세 테이블 사이에 조인 조건이 하나도 없으므로 카티션 곱이 만들어지고, WHERE 는 영화 쪽 행만 2행으로 줄인다.

따라서 결과는 2 × 3 × 4 = 24행이며 조건이 없는 상영관·시간대는 모든 행이 곱해진다.

  • 필터를 무시하고 5×3×4 로 곱하면 60행이 된다.
  • 행 수를 더한 2+3+4 는 조인 결과와 무관하다.
  • 영화 조건만 남고 영화 행을 곱에서 빼면 12행이 되지만 2행이 곱해진다.
문제 25
다음 [원하는 결과]를 얻기 위해 ( ㉠ )에 들어갈 조인으로 옳은 것은?

[영화]

영화번호제목
1파도
2여름밤
3유리새

[상영]

상영번호영화번호상영관
1111관
1213관
1322관
1491관
SELECT M.제목, S.상영관
  FROM 상영 S ( ㉠ ) 영화 M
    ON S.영화번호 = M.영화번호
 ORDER BY M.영화번호, S.상영번호;

[원하는 결과]

제목상영관
파도1관
파도3관
여름밤2관
유리새(null)
1LEFT OUTER JOIN
2FULL OUTER JOIN
3RIGHT OUTER JOIN
4INNER JOIN
정답 및 해설

원하는 결과에는 상영이 없는 유리새가 상영관 NULL 로 남고 영화번호 9 인 상영은 없으므로, 오른쪽에 쓴 영화를 모두 보존하는 RIGHT OUTER JOIN 이다.

FROM 에 상영을 먼저 썼으므로 상영이 왼쪽, 영화가 오른쪽이며 보존되는 쪽은 조인 키워드의 방향으로 정해진다.

  • INNER JOIN 은 상영이 없는 유리새를 결과에서 뺀다.
  • LEFT OUTER JOIN 은 상영 쪽을 보존해 영화가 없는 상영 14 가 제목 NULL 로 나온다.
  • FULL OUTER JOIN 은 유리새와 상영 14 를 모두 남겨 한 행이 더 생긴다.
문제 26
다음 SQL 의 실행 결과로 옳은 것은?

[영화]

영화번호제목장르
1파도액션
2정원드라마
3추적액션
4별빛애니

[상영]

상영번호영화번호관번호
10111
10212
10321
10443
SELECT M.제목, S.상영번호
  FROM 영화 M
  LEFT OUTER JOIN 상영 S
    ON M.영화번호 = S.영화번호
   AND M.장르 = '액션'
 ORDER BY M.영화번호, S.상영번호;
1
제목상영번호
파도101
파도102
정원(null)
추적(null)
별빛(null)
2
제목상영번호
파도101
파도102
추적(null)
3
제목상영번호
파도101
파도102
정원103
추적(null)
별빛104
4
제목상영번호
파도101
파도102
정답 및 해설

LEFT OUTER JOIN 의 ON 절 조건은 결합 여부만 정하므로, 왼쪽 테이블에 건 M.장르 = '액션' 도 영화 행을 거르지 않고 매칭만 막는다.

액션인 파도는 101·102 와 결합하고, 상영이 없는 추적과 액션이 아닌 정원·별빛은 상영번호가 NULL 인 한 행씩 남아 5행이 된다.

  • 3행 표는 장르 조건을 WHERE 절에 둔 결과로, 정원·별빛이 빠진다.
  • 정원 103·별빛 104 가 붙은 표는 장르 조건을 무시한 결과이다.
  • 2행 표는 INNER JOIN 처럼 결합된 행만 남긴 결과이다.
문제 27
다음 SQL 의 실행 결과로 옳은 것은?

[상영]

상영번호관번호시작시각
201110:00
202213:00
203(null)15:00
204118:00

[상영관]

관번호관이름
11관
22관
3IMAX
SELECT *
  FROM 상영 JOIN 상영관 USING (관번호)
 ORDER BY 상영번호;
1
상영번호관번호시작시각관이름
201110:001관
202213:002관
204118:001관
2
관번호상영번호시작시각관이름
120110:001관
220213:002관
(null)20315:00(null)
120418:001관
3
상영번호관번호시작시각관번호관이름
201110:0011관
202213:0022관
204118:0011관
4
관번호상영번호시작시각관이름
120110:001관
220213:002관
120418:001관
정답 및 해설

USING 으로 조인하면 공통 열 관번호가 결과에 한 번만, 맨 앞에 나오고 나머지 열은 상영·상영관 순으로 이어진다.

INNER 조인이므로 관번호가 NULL 인 203 은 짝이 없어 빠지고, 상영이 없는 IMAX 도 나오지 않아 3행이다.

  • 관번호가 상영 테이블 순서대로 두 번째에 오는 표는 공통 열의 위치를 잘못 본 것이다.
  • 203 이 NULL 로 남은 표는 OUTER JOIN 결과이다.
  • 관번호가 두 번 나오는 표는 ON 절 조인의 SELECT * 결과이다.
문제 28
예매 금액을 서브쿼리 결과와 비교하는 다중행 연산자에 대한 설명으로 적절하지 않은 것은?
SELECT 예매번호, 금액
  FROM 예매
 WHERE 금액 연산자 (SELECT 금액
                     FROM 예매
                    WHERE 회원번호 = 7);
1< ANY 는 최솟값보다 작은 행만 찾는다
2> ALL 은 최댓값보다 큰 행만 찾는다
3= ANY 는 IN 과 같은 결과를 낸다
4= 에 여러 행이 오면 오류가 난다
정답 및 해설

< ANY 는 서브쿼리 결과 중 어느 하나보다만 작으면 참이므로, 실제로는 결과의 최댓값보다 작은 행을 모두 찾는다.

최솟값 미만인 행만 남기려면 전체 값과 비교하는 < ALL 을 써야 한다.

  • = ANY 는 목록 중 하나와 같으면 참이라 IN 과 같은 결과를 낸다.
  • > ALL 은 모든 값보다 커야 하므로 최댓값보다 큰 행만 남는다.
  • 단일행 연산자 = 에 여러 행이 반환되면 실행 오류가 발생한다.
문제 29
다음 SQL 의 실행 결과로 옳은 것은?

[예매]

예매번호상영번호인원
11012
21014
31014
41023
5102(null)
61031
71032
SELECT A.예매번호, A.상영번호, A.인원
  FROM 예매 A
 WHERE A.인원 = (SELECT MAX(B.인원)
                   FROM 예매 B
                  WHERE B.상영번호 = A.상영번호)
 ORDER BY A.예매번호;
1
예매번호상영번호인원
21014
41023
71032
2
예매번호상영번호인원
21014
31014
41023
5102(null)
71032
3
예매번호상영번호인원
21014
31014
4
예매번호상영번호인원
21014
31014
41023
71032
정답 및 해설

연관 서브쿼리는 바깥 행의 상영번호마다 MAX(인원) 을 다시 구하므로, 상영별 최댓값과 같은 행이 동점까지 모두 남아 4행이다.

상영 101 은 인원 4 인 예매 2·3, 102 는 3 인 예매 4, 103 은 2 인 예매 7 이 남고, 인원이 NULL 인 예매 5 는 비교 결과가 UNKNOWN 이라 빠진다.

  • 예매 2·3 만 남은 표는 상관 조건 없이 전체 최댓값과 비교한 결과이다.
  • 상영별 한 행만 남긴 표는 동점 행을 하나로 줄인 것이다.
  • 예매 5 가 포함된 표는 NULL 과의 비교를 참으로 본 것이다.
문제 30
영화별 예매 건수를 다음 결과처럼 구하려 한다. ㉠에 들어갈 조건으로 옳은 것은?

[영화]

영화번호제목
1파도
2정원
3추적

[예매]

예매번호영화번호
111
121
133
141
15(null)
SELECT M.제목,
       (SELECT COUNT(*)
          FROM 예매 R
         WHERE ( ㉠ )) AS 건수
  FROM 영화 M
 ORDER BY M.영화번호;
제목건수
파도3
정원0
추적1
1M.영화번호 IN (1, 3)
2영화번호 IS NOT NULL
3R.영화번호 = M.영화번호
41 = 1
정답 및 해설

바깥 영화 행마다 같은 영화의 예매만 세려면 스칼라 서브쿼리의 조건이 바깥 별칭 M 을 가리키는 상관 조건 R.영화번호 = M.영화번호 여야 한다.

예매가 없는 정원은 COUNT(*) 가 0 을 돌려 0 으로 나오고, 영화번호가 NULL 인 15번은 어느 영화에도 세지지 않는다.

  • 한정자 없는 영화번호는 가장 가까운 R 의 열로 해석되어 NULL 이 아닌 예매 4건이 모든 영화에 세어진다.
  • 1 = 1 은 상관 조건이 없어 모든 영화에 예매 5건이 그대로 세어진다.
  • IN (1, 3) 은 파도·추적에 5, 정원에 0 을 주어 예매 건수와 다르다.
문제 31
다음 SQL 의 실행 결과로 옳은 것은?

[온라인예매]

회원번호금액
712000
39000

[현장예매]

회원번호금액
512000
39000
SELECT 회원번호 AS 회원, 금액 FROM 온라인예매
UNION ALL
SELECT 회원번호, 금액 FROM 현장예매
 ORDER BY 금액 DESC, 회원;
1
회원번호금액
512000
712000
39000
39000
2
회원금액
512000
712000
39000
39000
3
회원금액
712000
39000
512000
39000
4
회원금액
512000
712000
39000
정답 및 해설

집합 연산의 ORDER BY 는 맨 끝에 한 번만 쓰여 합쳐진 전체 결과를 정렬하고, 결과 열 이름과 정렬 키는 첫 SELECT 의 별칭 회원을 따른다.

UNION ALL 은 중복을 지우지 않아 (3, 9000) 두 행이 모두 남고, 금액 내림차순 뒤 회원 오름차순으로 5·7·3·3 순이 된다.

  • 온라인 행 뒤에 현장 행이 붙은 표는 정렬이 각 SELECT 에만 적용된다고 본 것이다.
  • 3행 표는 UNION 처럼 중복을 제거한 결과이다.
  • 열 이름이 회원번호인 표는 첫 SELECT 의 별칭을 무시한 것이다.
문제 32
두 SELECT 를 합친 결과에 중복 행이 전혀 없다고 보장될 때, UNION 과 UNION ALL 에 대한 설명으로 옳은 것은?
1UNION 은 NULL 이 포함된 행을 결과에서 뺀다
2UNION ALL 쪽 결과 행 수가 더 많다
3UNION ALL 은 중복 제거를 하지 않는다
4UNION 은 결과 정렬을 항상 보장한다
정답 및 해설

UNION ALL 은 중복 제거 단계를 거치지 않으므로, 중복이 없다고 보장되면 UNION 과 결과는 같으면서 정렬·비교 부담이 없다.

UNION 은 중복을 찾기 위해 정렬이나 해시 작업을 하지만, 그 결과의 순서를 보장하지는 않는다.

  • 중복이 없으면 두 연산자의 결과 행 수는 같다.
  • 순서가 필요하면 맨 끝에 ORDER BY 를 따로 써야 한다.
  • UNION 은 NULL 을 같은 값으로 보아 합칠 뿐 NULL 행을 빼지 않는다.
문제 33
다음 결과처럼 상영관별 소계는 있고 전체 총계는 없도록 집계하려 한다. ㉠에 들어갈 구문으로 옳은 것은?

[상영실적]

관이름장르관객수
1관액션120
1관드라마80
1관액션40
2관액션90
2관애니60
SELECT 관이름, 장르, SUM(관객수) AS 관객
  FROM 상영실적
 GROUP BY ( ㉠ )
 ORDER BY 관이름, 장르;
관이름장르관객
1관드라마80
1관액션160
1관(null)240
2관애니60
2관액션90
2관(null)150
1ROLLUP(관이름, 장르)
2GROUPING SETS(관이름, 장르)
3CUBE(관이름, 장르)
4관이름, ROLLUP(장르)
정답 및 해설

GROUP BY 관이름, ROLLUP(장르) 는 관이름을 늘 묶은 채 장르만 롤업하는 부분 ROLLUP 이라, 상세 행과 관별 소계만 만들고 총계는 만들지 않는다.

결과는 1관 드라마·액션과 소계 240, 2관 애니·액션과 소계 150 의 6행이며 소계 행의 장르가 NULL 이다.

  • ROLLUP(관이름, 장르) 는 마지막에 전체 총계 390 행이 더 붙는다.
  • GROUPING SETS(관이름, 장르) 는 관별·장르별 소계만 만들고 상세 행이 없다.
  • CUBE 는 장르별 소계와 총계까지 모두 만든다.
문제 34
다음 SQL 을 실행했을 때 결과 행 수는?

[예매집계]

요일관종류인원
토일반3
토IMAX2
일일반4
일(null)1
토일반2
SELECT 요일, 관종류, SUM(인원) AS 인원
  FROM 예매집계
 GROUP BY CUBE(요일, 관종류)
 ORDER BY 요일, 관종류;
17
210
312
49
정답 및 해설

CUBE(요일, 관종류) 는 데이터에 실제로 있는 조합별 행 4개, 요일별 소계 2개, 관종류별 소계 3개, 총계 1개를 만들어 10행이 된다.

조합은 (토,일반)·(토,IMAX)·(일,일반)·(일,NULL) 이고, 원래 NULL 인 관종류도 하나의 값이라 관종류별 소계가 일반·IMAX·NULL 3개다.

  • 7행은 관종류별 소계가 없는 ROLLUP 의 행 수이다.
  • 9행은 원래 NULL 인 관종류의 소계를 빼고 센 값이다.
  • 12행은 없는 조합까지 모두 만든다고 본 값이다.
문제 35
다음 SQL 을 실행했을 때 결과 행 수는?

[상영실적]

관이름장르관객수
1관액션50
1관(null)30
2관액션40
2관액션20
SELECT 관이름, 장르, SUM(관객수) AS 관객
  FROM 상영실적
 GROUP BY GROUPING SETS ((관이름, 장르), (관이름), ())
HAVING GROUPING(장르) = 1
 ORDER BY 관이름, 장르;
14
22
36
43
정답 및 해설

GROUPING(장르) 는 장르가 집계로 인해 NULL 이 된 행에서만 1 이므로, HAVING 조건은 1관·2관 소계와 총계 3행만 남긴다.

GROUPING SETS 가 만든 행은 상세 3, 관별 소계 2, 총계 1 의 6행이며, 1관의 장르 NULL 상세 행은 원래 데이터의 NULL 이라 GROUPING 값이 0 이다.

  • 2행은 총계 행의 GROUPING(장르) 도 1 이라는 점을 놓친 값이다.
  • 4행은 원래 NULL 인 장르 상세 행까지 포함한 값이다.
  • 6행은 HAVING 조건을 적용하기 전의 전체 행 수이다.
문제 36
Oracle 기준으로 다음 SQL 의 실행 결과로 옳은 것은?

[상영]

상영번호관이름관객수
11관30
21관50
31관20
42관40
52관(null)
62관60
SELECT 상영번호,
       RATIO_TO_REPORT(관객수)
         OVER (PARTITION BY 관이름) AS 비율
  FROM 상영
 ORDER BY 상영번호;
1
상영번호비율
10.3
20.8
31
40.4
5(null)
61
2
상영번호비율
10.3
20.5
30.2
40.4
5(null)
60.6
3
상영번호비율
10.3
20.5
30.2
40.4
50
60.6
4
상영번호비율
10.15
20.25
30.1
40.2
5(null)
60.3
정답 및 해설

RATIO_TO_REPORT 는 각 행 값을 파티션 합계로 나눈 비율로, 1관은 합 100 기준 0.3·0.5·0.2, 2관은 NULL 을 뺀 합 100 기준 0.4·0.6 이다.

관객수가 NULL 인 상영 5 는 나눌 값이 없어 비율도 NULL 이며, 합계 계산에서도 제외된다.

  • 0.15 부터 시작하는 표는 PARTITION BY 없이 전체 합 200 으로 나눈 결과이다.
  • 상영 5 가 0 인 표는 NULL 을 0 으로 바꿔 계산한 것이다.
  • 0.8·1 이 나오는 표는 누적 비율로 오해한 결과이다.
문제 37
다음 ㉠과 ㉡의 결과 행 수를 순서대로 나열한 것은?

[상영]

상영번호관이름관객수
1A관40
2A관20
3B관35
4B관(null)
5C관50
6A관30
7B관60

㉠

SELECT 관이름,
       COUNT(*) OVER (PARTITION BY 관이름) AS 횟수
  FROM 상영
 WHERE 관객수 >= 30;

㉡

SELECT DISTINCT 관이름,
       COUNT(*) OVER (PARTITION BY 관이름) AS 횟수
  FROM 상영
 WHERE 관객수 >= 30;
15, 5
27, 3
35, 3
43, 3
정답 및 해설

WHERE 가 먼저 관객수 30 이상인 1·3·5·6·7번 5행을 남기고, 윈도우 함수는 행을 줄이지 않으므로 ㉠은 5행이다.

㉡은 같은 관이름의 행이 같은 횟수 값을 가져 DISTINCT 로 A관 2·B관 2·C관 1 의 3행으로 줄어든다.

  • 7은 WHERE 이전의 전체 행 수로, NULL 과 20 인 행도 빠진다.
  • ㉡을 5행으로 본 것은 DISTINCT 가 중복 행을 합친다는 점을 놓친 것이다.
  • ㉠을 3행으로 본 것은 윈도우 함수를 GROUP BY 처럼 그룹당 1행으로 본 것이다.
문제 38
다음 결과를 얻기 위해 ㉠에 들어갈 함수로 옳은 것은? (DBMS 는 DESC 정렬에서 NULL 을 맨 앞에 둔다)

[상영]

상영번호관이름관객수
1A관50
2A관40
3A관40
4A관20
5B관30
6B관(null)
7B관30
SELECT 관이름, 상영번호, 관객수,
       ( ㉠ ) OVER (PARTITION BY 관이름
                    ORDER BY 관객수 DESC) AS 순위
  FROM 상영
 ORDER BY 관이름, 순위, 상영번호;
관이름상영번호관객수순위
A관1501
A관2402
A관3402
A관4203
B관6(null)1
B관5302
B관7302
1DENSE_RANK()
2ROW_NUMBER()
3RANK()
4PERCENT_RANK()
정답 및 해설

결과에서 A관은 1·2·2·3, B관은 1·2·2 로 동점은 같은 순위를 받고 다음 순위가 건너뛰지 않으므로 DENSE_RANK 이다.

B관은 DESC 정렬에서 NULL 이 맨 앞에 와 6번이 1위가 되고, 관객수 30 인 5·7번이 공동 2위가 된다.

  • RANK 는 동점 다음 순위를 건너뛰어 A관 20 이 4위가 된다.
  • ROW_NUMBER 는 동점에도 서로 다른 번호를 매겨 2·3 처럼 나뉜다.
  • PERCENT_RANK 는 0 과 1 사이의 비율 값을 돌려준다.
문제 39
다음 SQL 의 실행 결과로 옳은 것은?

[일별관객]

관이름상영일자관객수
A관2026-03-01100
A관2026-03-0280
A관2026-03-03120
B관2026-03-0150
B관2026-03-02(null)
B관2026-03-0370
SELECT 관이름, 상영일자,
       SUM(관객수) OVER (PARTITION BY 관이름
                         ORDER BY 상영일자
                         ROWS BETWEEN 1 PRECEDING
                                  AND CURRENT ROW) AS 이동합
  FROM 일별관객
 ORDER BY 관이름, 상영일자;
1
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-0150
B관2026-03-02(null)
B관2026-03-03(null)
2
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03300
B관2026-03-0150
B관2026-03-0250
B관2026-03-03120
3
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-0150
B관2026-03-0250
B관2026-03-0370
4
관이름상영일자이동합
A관2026-03-01100
A관2026-03-02180
A관2026-03-03200
B관2026-03-01170
B관2026-03-0250
B관2026-03-0370
정답 및 해설

ROWS BETWEEN 1 PRECEDING AND CURRENT ROW 는 파티션 안에서 직전 1행과 현재 행만 더하는 이동 합이라 A관은 100·180·200 이다.

B관 둘째 날은 50 과 NULL 중 NULL 을 건너뛰어 50, 셋째 날은 NULL 과 70 이라 70 이 되며 첫 행은 직전 행이 없어 자기 값이다.

  • 300·120 이 나온 표는 처음부터 누적한 합으로 본 결과이다.
  • B관에 NULL 이 이어지는 표는 SUM 이 NULL 을 전파한다고 본 것이다.
  • B관 첫 행이 170 인 표는 파티션을 무시하고 A관 마지막 행을 더한 것이다.
문제 40
다음 SQL 의 실행 결과로 옳은 것은?

[예매]

예매번호회원번호금액상태
1715000완료
2712000취소
379000완료
4820000취소
5811000완료
6811000완료
798000완료
SELECT 회원번호, 예매번호, 금액
  FROM (SELECT 회원번호, 예매번호, 금액, 상태,
               ROW_NUMBER() OVER (PARTITION BY 회원번호
                                  ORDER BY 금액 DESC, 예매번호) AS RN
          FROM 예매) T
 WHERE RN <= 2
   AND 상태 = '완료'
 ORDER BY 회원번호, 예매번호;
1
회원번호예매번호금액
7115000
2
회원번호예매번호금액
7115000
8511000
978000
3
회원번호예매번호금액
7115000
8511000
8611000
978000
4
회원번호예매번호금액
7115000
739000
8511000
8611000
978000
정답 및 해설

ROW_NUMBER 는 인라인 뷰 안에서 취소 건까지 포함해 회원별로 매겨지고, 상태 조건은 그 뒤 바깥 WHERE 에서 적용되므로 결과는 3행이다.

회원 7 은 1·2위가 예매 1·2 인데 2 가 취소라 1 만, 회원 8 은 1위 4 가 취소라 2위 5 만, 회원 9 는 7 만 남는다.

  • 5행 표는 취소 건을 먼저 거른 뒤 순번을 매긴 결과이다.
  • 회원 8 이 두 행인 표는 보조 정렬 예매번호를 무시하고 동점 11000 을 같은 순위로 본 결과이다.
  • 1행 표는 PARTITION BY 없이 전체 상위 2건만 본 결과이다.
문제 41
Oracle 에서 관객수 2~3위 영화를 구하려 한다. 의도한 두 행을 정확히 돌려주는 SQL 은? (관객수에 NULL·동점은 없다)

[영화]

제목관객수
파도900
정원700
추적800
별빛500
노을600
㉠ SELECT 제목, 관객수
     FROM (SELECT 제목, 관객수 FROM 영화
            ORDER BY 관객수 DESC)
    WHERE ROWNUM BETWEEN 2 AND 3;

㉡ SELECT 제목, 관객수
     FROM 영화
    WHERE ROWNUM <= 3 AND ROWNUM >= 2
    ORDER BY 관객수 DESC;

㉢ SELECT 제목, 관객수
     FROM (SELECT ROWNUM AS RN, A.*
             FROM (SELECT 제목, 관객수 FROM 영화
                    ORDER BY 관객수 DESC) A)
    WHERE RN BETWEEN 2 AND 3;

㉣ SELECT ROWNUM AS RN, 제목, 관객수
     FROM (SELECT 제목, 관객수 FROM 영화
            ORDER BY 관객수 DESC)
    WHERE RN BETWEEN 2 AND 3;
1㉠
2㉡
3㉣
4㉢
정답 및 해설

ROWNUM 은 조건을 통과한 행에 1부터 차례로 붙으므로 첫 행이 1 이 되지 못하면 다음 행도 1 이 되어 ROWNUM >= 2 류 조건은 0건이 된다.

㉢처럼 정렬한 인라인 뷰에 ROWNUM 을 별칭 RN 으로 고정한 뒤 바깥에서 RN 범위를 걸어야 추적·정원 두 행이 나온다.

  • ㉠은 ROWNUM BETWEEN 2 AND 3 이라 첫 행부터 탈락해 결과가 없다.
  • ㉡도 ROWNUM >= 2 를 만족하는 행이 없고 정렬도 번호 부여 뒤에 일어난다.
  • ㉣은 같은 쿼리 블록의 WHERE 에서 SELECT 별칭 RN 을 쓸 수 없어 오류가 난다.
문제 42
Oracle 에서 다음 계층형 질의에 대한 설명으로 옳은 것은?

[장르분류]

분류코드분류명상위코드
A영화(null)
A1액션A
A2드라마A
A11첩보A1
SELECT LEVEL, 분류명
  FROM 장르분류
 START WITH 분류코드 = 'A1'
 CONNECT BY PRIOR 분류코드 = 상위코드;
1시작 행 액션의 LEVEL 값은 0 이다
2첩보에서 영화로 올라가는 역방향이다
3시작 행의 상위인 영화도 함께 나온다
4위에서 아래로 내려가는 순방향 전개다
정답 및 해설

PRIOR 분류코드 = 상위코드 는 앞서 읽은 행의 분류코드를 상위코드로 가진 자식을 찾으므로 순방향(부모→자식) 전개다.

결과는 시작 행 액션(LEVEL 1)과 그 하위 첩보(LEVEL 2) 두 행이며, 시작 행 위쪽은 탐색하지 않는다.

  • LEVEL 은 시작 행을 1 로 세며 0 부터 시작하지 않는다.
  • 역방향은 PRIOR 상위코드 = 분류코드 처럼 PRIOR 를 자식 쪽 열에 둘 때이다.
  • 순방향이므로 시작 행의 상위인 영화는 결과에 나오지 않는다.
문제 43
Oracle 계층형 질의에서 더 이상 하위 분류가 없는 최하위 분류만 남기려 한다. ㉠에 알맞은 조건은?
SELECT 분류명
  FROM 장르분류
 WHERE ( ㉠ )
 START WITH 상위코드 IS NULL
 CONNECT BY PRIOR 분류코드 = 상위코드;
1LEVEL = 1
2ROWNUM = 1
3상위코드 IS NOT NULL
4CONNECT_BY_ISLEAF = 1
정답 및 해설

CONNECT_BY_ISLEAF 는 현재 행에 자식이 없으면 1, 있으면 0 을 돌려주므로 최하위 분류만 남기려면 = 1 조건을 쓴다.

계층형 질의의 WHERE 절은 계층 전개가 끝난 뒤 결과 행을 거르는 데 쓰인다.

  • LEVEL = 1 은 START WITH 로 시작한 최상위 분류만 남긴다.
  • 상위코드 IS NOT NULL 은 하위가 있는 중간 분류까지 함께 남긴다.
  • ROWNUM = 1 은 전개 결과의 첫 행인 최상위 분류 하나만 남긴다.
문제 44
다음 SQL 의 실행 결과로 옳은 것은? (요일은 가나다순으로 금·일·토 순서이다)

[예매]

예매번호제목요일인원
1파도토2
2파도일3
3파도일(null)
4정원토4
5정원금1
6추적금2
SELECT 제목,
       SUM(CASE WHEN 요일 = '토' THEN 인원 ELSE 0 END) AS 토,
       SUM(CASE WHEN 요일 = '일' THEN 인원 ELSE 0 END) AS 일
  FROM 예매
 GROUP BY 제목, 요일
 ORDER BY 제목, 요일;
1
제목토일
정원40
추적00
파도23
2
제목토일
정원00
정원40
파도03
파도20
3
제목토일
정원00
정원40
추적00
파도0(null)
파도20
4
제목토일
정원00
정원40
추적00
파도03
파도20
정답 및 해설

GROUP BY 에 피벗 대상인 요일까지 포함했으므로 (제목, 요일) 조합마다 한 행이 생겨 피벗되지 않고 5행이 된다.

정원은 금·토 두 행, 추적은 금 한 행(토·일 모두 0), 파도는 일 행에서 3, 토 행에서 2 가 나온다.

  • 제목당 한 행인 표는 GROUP BY 에 제목만 둔 올바른 피벗 결과이다.
  • 파도 일 칸이 NULL 인 표는 SUM 이 NULL 인원 행 때문에 NULL 이 된다고 본 것이다.
  • 추적 행이 없는 표는 토·일 예매가 없는 그룹이 사라진다고 본 것이다.
문제 45
Oracle 기준으로 다음 SQL 의 결과 행 수는?

[예매]

예매번호좌석
1H-07
2J 12
3K1,K2
4VIP3
5A_5
6B12
SELECT 예매번호, 좌석
  FROM 예매
 WHERE REGEXP_LIKE(좌석, '[[:space:][:punct:]]');
13
22
35
44
정답 및 해설

[[:space:][:punct:]] 는 공백 또는 구두점 한 글자와 일치하는 문자 목록이고 앵커가 없어 어디에 있든 하나만 있으면 참이므로 4행이다.

하이픈의 H-07, 공백의 J 12, 쉼표의 K1,K2, 밑줄의 A_5 가 일치하고 영숫자뿐인 VIP3·B12 는 빠진다.

  • 3행은 밑줄(_)을 구두점이 아니라고 본 값이다.
  • 2행은 공백 클래스만 또는 구두점 중 일부만 적용한 값이다.
  • 5행은 숫자가 섞인 VIP3 까지 일치한다고 본 값이다.
문제 46
다음 MERGE 문을 실행한 뒤 요금표의 행 수와, MERGE 가 갱신·삽입으로 처리한 행 수를 순서대로 나열한 것은? (단위: 행)

[요금표]

상영관요금
1관12000
2관13000
3관15000

[신규요금]

상영관요금
2관14000
3관15000
4관18000
MERGE INTO 요금표 T
USING 신규요금 S
   ON (T.상영관 = S.상영관)
 WHEN MATCHED THEN
   UPDATE SET T.요금 = S.요금
 WHEN NOT MATCHED THEN
   INSERT (상영관, 요금)
   VALUES (S.상영관, S.요금);
13, 2
24, 2
34, 3
46, 3
정답 및 해설

ON 조건에 맞는 2관·3관은 WHEN MATCHED 로 갱신되고 짝이 없는 4관은 WHEN NOT MATCHED 로 삽입되어 처리 행 수는 3, 요금표는 4행이 된다.

3관은 바뀌기 전후 요금이 같지만 조건에 맞았으므로 UPDATE 대상으로 처리되고, 원본에 없는 1관은 영향을 받지 않는다.

  • 처리 2행은 값이 같은 3관을 갱신 대상에서 뺀 값이다.
  • 요금표 3행은 4관이 삽입된다는 점을 놓친 값이다.
  • 요금표 6행은 원본 행을 모두 새로 붙인다고 본 값이다.
문제 47
Oracle 에서 다음 순서로 실행했을 때 ㉠ 시점 세션 B 의 SELECT 결과로 옳은 것은?
-- 예매번호 10 의 인원은 처음에 2 이다
[세션 A] UPDATE 예매 SET 인원 = 5 WHERE 예매번호 = 10;
[세션 B] SELECT 인원 FROM 예매 WHERE 예매번호 = 10;  -- ㉠
[세션 A] COMMIT;
1잠금 충돌로 오류가 난다
2변경 전 값 2 를 읽는다
3A 가 끝날 때까지 기다린다
4변경 후 값 5 를 읽는다
정답 및 해설

Oracle 은 읽기 일관성을 보장해 커밋되지 않은 다른 세션의 변경을 보여 주지 않으므로, 세션 B 는 변경 전 값 2 를 읽는다.

조회는 행 잠금을 기다리지 않고 언두(Undo) 정보로 변경 전 데이터를 만들어 돌려준다.

  • 미커밋 값 5 를 읽는 것은 Dirty Read 로 Oracle 에서는 일어나지 않는다.
  • 잠금은 같은 행을 수정하려는 DML 끼리만 기다리게 한다.
  • 단순 조회는 잠금 충돌 오류를 일으키지 않는다.
문제 48
다음 테이블에 상영번호 1 행이 이미 입력된 상태에서 ㉠~㉣을 차례로 실행할 때, 제약조건 위반으로 실패하는 것은?
CREATE TABLE 상영관 (관번호 INT PRIMARY KEY, 좌석수 INT);
-- 상영관: (1, 100), (2, 80)

CREATE TABLE 상영 (
  상영번호 INT PRIMARY KEY,
  관번호   INT REFERENCES 상영관(관번호),
  시작시각 CHAR(5) NOT NULL,
  요금     INT DEFAULT 10000
           CHECK (요금 BETWEEN 5000 AND 20000),
  UNIQUE (관번호, 시작시각)
);
-- 상영: (1, 1, '10:00', 12000)

㉠ INSERT INTO 상영 VALUES (2, NULL, '10:00', 9000);
㉡ INSERT INTO 상영 (상영번호, 관번호, 시작시각)
   VALUES (3, 2, '10:00');
㉢ INSERT INTO 상영 VALUES (4, 1, '13:00', 20000);
㉣ INSERT INTO 상영 VALUES (5, 1, '10:00', 8000);
1㉣
2㉡
3㉢
4㉠
정답 및 해설

㉣은 관번호 1·시작시각 '10:00' 조합이 기존 상영번호 1 행과 같아 복합 UNIQUE 제약 (관번호, 시작시각) 을 위반한다.

복합 UNIQUE 는 두 열 값이 모두 같을 때만 막으며, 한 열만 같거나 NULL 이 섞인 행은 허용한다.

  • ㉠은 FK 열이 NULL 이라 참조 검사를 하지 않고, UNIQUE 도 NULL 이 섞여 통과한다.
  • ㉡은 생략한 요금에 DEFAULT 10000 이 들어가 CHECK 를 만족한다.
  • ㉢의 20000 은 BETWEEN 의 끝값이라 포함되어 통과한다.
문제 49
Oracle 에서 다음 두 테이블에 데이터가 들어 있을 때, 실행하면 오류가 발생하는 문장은?
CREATE TABLE 영화 (
  영화번호 NUMBER PRIMARY KEY,
  제목     VARCHAR2(50)
);
CREATE TABLE 상영 (
  상영번호 NUMBER PRIMARY KEY,
  영화번호 NUMBER REFERENCES 영화(영화번호),
  상영일시 DATE
);
1TRUNCATE TABLE 상영;
2DROP TABLE 영화 PURGE;
3ALTER TABLE 상영 DROP COLUMN 상영일시;
4DROP TABLE 영화 CASCADE CONSTRAINTS;
정답 및 해설

영화 테이블의 기본키를 상영 테이블의 외래키가 참조하고 있으므로, 옵션 없이 부모인 영화를 DROP 하면 참조 제약 때문에 오류(ORA-02449)가 난다.

PURGE 는 휴지통을 거치지 않고 바로 지우라는 뜻일 뿐 참조 제약 검사는 그대로 받으며, 부모를 지우려면 CASCADE CONSTRAINTS 로 자식의 FK 제약을 함께 없애야 한다.

  • 상영 테이블의 일반 열인 상영일시는 제약과 무관해 DROP COLUMN 으로 지울 수 있다.
  • 자식 테이블을 TRUNCATE 하는 것은 참조 제약에 걸리지 않는다.
  • CASCADE CONSTRAINTS 를 붙이면 상영의 FK 제약이 삭제되며 영화가 지워진다.
문제 50
Oracle 에서 시스템 권한 CREATE TABLE 을 받은 사용자가 그 권한을 다른 사용자에게 다시 줄 수 있게 하려 한다. ㉠에 알맞은 것은?
GRANT CREATE TABLE TO 매니저 WITH ( ㉠ ) OPTION;
1GRANT
2ADMIN
3CHECK
4CASCADE
정답 및 해설

CREATE TABLE 같은 시스템 권한을 재부여할 수 있게 주려면 WITH ADMIN OPTION 을 붙인다.

SELECT ON 테이블 같은 오브젝트 권한을 재부여 가능하게 줄 때는 WITH GRANT OPTION 을 쓴다.

  • WITH GRANT OPTION 은 오브젝트 권한에만 쓰는 옵션이다.
  • WITH CHECK OPTION 은 뷰를 통한 입력·수정을 뷰 조건으로 제한한다.
  • WITH CASCADE OPTION 이라는 권한 부여 구문은 없다.