본문으로 건너뛰기

단원 모의 문제

정보처리기사 목차절차형 SQL문제 11개

16단원 '절차형 SQL'의 다섯 레슨에서 6문제, 앞 단원(13·14)에서 2문제를 섞었고, 끝에 실기 꼴 3문제가 있습니다. 앞 단원 문제가 어느 레슨인지는 정답을 펼치면 보입니다. 문제의 블록과 SQL은 아래 네 표로 Oracle에서 돌린다고 보고 풀어 보세요. 실기 꼴은 종이에 답을 끝까지 쓴 뒤 펼치세요. 띄어쓰기만 다르면 같은 답입니다.

학과

학과코드학과명건물
CS컴퓨터공학관
EE전자공학관
BA경영경영관

학생

학번이름학년학과코드
101김민수3CS
102이서준2CS
103김지민2CS
104박서연1EE
105최민준3EE
106정하윤3EE
107강도현1NULL

과목

과목코드과목명학점선수과목
DS자료구조3NULL
OS운영체제3DS
NW네트워크2OS

수강

학번과목코드점수
101DS85
101OS75
101NW80
102DS70
102OS60
103DS65
103NW55
104OS75
104NW95
105DS100
105NW90
107NW50

문제 1

다음 블록은 컴퓨터학과(CS) 학생 수를 세어 변수에 담고, 그 값에 1을 더해 다시 담습니다. (가)·(나)에 들어갈 것으로 알맞은 것을 고르세요.

DECLARE
  v_인원 NUMBER;
BEGIN
  SELECT COUNT(*) (가) v_인원
  FROM 학생
  WHERE 학과코드 = 'CS';
  v_인원 (나) v_인원 + 1;
END;
  • ① (가) AS · (나) =
  • ② (가) AS · (나) :=
  • ③ (가) INTO · (나) =
  • ④ (가) INTO · (나) :=
정답

④ — SELECT 결과를 변수에 담는 절은 INTO이고, 변수에 값을 담는 기호는 :=입니다. 등호 하나(=)는 값이 같은지 묻는 비교라서 담는 자리에 쓰지 않습니다.

  • ① 두 자리를 모두 쿼리에서 쓰는 꼴로 봤습니다. AS는 결과 열에 별칭을 붙이는 말이고, =는 비교 기호입니다.
  • ② (나)는 맞게 봤지만 (가)를 별칭으로 봤습니다. 별칭은 결과 열의 이름만 바꾸고, 변수에 담지는 못합니다.
  • ③ (가)는 맞게 봤지만 (나)를 비교 기호로 봤습니다. 블록에서 값을 담을 때는 콜론을 붙인 :=를 씁니다.

다시 볼 레슨: 절차형 SQL의 구조

문제 2

학년을 받아 그 학년 학생이 몇 명인지 세어 돌려주는 프로시저를 다음처럼 만들어 두었습니다. 3학년 인원을 받아 보는 문장으로 알맞은 것을 고르세요. 받을 칸은 VARIABLE 결과 NUMBER로 미리 만들어 두었습니다.

CREATE PROCEDURE 학년인원(
  p_학년 IN NUMBER,
  p_건수 OUT NUMBER
) IS
BEGIN
  SELECT COUNT(*) INTO p_건수
  FROM 학생
  WHERE 학년 = p_학년;
END;
  • ① EXECUTE 학년인원(3);
  • ② EXECUTE 학년인원(3, :결과);
  • ③ EXECUTE 학년인원(3, 0);
  • ④ SELECT 학년인원(3) FROM DUAL;
정답

② — 괄호 안의 값은 적은 차례대로 매개변수에 담기고, OUT 자리에는 값 대신 돌려받을 변수를 적습니다. VARIABLE로 만든 칸은 :결과처럼 앞에 콜론을 붙여 가리킵니다.

  • ① OUT 자리를 비워도 된다고 봤습니다. 매개변수가 둘인데 값을 하나만 넘기면 매개변수의 수가 맞지 않아 호출 자체가 막힙니다.
  • ③ OUT 자리에 값을 그대로 적었습니다. 프로시저가 담아 줄 자리가 필요하므로 값이 아니라 변수를 적습니다.
  • ④ 프로시저를 값이 올 자리에서 부를 수 있다고 봤습니다. 쿼리 안에서 부르는 것은 사용자 정의 함수이고, 프로시저 이름을 적으면 데이터베이스가 알아보지 못합니다.

다시 볼 레슨: 저장 프로시저

문제 3

점수를 받아 80점 이상이면 '우수'를 돌려주는 함수를 만들고, 네트워크(NW) 수강 행에 붙여 조회했습니다. 일어나는 일로 알맞은 것을 고르세요.

CREATE FUNCTION 평가(
  p_점수 NUMBER
) RETURN VARCHAR2 IS
BEGIN
  IF p_점수 >= 80 THEN
    RETURN '우수';
  END IF;
END;
/
SELECT 학번,
  평가(점수) AS 평가
FROM 수강
WHERE 과목코드 = 'NW'
ORDER BY 학번;
  • ① 함수는 만들어지고, 80점 미만인 행을 만나면 오류가 난다
  • ② 함수가 만들어지지 않아 쿼리도 돌지 않는다
  • ③ 함수는 만들어지고, 80점 미만인 행은 NULL로 나온다
  • ④ 함수는 만들어지고, 80점 미만인 행만 결과에서 빠진다
정답

① — 몸의 RETURN은 값을 들고 그 자리에서 함수를 끝냅니다. 80점 미만인 점수는 IF 안으로 들어가지 못해 RETURN을 한 번도 지나지 않고 END에 닿고, 그런 행에서 ORA-06503 오류가 납니다. NW 점수는 101이 80, 103이 55이므로 55를 받은 행에서 오류가 나고, 쿼리는 결과를 내놓지 못합니다.

  • ② 갈림길마다 RETURN이 없으면 만들 때 막힌다고 봤습니다. 머리에 돌려줄 자료형이 있어 함수는 만들어지고, 값을 들고 나오지 못하는 것은 부를 때 드러납니다.
  • ③ 돌려준 값이 없으면 NULL이 된다고 봤습니다. 돌려주는 통로를 지나지 않은 것은 빈 값이 아니라 오류입니다.
  • ④ 값을 못 받은 행만 조용히 빠진다고 봤습니다. 한 행에서 난 오류가 쿼리 전체를 멈춥니다.

다시 볼 레슨: 사용자 정의 함수

문제 4

학생 표의 학년이 바뀔 때마다 기록 표에 한 줄을 남기려고 다음 트리거를 만들고, 2학년의 학년을 1씩 올렸습니다. 기록 표에 쌓이는 줄 수가 (가)입니다. 같은 몸으로 FOR EACH ROW만 뺀 트리거를 만들어 같은 UPDATE를 돌리면 (나)입니다. 알맞은 것을 고르세요.

CREATE TABLE 변경기록 (
  메모 VARCHAR2(20 CHAR)
);
CREATE TRIGGER 학년_변경기록
AFTER UPDATE ON 학생
FOR EACH ROW
BEGIN
  INSERT INTO 변경기록
  VALUES ('학년 바뀜');
END;
/
UPDATE 학생
SET 학년 = 학년 + 1
WHERE 학년 = 2;
SELECT COUNT(*) AS 줄수
FROM 변경기록;
  • ① (가) 1줄 · (나) 1줄
  • ② (가) 1줄 · (나) 2줄
  • ③ (가) 2줄 · (나) 1줄
  • ④ (가) 2줄 · (나) 2줄
정답

③ — FOR EACH ROW가 있으면 바뀐 행마다 한 번씩 깨어납니다. 2학년은 102·103 둘이라 UPDATE 한 문장에 두 줄이 쌓입니다. FOR EACH ROW를 빼면 문장 트리거가 되어 문장 하나에 한 번만 깨어나므로 한 줄입니다.

  • ① (가)를 문장 트리거처럼 봤습니다. 행 트리거는 바뀐 행 수만큼 돕니다.
  • ② 두 자리를 거꾸로 봤습니다. 행마다 도는 쪽이 FOR EACH ROW가 있는 트리거입니다.
  • ④ (나)에서도 행마다 돈다고 봤습니다. FOR EACH ROW가 없으면 몇 행이 바뀌어도 한 번입니다.
줄수
2

다시 볼 레슨: 트리거와 이벤트

문제 5

어느 쇼핑몰 데이터베이스에서 (가)·(나) 두 가지 일을 저절로 일어나게 하려 합니다. 각각 무엇으로 만들어야 하는지 알맞은 것을 고르세요.

  • (가) 주문 표에 주문 한 건이 들어가는 순간 재고 기록 표에 한 줄을 남깁니다.

  • (나) 데이터가 바뀌지 않아도 날마다 밤 3시가 되면 지난해 접속 기록을 지웁니다.

  • ① (가) 트리거 · (나) 트리거

  • ② (가) 트리거 · (나) 이벤트

  • ③ (가) 이벤트 · (나) 트리거

  • ④ (가) 이벤트 · (나) 이벤트

정답

② — 둘을 가르는 것은 깨우는 쪽입니다. (가)는 주문 표의 데이터가 들어가는 것이 깨우므로 트리거이고, (나)는 데이터가 그대로여도 정해진 시각이 깨우므로 이벤트입니다.

  • ① (나)도 데이터 변경이 깨운다고 봤습니다. 접속 기록을 지우는 일은 아무 표도 바뀌지 않아도 때가 되면 돌아야 합니다.
  • ③ 두 자리를 거꾸로 봤습니다. 표에 매여 변경을 기다리는 쪽이 트리거, 데이터베이스에 걸려 시각을 기다리는 쪽이 이벤트입니다.
  • ④ (가)도 시각이 깨운다고 봤습니다. 주문이 몇 시에 들어올지 정해 둘 수 없고, 들어가는 순간에 맞춰 돌아야 합니다.

다시 볼 레슨: 트리거와 이벤트

문제 6

학생 표를 만들 때 학년 열에 CHECK (학년 BETWEEN 1 AND 4) 제약 조건을 걸어 두었습니다. (가) 학년을 5로 적은 INSERT가 어떻게 되는지, (나) 5로 들어오는 값을 막지 않고 4로 바꿔 저장하려면 무엇을 두어야 하는지 알맞은 것을 고르세요.

  • ① (가) 행이 들어가고 학년은 NULL이 된다 · (나) CHECK 제약 조건
  • ② (가) 행이 들어가고 학년은 NULL이 된다 · (나) BEFORE 트리거
  • ③ (가) 오류가 나고 행이 들어가지 않는다 · (나) CHECK 제약 조건
  • ④ (가) 오류가 나고 행이 들어가지 않는다 · (나) BEFORE 트리거
정답

④ — 제약 조건은 어긋나는 값을 받지 않고 그 문장을 오류로 되돌립니다. 행은 들어가지 않고 표는 그대로입니다. 값을 바꿔 저장하려면 저장되기 전에 끼어드는 자리가 필요하고, 그 자리가 BEFORE 행 트리거입니다. :NEW.학년에 4를 담으면 담은 값이 저장됩니다.

  • ① 제약 조건이 어긋나는 값을 비워서 넣는다고 보고, (나)도 거절하는 쪽을 골랐습니다. 제약 조건은 값을 고치지 않습니다.
  • ② (나)는 맞게 봤지만 (가)에서 값이 비워진다고 봤습니다. 제약 조건을 어기면 그 INSERT 문이 거절됩니다.
  • ③ (가)는 맞게 봤지만 (나)도 제약 조건으로 봤습니다. 제약 조건에는 값을 다듬는 자리가 없어, 걸리면 거절뿐입니다.

다시 볼 레슨: DDL: CREATE·ALTER·DROP · 트리거와 이벤트

문제 7

다음 블록을 돌렸습니다. 찍히는 줄이 (가)이고, 블록이 끝나는 모습이 (나)입니다. 알맞은 것을 고르세요.

SET SERVEROUTPUT ON
DECLARE
  미달 EXCEPTION;
  v_평균 NUMBER;
BEGIN
  SELECT AVG(점수) INTO v_평균
  FROM 수강
  WHERE 학번 = 103;
  IF v_평균 < 70 THEN
    RAISE 미달;
  END IF;
  DBMS_OUTPUT.PUT_LINE(
      '통과');
EXCEPTION
  WHEN 미달 THEN
    DBMS_OUTPUT.PUT_LINE(
        '미달');
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(
        '오류');
END;
/
  • ① (가) 미달 · (나) 정상으로 끝난다
  • ② (가) 미달 · (나) 오류 번호가 나온다
  • ③ (가) 통과 · (나) 정상으로 끝난다
  • ④ (가) 통과 · (나) 오류 번호가 나온다
정답

① — 103번의 점수는 65·55라 평균이 60이고, 70 미만이므로 RAISE 미달;을 지납니다. 그 순간 흐름이 예외 처리부로 뛰어 아래의 '통과' 줄을 건너뛰고, 이름이 맞는 WHEN 미달만 실행됩니다. 예외를 받아 처리하면 블록은 정상으로 끝납니다.

  • ② 받은 예외도 밖으로 나간다고 봤습니다. 받아 처리한 예외는 오류 번호를 내지 않습니다.
  • ③ 평균을 70 이상으로 셈했거나, RAISE가 흐름을 바꾸지 않는다고 봤습니다. 65와 55의 평균은 60입니다.
  • ④ 두 자리를 모두 어긋나게 봤습니다. RAISE를 지나면 '통과'는 찍히지 않고, 받은 예외는 오류로 끝나지 않습니다.
미달

다시 볼 레슨: 절차형 SQL의 오류 처리

문제 8

다음 쿼리를 돌리면 어떻게 되는지 고르세요.

SELECT 이름
FROM 학생
WHERE 학과코드 = (
  SELECT 학과코드
  FROM 학생
  WHERE 학년 = 3
);
  • ① 3학년이 속한 학과의 학생 이름이 모두 나온다
  • ② 한 행도 나오지 않는다
  • ③ 서브쿼리가 여러 행을 돌려줘 오류가 난다
  • ④ 서브쿼리가 돌려준 첫 행의 학과만 쓰여 그 학과 학생 이름이 나온다
정답

③ — =는 값 하나와 견주는 비교 연산자라서 서브쿼리가 돌려주는 행이 하나여야 합니다. 3학년은 101·105·106 셋이고 학과코드가 CS·EE·EE 세 행으로 나오므로 ORA-01427 오류가 납니다. 여러 값을 받으려면 IN이나 = ANY를 씁니다.

  • ① = 자리에 값이 여럿 와도 그 가운데 하나만 맞으면 참이 된다고 봤습니다. 그 뜻으로 쓰는 연산자가 IN입니다.
  • ② 조건이 참이 되지 못해 결과가 빈다고 봤습니다. 거짓이 되는 것이 아니라 쿼리 자체가 멈춥니다.
  • ④ 여러 행 가운데 첫 행만 쓰인다고 봤습니다. 비교 연산자는 행을 골라 쓰지 않습니다.

다시 볼 레슨: 서브쿼리

문제 9 (실기)

다음 (가)·(나)에서 블록이 받게 되는 예외의 이름을 영문으로, 대문자와 밑줄까지 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

  • (가) 수강 표에서 점수 하나를 변수에 담으려고 학번 101만 조건으로 주었습니다. 101번은 세 과목을 듣고 있습니다.
  • (나) 반 평균을 내려고 점수 합계를 학생 수로 셈하는 블록을 돌렸습니다. 조건에 맞는 학생이 한 명도 없어 학생 수 자리에 0이 담겼습니다.
정답

받는 답: (가) TOO_MANY_ROWS · (나) ZERO_DIVIDE

(가)의 실마리는 'SELECT INTO가 담을 행이 한 행을 넘는다', (나)는 '셈하는 값 가운데 아래쪽이 0이다'입니다.

  • 같은 이름의 다른 꼴: 오류 번호로 쓴 꼴(ORA-01422·ORA-01476) — 번호가 아니라 예외의 이름을 묻습니다.
  • 틀리는 꼴 NO_DATA_FOUND — (가)에: SELECT INTO가 담을 행을 찾지 못했을 때 나는 이름입니다. (가)는 찾은 행이 많아서 난 오류입니다.
  • 틀리는 꼴 DUP_VAL_ON_INDEX — (나)에: 겹치면 안 되는 칸에 같은 값을 넣었을 때 나는 이름입니다. 셈하다 난 오류가 아닙니다.

다시 볼 레슨: 절차형 SQL의 오류 처리

문제 10 (실기)

어느 회사가 접속 기록 표를 비웁니다. (가)·(나)에서 쓸 명령어를 SQL 키워드 그대로 대문자로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

  • (가) 지난달에 쌓인 기록만 조건으로 골라 지우고, 잘못 지웠으면 ROLLBACK으로 되돌릴 수 있어야 합니다.
  • (나) 행을 전부 지워 비우되 표의 틀은 남깁니다. 되돌릴 일은 없고, 시험 자료는 이 명령어를 DDL로 봅니다.
정답

받는 답: (가) DELETE · (나) TRUNCATE

(가)의 실마리는 '조건으로 골라 지운다'와 '되돌릴 수 있다', (나)는 '행은 다 지우고 틀은 남는다'와 'DDL'입니다.

  • 같은 이름의 다른 꼴: DELETE FROM·TRUNCATE TABLE처럼 뒤따르는 낱말까지 쓴 꼴 — 명령어가 들어 있으니 함께 받습니다.
  • 틀리는 꼴 TRUNCATE — (가)에: 조건을 줄 수 없고 행을 전부 지우며, 되돌릴 수도 없습니다.
  • 틀리는 꼴 DROP — (나)에: 행과 함께 표의 틀까지 없앱니다. (나)는 틀을 남깁니다.

다시 볼 레슨: DML: INSERT·UPDATE·DELETE

문제 11 (실기)

다음을 차례로 돌렸습니다. 마지막 쿼리의 결과가 몇 행이고 각 행의 값이 무엇인지 위에서부터 차례로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

CREATE FUNCTION 구간(
  p_점수 NUMBER
) RETURN VARCHAR2 IS
BEGIN
  IF p_점수 >= 90 THEN
    RETURN '상';
  ELSIF p_점수 >= 70 THEN
    RETURN '중';
  END IF;
  RETURN '하';
END;
/
SELECT 구간(점수) AS 구간,
  COUNT(*) AS 인원,
  MAX(점수) AS 최고
FROM 수강
WHERE 과목코드 <> 'DS'
GROUP BY 구간(점수)
HAVING COUNT(*) >= 3
ORDER BY 구간(점수);
정답

받는 답: 2행 · 중 3 80 · 하 3 60

함수는 행마다 한 번씩 불려 점수를 구간으로 바꾸고, GROUP BY가 그 값으로 묶습니다. 자료구조(DS)를 뺀 여덟 행의 구간은 95·90이 상, 80·75·75가 중, 60·55·50이 하입니다. HAVING이 인원 3 미만인 묶음을 떨어뜨려 상은 남지 않고, 남은 두 묶음의 가장 높은 점수는 80과 60입니다.

  • 틀리는 꼴 3행 · 상 2 95 · 중 3 80 · 하 3 60: HAVING을 지나쳤습니다. 인원이 3 미만인 묶음은 결과에 남지 않습니다.
  • 틀리는 꼴 3행 · 상 3 100 · 중 5 85 · 하 4 65: WHERE의 과목코드 <> 'DS'를 빼고 열두 행으로 셈했습니다.
  • 틀리는 꼴 2행 · 중 4 90 · 하 3 60: 90점을 중으로 봤습니다. 머리의 IF가 90 이상을 먼저 걸러 상으로 보냅니다.
구간인원최고
중380
하360

다시 볼 레슨: 사용자 정의 함수 · 그룹과 집계: GROUP BY·HAVING

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

정보처리기사 목차로