18장. 뷰(View) 뷰의 생성 뷰의 열 이름 뷰의 변경 : WITH CHECK OPTION 뷰 테이블의 정보와 네비게이터 뷰 테이블의 통계함수 사용 뷰 테이블의 제약 사항 뷰 명령어의 처리 뷰의 응용 분야 2018-11-20 쉽게 배우는 MySQL 5.x
18.1 뷰의 생성 -기본 테이블은 CREATE TABLE 명령문을 사용하여 생성하고 데이터 저장 -뷰 테이블은 그 자체에는 행을 가지고 있지 않고 기본 테이블로부터 조합한 데이터에 대한 처리로 가상 테이블을 만들어서 사용자에게 보여준다. -SQL 명령문에서 뷰의 이름이 사용될 때만 뷰의 내용이 존재 -뷰 형식을 구성하는 뷰 처리서(view formula)를 가지고 그 순간에 뷰를 실행 18.1 뷰의 생성 -뷰는 CREATE VIEW 명령문으로 생성 [예제 18-1] STUDENT 테이블로부터 모든 학생의 학번과 학년, 반을 가지고 있는 뷰 테이블(V_CLASS)을 생성하라. mysql> create view v_class as -> select distinct stu_no, grade, class -> from student; Query OK, 0 rows affected (0.05 sec) 뷰 테이블(“V_CLASS”)은 학년과 반이 중복되는 경우를 제외하고 모두 생성 2018-11-20 쉽게 배우는 MySQL 5.x
-새로 생성된 “V_CLASS” 뷰 테이블을 확인해 보자. mysql> select * from v_class; +----------+-------+-------+ | stu_no | grade | class | | 20001001 | 4 | 3 | | 20001015 | 4 | 1 | | 20001021 | 4 | 1 | | 20041002 | 3 | 2 | | 20041007 | 2 | 2 | | 20041033 | 3 | 3 | | 20061011 | 2 | 1 | | 20061014 | 2 | 1 | | 20061048 | 4 | 3 | | 20071001 | 1 | 1 | | 20071010 | 1 | 3 | | 20071022 | 1 | 3 | | 20071300 | 1 | 1 | | 20071307 | 1 | 3 | | 20071405 | 1 | 2 | 15 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-2] 등록한 학생의 학번과 등록년도에 대한 뷰 테이블을 생성하라. mysql> create view v_feeyear as -> select stu_no, fee_year -> from fee -> where fee_year is not null; Query OK, 0 rows affected (0.19 sec) -CREATE VIEW 명령문으로 V_CLASS과 V_FEEYEAR이라는 2개의 뷰를 생성 -뷰의 내용은 SELECT 명령문에 의해서 정의 -SELECT 명령문은 뷰 처리서를 구성 -2개의 뷰는 기본 테이블을 사용하는 것처럼 질의어를 사용 2개의 뷰 테이블은 기본 테이블처럼 변경시킬 수 있다. 뷰 테이블 변경시 기본 테이블의 데이터가 변경된다. 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-3] 재학생의 학번과 이름, 성별, 입학년도, 생년, 월, 일, 나이에 대한 뷰 테이블(V_AGES)을 생성하라. mysql> create view V_AGES as -> select stu_no, stu_name, -> substring(id_num, 8, 1) "SEX", -> substring(stu_no, 1, 4) "IBHAK_YEAR", -> substring(id_num,1,2) "B_YEAR", -> substring(id_num,3,2) "B_MONTH", -> substring(id_num,5,2) "B_DATE", -> year(now()) - birth_year + 1 "AGE" -> from student; Query OK, 0 rows affected (0.00 sec) mysql> select * from V_AGES; +----------+----------+------+------------+--------+---------+--------+------+ | stu_no | stu_name | SEX | IBHAK_YEAR | B_YEAR | B_MONTH | B_DATE | AGE | | 20001001 | 김유신 | 1 | 2000 | 81 | 10 | 07 | 27 | | 20001015 | 박도준 | 1 | 2000 | 78 | 01 | 16 | 30 | | 20001021 | 이상길 | 1 | 2000 | 75 | 08 | 19 | 33 | | 20041002 | 김유미 | 2 | 2004 | 83 | 02 | 07 | 25 | | 20041007 | 정인정 | 2 | 2004 | 83 | 03 | 15 | 25 | | 20041033 | 연개소문 | 1 | 2004 | 81 | 06 | 15 | 27 | | 20061011 | 박정인 | 1 | 2006 | 83 | 04 | 03 | 25 | | 20061014 | 고혜진 | 2 | 2006 | 87 | 03 | 07 | 21 | | 20061048 | 김영호 | 1 | 2006 | 86 | 08 | 11 | 22 | | 20071001 | 장수인 | 1 | 2007 | 89 | 02 | 09 | 19 | | 20071010 | 홍길동 | 1 | 2007 | 88 | 04 | 02 | 20 | | 20071022 | 이순신 | 1 | 2007 | 89 | 02 | 22 | 19 | | 20071300 | 유하나 | 2 | 2007 | 88 | 09 | 21 | 20 | | 20071307 | 김문영 | 2 | 2007 | 88 | 04 | 18 | 20 | | 20071405 | 최차영 | 2 | 2007 | 88 | 10 | 03 | 20 | 15 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-4] 재학생 중 21세 이상인 여학생의 학번, 이름, 성별, 출생년도, 나이를 출력하라. mysql> select stu_no, stu_name, sex, b_year, age -> from V_AGES -> where age > 20 and sex = '2'; +----------+----------+------+--------+------+ | stu_no | stu_name | SEX | B_YEAR | AGE | | 20041002 | 김유미 | 2 | 83 | 25 | | 20041007 | 정인정 | 2 | 83 | 25 | | 20061014 | 고혜진 | 2 | 87 | 21 | [예제 18-5] 재학생 중 21세에 해당하는 학생의 성년식 행사를 위한 명단을 출력하라. 단, 출력형식은 학과, 학년, 학번, 이름, 생년, 월, 일, 나이를 출력하라. mysql> select dept_code "학과코드",grade "학년",s.stu_no "학번",s.stu_name "이름", -> b_year "년",b_month "월", b_date "일", age "나이" -> from student s, V_AGES v -> where s.stu_no = v.stu_no and age = 21 -> order by 1, 2, 3; +----------+------+----------+--------+------+------+------+------+ | 학과코드 | 학년 | 학번 | 이름 | 년 | 월 | 일 | 나이 | | 10 | 2 | 20061014 | 고혜진 | 87 | 03 | 07 | 21 | 2018-11-20 쉽게 배우는 MySQL 5.x
V_AGES 뷰 테이블이 없다면 다음과 같은 SELECT 명령문을 사용 mysql> select dept_code "학과코드", grade "학년", stu_no "학번", stu_name "이름", -> substring(id_num, 1, 2) "년", -> substring(id_num, 3, 2) "월", -> substring(id_num, 5, 2) "일", -> year(now()) - birth_year + 1 "나이" -> from student -> where year(now()) - birth_year + 1 = 21 -> order by 1, 2, 3; +----------+------+----------+--------+------+------+------+------+ | 학과코드 | 학년 | 학번 | 이름 | 년 | 월 | 일 | 나이 | | 10 | 2 | 20061014 | 고혜진 | 87 | 03 | 07 | 21 | 1 row in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-6] 뷰 테이블(V_AGES)에서 재학생 중 20세 이상이고, 2000년~2004년에 입학한 학생을 구하여라. mysql> select * from V_AGES -> where age > 20 -> and ibhak_year between '2000' and '2004'; +----------+----------+------+------------+--------+---------+--------+------+ | stu_no | stu_name | SEX | IBHAK_YEAR | B_YEAR | B_MONTH | B_DATE | AGE | | 20001001 | 김유신 | 1 | 2000 | 81 | 10 | 07 | 27 | | 20001015 | 박도준 | 1 | 2000 | 78 | 01 | 16 | 30 | | 20001021 | 이상길 | 1 | 2000 | 75 | 08 | 19 | 33 | | 20041002 | 김유미 | 2 | 2004 | 83 | 02 | 07 | 25 | | 20041007 | 정인정 | 2 | 2004 | 83 | 03 | 15 | 25 | | 20041033 | 연개소문 | 1 | 2004 | 81 | 06 | 15 | 27 | 6 rows in set (0.00 sec) ) -DROP VIEW 명령문은 뷰를 삭제할 때 사용 -삭제될 뷰를 참조하는 다른 모든 종속된 뷰도 뷰 처리서에서 자동적으로 삭제 기본 테이블이 삭제될 때는 직접 또는 간접적으로 정의된 모든 뷰도 삭제 [예제 18-8] 뷰 테이블(V_AGES)를 삭제하라. mysql> drop view V_AGES; Query OK, 0 rows affected (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
18.2 뷰의 열 이름 -뷰에서 열의 이름을 지정하지 않으면 SELECT 절에서 열의 이름과 동일 18.2 뷰의 열 이름 -뷰에서 열의 이름을 지정하지 않으면 SELECT 절에서 열의 이름과 동일 -V_AGES 테이블의 STU_NO과 STU_NAME는 기본 테이블의 열의 이름과 동일 -나머지 열이름(SEX, IPHAK_YEAR,... AGE)은 뷰 테이블 생성자 임의로 정의 [예제 18-9] 전라남도 여수지역(우편번호 550)에 살고 있는 학생의 학번, 이름, 현주소의 우편번호 3자리를 가지는 뷰 테이블(V_ADDRESS)를 생성하라. mysql> create view v_address(hak, irum, hpost) as -> select stu_no, stu_name, substring(post_no, 1, 3) -> from student -> where substring(post_no, 1, 3) = '550'; Query OK, 0 rows affected (0.00 sec) 위의 뷰를 만들고 나서 확인을 해보자. mysql> select * from v_address; +----------+----------+-------+ | hak | irum | hpost | | 20041033 | 연개소문 | 550 | | 20071010 | 홍길동 | 550 | | 20071300 | 유하나 | 550 | V_ADDRESS 뷰에서는 STU_NO, STU_NAME 같은 열의 이름을 참조할 수 없다. 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-10] 등록금 총액별로 학생 인원 수 현황을 생성하는 뷰 테이블 V_FEETOTAL를 생성하라. 뷰의 열의 이름을 꼭 사용해야 되는 경우 -뷰 처리서의 SELECT 절에 있는 수식이 열의 명세로 구성되지 않고 함수이거나 계산 부분(예를 들면 v_address 뷰 테이블의 HPOST와 같이 사용) [예제 18-10] 등록금 총액별로 학생 인원 수 현황을 생성하는 뷰 테이블 V_FEETOTAL를 생성하라. mysql> create view v_feetotal(fee_total, row_total) as -> select fee_pay, count(*) -> from fee -> group by fee_pay; Query OK, 0 rows affected (0.08 sec) 뷰 테이블 V_FEETOTAL에서는 FEE_TOTAL과 ROW_TOTAL의 열 이름을 생략할 수 없다. 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-11] 등록금 총액별로 학생 인원 수 현황을 생성한 뷰 테이블 V_FEETOTA의L 내용을 출력하라. mysql> select fee_total , row_total, '명' -> from v_feetotal; +-----------+-----------+----+ | fee_total | row_total | 명 | | 5000 | 1 | 명 | | 305000 | 2 | 명 | | 500000 | 1 | 명 | | 505000 | 4 | 명 | | 1005000 | 3 | 명 | | 2005000 | 1 | 명 | | 2205000 | 1 | 명 | | 3000000 | 5 | 명 | | 3005000 | 6 | 명 | | 3500000 | 2 | 명 | 10 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
18.3 뷰의 변경 : WITH CHECK OPTION -뷰 테이블의 변경할 행은 기본 테이블에 기초를 두고 변경 -뷰의 변경은 예상치 않은 결과를 가져올 수 있다. [예제 18-12] 학적테이블에서 1985년 이전에 출생한 모든 학생에 대한 뷰 테이블(V_OLD)를 생성하라. mysql> create view v_old as -> select * from student -> where birth_year < 1985; Query OK, 0 rows affected (0.00 sec) mysql> select stu_no, stu_name, birth_year -> from v_old; +----------+----------+------------+ | stu_no | stu_name | birth_year | | 20001001 | 김유신 | 1981 | | 20001015 | 박도준 | 1978 | | 20001021 | 이상길 | 1975 | | 20041002 | 김유미 | 1983 | | 20041007 | 정인정 | 1983 | | 20041033 | 연개소문 | 1981 | | 20061011 | 박정인 | 1983 | 7 rows in set (0.01 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-13] V_OLD 테이블에서 학번이 20001001인 학생의 출생년도를 1986으로 변경하라. mysql> update v_old -> set birth_year = '1986' -> where stu_no = '20001001'; Query OK, 1 row affected (0.08 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select stu_no, stu_name, birth_year -> from v_old; +----------+----------+------------+ | stu_no | stu_name | birth_year | | 20001015 | 박도준 | 1978 | | 20001021 | 이상길 | 1975 | | 20041002 | 김유미 | 1983 | | 20041007 | 정인정 | 1983 | | 20041033 | 연개소문 | 1981 | | 20061011 | 박정인 | 1983 | 6 rows in set (0.00 sec) 뷰 테이블 V_OLD를 살펴보면 학번 20001001번은 1986으로 변경되어 뷰 처리시에서 지정한 조건을 만족하지 못하기 때문에 뷰 테이블 V_OLD에서 제거 2018-11-20 쉽게 배우는 MySQL 5.x
[실습 따라하기] [예제 18-13]에서 V_OLD 테이블의 20001001 학생의 출생년도를 1986으로 변경하였지만 실질적으로는 기본 테이블인 STUDENT 테이블이 변경되었으므로 데이터를 확인해 보자. mysql> select stu_no, stu_name, birth_year -> from student -> where stu_no = 20001001; +----------+----------+------------+ | stu_no | stu_name | birth_year | | 20001001 | 김유신 | 1986 | 1 row in set (0.00 sec) STUDENT 테이블에서 20001001번 학생의 BIRTH_YEAR가 1986으로 변경되어 있으므로 우선적으로 1981년으로 다시 변경해 준다. mysql> update student -> set birth_year = '1981' -> where stu_no = '20001001'; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-14] 학적테이블에서 1985년 이전에 출생한 모든 학생에 대한 뷰 테이블(V_OLD1)를 생성하라. mysql> create view v_old1 as -> select * from student -> where birth_year < 1985 -> with check option; Query OK, 0 rows affected (0.00 sec) 새롭게 생성된 V_OLD1 뷰 테이블을 확인해 보자. mysql> select stu_no, stu_name, birth_year -> from v_old1; +----------+----------+------------+ | stu_no | stu_name | birth_year | | 20001001 | 김유신 | 1981 | | 20001015 | 박도준 | 1978 | | 20001021 | 이상길 | 1975 | | 20041002 | 김유미 | 1983 | | 20041007 | 정인정 | 1983 | | 20041033 | 연개소문 | 1981 | | 20061011 | 박정인 | 1983 | 7 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-15] V_OLD1 테이블에서 학번이 20001001인 학생의 출생년도를 1986으로 변경하라. mysql> update v_old1 -> set birth_year = '1986' -> where stu_no = '20001001'; ERROR 1369 (HY000): CHECK OPTION failed 'haksa.v_old1' V_OLD1 뷰 테이블에서 20001001번의 BIRTH_YEAR을 1986으로 변경해 보면 오류 메시지를 출력하면서 변경작업을 할 수 없게 된다. 뷰가 WITH CHECK OPTION 절을 가지고 있다면 UPDATE와 INSERT 명령문과 같은 변경은 유효성을 검사한다. - 만약 변경된 행이 변경을 수행한 후에 뷰의 내용(가상 내용)에 아직 속해 있다면 UPDATE 명령문은 정확하게 처리된다. - 만약 새로운 행이 뷰의 내용(가상)에 포함된다면 INSERT 명령문은 정확하게 처리된다. 2018-11-20 쉽게 배우는 MySQL 5.x
18.4 뷰 테이블의 정보와 네비게이터 뷰 테이블의 정보 뷰 테이블 V_ADDRESS의 구조를 질의 18.4 뷰 테이블의 정보와 네비게이터 뷰 테이블의 정보 뷰 테이블 V_ADDRESS의 구조를 질의 mysql> desc v_address; +-------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | | hak | char(10) | NO | | NULL | | | irum | char(10) | NO | | NULL | | | hpost | varchar(3) | YES | | NULL | | 3 rows in set (0.00 sec) 뷰 테이블의 정보를 알아보기 위해 데이터베이스(information_schema)로 변경 mysql> use information_schema; Database changed 2018-11-20 쉽게 배우는 MySQL 5.x
뷰 테이블(views)의 칼럼(field)과 데이터 형(type) 정보를 알아보자. mysql> desc views; +-----------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | | TABLE_CATALOG | varchar(512) | YES | | NULL | | | TABLE_SCHEMA | varchar(64) | NO | | | | | TABLE_NAME | varchar(64) | NO | | | | | VIEW_DEFINITION | longtext | NO | | | | | CHECK_OPTION | varchar(8) | NO | | | | | IS_UPDATABLE | varchar(3) | NO | | | | | DEFINER | varchar(77) | NO | | | | | SECURITY_TYPE | varchar(7) | NO | | | | 8 rows in set (0.03 sec) [예제 18-16] VIEWS 테이블에서 뷰 테이블(V_OLD1)의 정보를 출력하라. mysql> select table_name, table_catalog -> from views -> where table_name = 'v_old1'; +------------+---------------+ | table_name | table_catalog | | v_old1 | NULL | 1 row in set (0.05 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
18.5 뷰 테이블 통계함수 사용 뷰 테이블을 WHERE 절에 통계함수 사용 18.5 뷰 테이블 통계함수 사용 뷰 테이블을 WHERE 절에 통계함수 사용 View 테이블을 사용하기 위해 학사 데이터베이스(haksa)로 변경 mysql> use haksa; Database changed [예제 18-17] 등록 테이블로부터 학번과 학생별 등록금 납입총액의 합계로 구성하는 뷰 테이블 (TOTALS)을 생성하라. mysql> create view totals -> (stu_no, fee_total) as -> select stu_no, sum(fee_pay) -> from fee -> group by stu_no; Query OK, 0 rows affected (0.09 sec) TOTALS 뷰 테이블을 내용 확인해 보자. mysql> select * from totals; +----------+-----------+ | stu_no | fee_total | | 20001015 | 5140000 | | 20061011 | 6720000 | | 20071001 | 6010000 | | 20071010 | 6000000 | | 20071022 | 6000000 | | 20071300 | 4010000 | | 20071307 | 6010000 | | 20071405 | 3500000 | | 20081001 | 3500000 | | 20081002 | 3500000 | 10 rows in set (0.03 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
SELECT 명령문의 SELECT 절에서 통계 함수를 사용할 수 있다. [예제 18-18] 뷰 테이블 (TOTALS)로부터 학생별 등록금 납입총액의 최대값을 구하여라. mysql> select max(fee_total) -> from totals; +----------------+ | max(fee_total) | | 6720000 | 1 row in set (0.00 sec) TOTALS 뷰를 SELECT 절에서 통계함수 “MAX( )”를 사용할 경우 명령문이 허용된다. 2018-11-20 쉽게 배우는 MySQL 5.x
GROUP BY절을 이용한 VIEW 테이블과 다른 테이블과 JOIN [예제 18-19] 뷰 테이블 (TOTALS)과 학적테이블을 이용하여 학번, 이름, 납입 총액을 출력하라. mysql> select s.stu_no, stu_name, fee_total -> from student s, totals t -> where s.stu_no = t.stu_no; +----------+----------+-----------+ | stu_no | stu_name | fee_total | | 20001015 | 박도준 | 5140000 | | 20061011 | 박정인 | 6720000 | | 20071001 | 장수인 | 6010000 | | 20071010 | 홍길동 | 6000000 | | 20071022 | 이순신 | 6000000 | | 20071300 | 유하나 | 4010000 | | 20071307 | 김문영 | 6010000 | | 20071405 | 최차영 | 3500000 | 8 rows in set (0.01 sec) 뷰 테이블 생성시 GROUP BY 절을 가지고 있다면 뷰는 또 다른 뷰나 테이블과 조인할 수 있다. 2018-11-20 쉽게 배우는 MySQL 5.x
WHERE 절에 다른 테이블을 부속질의어로 사용하는 경우 [예제 18-20] 수강 신청한 학생 중에 뷰 테이블 (TOTALS)에 존재하는 학생의 학번, 납입총액을 출력하라. mysql> select * from totals -> where stu_no in -> (select stu_no from attend); +----------+-----------+ | stu_no | fee_total | | 20061011 | 6720000 | | 20071300 | 4010000 | 2 rows in set (0.03 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
ORDER BY절을 사용하는 경우 [예제 18-21] 뷰 테이블 (TOTALS)에 존재하는 학생의 학번, 납입총액을 출력하라. 단, 출력 순서는 납입총액 내림차순으로 정렬한다. mysql> select * from totals -> order by fee_total desc; +----------+-----------+ | stu_no | fee_total | | 20061011 | 6720000 | | 20071001 | 6010000 | | 20071307 | 6010000 | | 20071010 | 6000000 | | 20071022 | 6000000 | | 20001015 | 5140000 | | 20071300 | 4010000 | | 20071405 | 3500000 | | 20081001 | 3500000 | | 20081002 | 3500000 | 10 rows in set (0.02 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
집합 연산자를 사용하는 경우 [예제 18-22] 뷰 테이블 (TOTALS)에 존재하는 학생의 학번과 동아리 테이블에 존재하는 학생의 학번을 학번 오름차순으로 정렬하여 출력하라. mysql> select stu_no from totals -> union -> select stu_no from circle -> order by stu_no; +----------+ | stu_no | | 20001015 | | 20001021 | | 20041007 | | 20061011 | | 20071001 | | 20071010 | | 20071022 | | 20071300 | | 20071307 | | 20071405 | | 20081001 | | 20081002 | 12 rows in set (0.03 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
HAVING절을 사용하는 경우 [예제 18-23] 수강신청 테이블에서 학생별, 수강년도별, 학기별로 그룹을 만들고 이 그룹의 수강신청 학점이 5학점 이상인 학생의 학번, 연도, 학기, 수강학점 계를 뷰 테이블 “V_SUGA”를 생성하라. mysql> create view v_suga(bunho, v_yy, v_hakgi, v_hakjum) as -> select stu_no, att_year, att_term, sum(att_point) -> from attend -> group by stu_no, att_year, att_term -> having sum(att_point) >= 5; Query OK, 0 rows affected (0.00 sec) 뷰 테이블 V_SUGA를 확인해 보자. mysql> select * from v_suga; +----------+------+---------+----------+ | bunho | v_yy | v_hakgi | v_hakjum | | 20061011 | 2006 | 1 | 18 | | 20061011 | 2006 | 2 | 18 | | 20071300 | 2007 | 1 | 18 | 3 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
18.6 뷰 테이블의 제약 사항 뷰 테이블을 변경할 때 UPDATE 명령문의 일반 칼럼은 변경이 가능하나 가상 열은 임의적으로 갱신할 수 없다. [예제 18-24] 뷰테이블 "V_SUGA"에서 2006년도의 해당학기를 4학기로 변경하여라. mysql> update v_suga -> set v_hakgi = 4 -> where v_yy = '2006'; ERROR 1288 (HY000): The target table v_suga of the UPDATE is not updatable 2018-11-20 쉽게 배우는 MySQL 5.x
18.7 뷰 명령문의 처리 -어떻게 SQL이 뷰를 접근하는 명령문을 처리하는가? 18.7 뷰 명령문의 처리 -어떻게 SQL이 뷰를 접근하는 명령문을 처리하는가? -기본 테이블에 적용된 것처럼 단계적으로 실행할 수 없다. -뷰는 저장된 행을 가지고 있지 않기 때문에 SQL은 여분의 처리 단계를 수행 -뷰 처리서가 명령문으로 포함된다. [예제18-25]적어도한번 이상 등록한 학생들을 학적테이블과 동일한 가상 테이블 “expensv”를 생성하라. mysql> create view expensv as -> select * from student -> where stu_no in -> (select stu_no -> from fee); Query OK, 0 rows affected (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제18-26]적어도 한번은 등록하고 남자인 학생의 학번과 이름을 출력하라. mysql> select stu_no, stu_name -> from expensv -> where substring(id_num, 8 ,1) = '1'; +----------+----------+ | stu_no | stu_name | | 20001015 | 박도준 | | 20061011 | 박정인 | | 20071001 | 장수인 | | 20071010 | 홍길동 | | 20071022 | 이순신 | 5 rows in set (0.00 sec) -첫 번째 처리 단계는 뷰 처리서를 SELECT 명령문으로 병합하여 포함 -다음과 같은 명령문은 동일한 결과 출력 mysql> select stu_no, stu_name -> from student -> where substring(id_num, 8 ,1) = '1' -> and stu_no in -> (select stu_no -> from fee); 2018-11-20 쉽게 배우는 MySQL 5.x
18.8 뷰의 응용 분야 다음과 같은 두 개의 명령문을 자주 입력한다고 하자. 18.8 뷰의 응용 분야 다음과 같은 두 개의 명령문을 자주 입력한다고 하자. ① 학급 3반에서 등록한 학생의 학번과 반을 출력하라. mysql> select stu_no, class -> from student -> where stu_no in -> (select stu_no -> from fee) -> and class = 3; +----------+-------+ | stu_no | class | | 20071010 | 3 | | 20071022 | 3 | | 20071307 | 3 | 3 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
② 학급별로 등록한 학생의 학급 통계를 출력하라. mysql> select class, count(*) -> from student -> where stu_no in -> (select stu_no -> from fee) -> group by class; +-------+----------+ | class | count(*) | | 1 | 4 | | 2 | 1 | | 3 | 3 | 3 rows in set (0.00 sec) [예제 18-27] 등록한 학생의 학번과 반으로 구성되는 뷰 테이블 “student_cnt”를 생성하라. mysql> create view student_cnt as -> select stu_no, class -> from fee); 2018-11-20 쉽게 배우는 MySQL 5.x
①② 번의 SELECT 명령문은 STUDENT_CNT 뷰를 사용하여 아주 간단하게 할 수 있다. mysql> select * -> from student_cnt -> where class = 3; +----------+-------+ | stu_no | class | | 20071010 | 3 | | 20071022 | 3 | | 20071307 | 3 | 3 rows in set (0.00 sec) mysql> select class, count(*) -> group by class; +-------+----------+ | class | count(*) | | 1 | 4 | | 2 | 1 | | 3 | 3 | 2018-11-20 쉽게 배우는 MySQL 5.x
-데이터베이스 구조의 재구성은 시간이 필요할 뿐만 아니라 비용이 많이 든다 -데이터베이스 구조의 재구성은 시간이 필요할 뿐만 아니라 비용이 많이 든다. -뷰의 적절한 사용은 시간과 비용을 최소화할 수 있도록 한다. [예제 18-28] 재학생 중 수강신청 연도, 학기와 등록년도, 학기가 동일한 학생의 학번과 이름, 수강년도, 수강학기를 출력하라. mysql> select distinct s.stu_no, stu_name, att_year, att_term -> from student s, fee f, attend a -> where s.stu_no = f.stu_no -> and f.stu_no = a.stu_no -> and f.fee_year = a.att_year -> and f.fee_term = a.att_term; +----------+----------+----------+----------+ | stu_no | stu_name | att_year | att_term | | 20061011 | 박정인 | 2006 | 1 | | 20061011 | 박정인 | 2006 | 2 | | 20071300 | 유하나 | 2007 | 1 | 3 rows in set (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
[예제 18-29] 재학생 중 2006년에 수강 신청을 했으며 2006년에 등록한 학생의 평균 등록금보다 더 많은 등록금을 납부해야 하고,성별이 남자인 학생의 학번과 이름을 출력하라. (위의 예제는 아주 긴 SELECT 명령문을 작성해야 하므로 단계적으로 질의어를 구성한다. 먼저 2006년에 등록한 학생의 평균 등록금 보다 많고, 적어도 한 번 등록을 한 학생에 대한 뷰를 생성해야 한다.) mysql> create view greater as -> select distinct stu_no -> from fee -> where fee_total > -> (select avg(fee_total) -> where fee_year = '2006'); Query OK, 0 rows affected (0.03 sec) 2006년에 수강신청을 한 모든 학생에 대한 뷰를 생성 mysql> create view first as -> from attend -> where stu_no in -> (select stu_no -> where att_year = '2006'); Query OK, 0 rows affected (0.00 sec) 2018-11-20 쉽게 배우는 MySQL 5.x
두 개의 뷰를 사용하면 원래의 질문에 대한 응답은 상당히 단순화 된다. mysql> select stu_no, stu_name -> from student -> where substring(id_num, 8 ,1) = '1' -> and stu_no in -> (select stu_no -> from greater) -> from first); +----------+----------+ | stu_no | stu_name | | 20061011 | 박정인 | 1 row in set (0.00 sec) -문제를 작은 크기의 문제로 나누고 단계적으로 실행 -원한다면 하나의 긴 명령문으로 구성 가능 2018-11-20 쉽게 배우는 MySQL 5.x