20230330 SQL
▶ 제약조건 다섯 가지
PRIMARY KEY
FOREIGN KEY
UNIQUE
CHECK
NOT NULL
-- 이렇게 다섯 개임. 이 외 업무별 제약 조건은 TRIGGER를 이용해서 만듦
<차례>
❍ 제약조건 삭제
❍ UNIQUE 제약조건
❍ CHECK 제약조건
❍ NOT NULL 제약조건
■ 테이블 생성시 제약조건 함께 생성
■ 테이블 이름 수정
■ 컬럼 이름 수정
■ 제약조건 이름 수정
■ 인덱스 이름 수정
■ FLASHBACK TABLE
❍ 삭제한 테이블 복원
● 제약조건 이름 수정
● 인덱스 이름 수정
■ TRUNCATE
■ COMMENT
❍ 테이블 주석 확인/생성/삭제
❍ 컬럼 주석 확인/생성/삭제
■ VIEW
CTAS 만드는 것과 같음
● VIEW인지 TABLE인지 여부 확인 방법
❍ VIEW를 삭제하는 방법
❍ VIEW를 수정하는 방법
❍ VIEW에 신규 데이터 INSERT 하기
❍ VIEW에 신규 데이터 UPDATE 하기
❍ VIEW에 신규 데이터 DELETE 하기
■ 단순 VIEW
■ 복합 VIEW
DROP TABLE hr.emp CASCADE CONSTRAINT PURGE;
DROP TABLE hr.dept CASCADE CONSTRAINT PURGE;
=> 나를 참조하는 foreign key 제약조건 삭제하고 drop 하겠음
(제약 조건 없는 테이블 삭제시에도 사용 가능)
CREATE TABLE hr.emp(id number, name varchar2(30), day date, dept_id number);
ALTER TABLE hr.emp ADD constraint emp_id_pk PRIMARY KEY(id);
SELECT*FROM user_constraints;
SELECT*FROM user_constraints WHERE table_name = 'EMP';
SELECT*FROM user_cons_columns WHERE table_name = 'EMP';
SELECT*FROM user_indexes WHERE table_name = 'EMP';
SELECT*FROM user_ind_columns WHERE table_name = 'EMP';
CREATE TABLE hr.dept(dept_id number, dept_name varchar2(30));
ALTER TABLE hr.dept ADD CONSTRAINT dept_id_pk PRIMARY KEY(dept_id); -> 못 만듦
ALTER TABLE hr.dept ADD CONSTRAINT dept_dept_id_pk PRIMARY KEY(dept_id);
ALTER TABLE hr.emp ADD CONSTRAINT emp_dept_id_fk
FOREIGN KEY(dept_id) REFERENCES hr.dept(dept_id);
SELECT*FROM user_constraints WHERE table_name IN ('EMP','DEPT');
SELECT*FROM user_cons_columns WHERE table_name IN ('EMP','DEPT');
SELECT*FROM user_indexes WHERE table_name IN ('EMP','DEPT');
SELECT*FROM user_ind_columns WHERE table_name IN ('EMP','DEPT');
--- foreign key는 primary key, unique key를 참조하는 제약조건
1) 다른 범위의 값 입력하는 것 방지(데이터 품질 굿)
2) 참조 대상인 pk 삭제되지 않도록 방지
INSERT INTO hr.dept(dept_id, dept_name) VALUES(10, '총무부');
INSERT INTO hr.dept(dept_id, dept_name) VALUES(20, '분석팀');
COMMIT;
INSERT INTO hr.emp(id, name, day, dept_id) VALUES(1, '홍길동', sysdate, 10);
INSERT INTO hr.emp(id, name, day, dept_id) VALUES(1, '나얼', sysdate, 10); -> 안돼
오류 보고 -
ORA-00001: unique constraint (HR.EMP_ID_PK) violated
INSERT INTO hr.emp(id, name, day, dept_id) VALUES(2, '나얼', sysdate, 30); -> 안돼
오류 보고 -
ORA-02291: integrity constraint (HR.EMP_DEPT_ID_FK) violated - parent key not found
5-6 텍스트 마이닝
5-7 머신러닝 딥러닝
8 R
9 최종 프로젝트
[도서] 데이터 품질 — 90년도 발간
INSERT INTO hr.emp(id, name, day, dept_id) VALUES(2, '나얼', sysdate, NULL);
1 행 이(가) 삽입되었습니다. => NULL, 중복값 허용
--- foreign key 제약조건에는 index 안 걸림
--- 데이터가 있을 때 pk를 걸기 어려울 수 있음(모든 값이 unique 해야 함)
❍ 제약조건 삭제
ALTER TABLE hr.emp DROP CONSTRAINT emp_id_pk; - 다른 제약조건 삭제시 이름 명시
ALTER TABLE hr.emp DROP PRIMARY KEY; --- pk 제약조건 삭제시 사용
ALTER TABLE hr.dept DROP PRIMARY KEY; --- 오류남
오류 보고 -
ORA-02273: this unique/primary key is referenced by some foreign keys
02273. 00000 - "this unique/primary key is referenced by some foreign keys"
Cause: Self-evident.
Action: Remove all references to the key before the key is to be dropped.
=> 나를 참조하고 있는 foreign key 제약조건이 있어서 오류 발생
해결방법 1)
ALTER TABLE hr.emp DROP CONSTRAINT emp_dept_id_fk;
--- 나를 참조하는 fk 제약조건 삭제
ALTER TABLE hr.dept DROP PRIMARY KEY;
해결방법 2)
ALTER TABLE hr.dept DROP PRIMARY KEY CASCADE;
--- CASCADE 옵션을 사용하면 나를 참조하는 제약조건을 모두 삭제한 후 제약조건 삭제
❍ UNIQUE 제약조건 --- (실 예)중복 아이디 체크
SELECT*FROM hr.dept;
ALTER TABLE hr.dept ADD CONSTRAINT dept_name_uk UNIQUE(dept_name);
INSERT INTO hr.dept(dept_id, dept_name) VALUES(30, '분석팀'); --- 오류 나옴, uk 위반
오류 보고 -
ORA-00001: unique constraint (HR.DEPT_NAME_UK) violated
INSERT INTO hr.dept(dept_id, dept_name) VALUES(30, NULL); --- uk NULL은 허용
■ UNIQUE 제약조건 삭제하는 방법
ALTER TABLE hr.dept DROP CONSTRAINT dept_name_uk;
또 는
ALTER TABLE hr.dept DROP UNIQUE(dept_name);
❍ CHECK 제약조건
ALTER TABLE hr.emp ADD sal NUMBER;
desc hr.emp;
SELECT*FROM hr.emp;
ALTER TABLE hr.emp ADD CONSTRAINT emp_sal_ck CHECK(sal >= 1000 AND sal <= 2000);
또 는
ALTER TABLE hr.emp ADD CONSTRAINT emp_sal_ck CHECK(sal BETWEEN 1000 AND 2000);
INSERT INTO hr.emp(id, name, day, dept_id, sal) VALUES(3, '윤건', sysdate, 20, 500);
오류 보고 -
ORA-02290: check constraint (HR.EMP_SAL_CK) violated
--- CHECK 제약조건에 조건식의 결과값이 false이기 때문에 오류 발생
INSERT INTO hr.emp(id, name, day, dept_id, sal) VALUES(3, '윤건', sysdate, 20, NULL);
--- CHECK 제약조건은 NULL값을 허용함
INSERT INTO hr.emp(id, name, day, dept_id, sal) VALUES(3, '윤건', sysdate, 20, 1500);
1 행 이(가) 삽입되었습니다.
UPDATE hr.emp
SET sal = 500
WHERE id = 1;
오류 보고 -
ORA-02290: check constraint (HR.EMP_SAL_CK) violated
■ CHECK 제약조건 삭제하는 방법
ALTER TABLE hr.emp DROP CONSTRAINT emp_sal_ck;
SELECT*FROM user_constraints WHERE table_name IN ('EMP','DEPT');
❍ NOT NULL 제약조건
SELECT*FROM user_constraints WHERE table_name IN ('EMP','DEPT');
desc hr.emp;
ALTER TABLE hr.dept MODIFY dept_name CONSTRAINT dept_name_notnull NOT NULL;
SELECT*FROM user_constraint WHERE table_name IN ('EMP', 'DEPT');
DESC hr.dept
SELECT*FROM hr.dept;
INSERT INTO hr.dept(dept_id, dept_name) VALUES (30, NULL); -- 오류
오류 보고 -
ORA-01400: cannot insert NULL into ("HR"."DEPT"."DEPT_NAME")
INSERT INTO hr.dept(dept_id, dept_name) VALUES (30, '총무부'); -- 수행됨
ROLLBACK;
ALTER TABLE hr.dept ADD CONSTRAINT dept_name_uk UNIQUE(dept_name);
INSERT INTO hr.dept(dept_id, dept_name) VALUES (30, '총무부');
오류 보고 -
ORA-00001: unique constraint (HR.DEPT_NAME_UK) violated
=> dept_name 컬럼의 NOT NULL, UNIQUE 제약조건이 생성되어 있어서 NULL값 또는 중복되는 값이 입력되면 오류 발생
■ NOT NULL 제약조건 삭제하는 방법
SELECT*FROM user_constraints WHERE table_name IN ('EMP', 'DEPT');
ALTER TABLE hr.dept DROP CONSTRAINT dept_name_notnull;
또 는
ALTER TABLE hr.dept MODIFY dept_name NULL;
DROP TABLE hr.emp CASCADE CONSTRAINT PURGE;
DROP TABLE hr.dept CASCADE CONSTRAINT PURGE;
■ 테이블 생성시 제약조건 함께 생성
CREATE TABLE hr.dept
(dept_id number CONSTRAINT dept_dept_id_pk PRIMARY KEY,
dept_name varchar2(30));
CREATE TABLE hr.emp(
id number CONSTRAINT emp_id_pk PRIMARY KEY, -- 열 레벨 정의
name varchar(30) CONSTRAINT emp_name_nn NOT NULL,
sal number,
dept_id number CONSTRAINT emp_dept_id_fk REFERENCES hr.dept(dept_id),
CONSTRAINT emp_name_uk UNIQUE(name), -- 테이블 레벨 정의
CONSTRAINT emp_sal_ck CHECK(sal BETWEEN 1000 AND 2000));
--- NOT NULL 제약조건은 열 레벨 정의만 가능
DROP TABLE hr.emp CASCADE CONSTRAINT PURGE;
● id number PRIMARY KEY를 열 레벨 -> 테이블 레벨 정의로 내리고 싶음
CREATE TABLE hr.emp(
id number,
name varchar(30) CONSTRAINT emp_name_nn NOT NULL,
sal number,
dept_id number CONSTRAINT emp_dept_id_fk REFERENCES hr.dept(dept_id),
CONSTRAINT emp_id_pk PRIMARY KEY(id),
CONSTRAINT emp_name_uk UNIQUE(name),
CONSTRAINT emp_sal_ck CHECK(sal BETWEEN 1000 AND 2000));
● dept_id number FOREIGN KEY를 열 레벨 -> 테이블 레벨 정의로 내리고 싶음
--- 이 경우 CONSTRAINT ... FOREIGN KEY ... REFERENCES 로 작성
--- 열 레벨 정의: FOREIGN KEY 작성X, 테이블 레벨 정의: FOREIGN KEY 작성O
CREATE TABLE hr.emp(
id number,
name varchar(30) CONSTRAINT emp_name_nn NOT NULL,
sal number,
dept_id number,
CONSTRAINT emp_id_pk PRIMARY KEY(id),
CONSTRAINT emp_name_uk UNIQUE(name),
CONSTRAINT emp_sal_ck CHECK(sal BETWEEN 1000 AND 2000),
CONSTRAINT emp_dept_id_fk FOREIGN KEY(dept_id) REFERENCES hr.dept(dept_id));
언니 이거 키보드 가져온??? ~
아니야아아아 키보드 파업!!
■ 테이블 이름 수정
1) RENAME 기존 이름 TO 새로운 이름;
2) ALTER TABLE 기존 이름 RENAME TO 새로운 이름;
(테이블 만들기)
INSERT INTO hr.dept(dept_id, dept_name) VALUES (10, '총무부');
INSERT INTO hr.dept(dept_id, dept_name) VALUES (20, '분석팀');
COMMIT;
SELECT*FROM hr.dept;
INSERT INTO hr.emp(id, name, sal, dept_id) VALUES(1, '홍길동', 2000, 10);
INSERT INTO hr.emp(id, name, sal, dept_id) VALUES(2, '나얼', 1000, 20);
COMMIT;
SELECT*FROM hr.emp;
RENAME hr.emp to hr.emp_new; -- 오류(소유자 이름은 사용할 수 없음)
오류 보고 -
ORA-01765: specifying owner's name of the table is not allowed
((방법 1))
RENAME emp TO emp_new; -- 테이블 이름이 변경되었습니다.
SELECT*FROM emp_new;
SELECT*FROM user_tables WHERE table_name = 'EMP_NEW';
SELECT*FROM user_constraints WHERE table_name = 'EMP_NEW';
SELECT*FROM user_cons_columns WHERE table_name = 'EMP_NEW';
SELECT*FROM user_indexes WHERE table_name = 'EMP_NEW';
SELECT*FROM user_ind_columns WHERE table_name = 'EMP_NEW';
((방법 2))
ALTER TABLE emp_new RENAME TO emp;
SELECT*FROM hr.emp;
SELECT*FROM user_tables WHERE table_name = 'EMP';
SELECT*FROM user_constraints WHERE table_name = 'EMP';
SELECT*FROM user_cons_columns WHERE table_name = 'EMP';
SELECT*FROM user_indexes WHERE table_name = 'EMP';
SELECT*FROM user_ind_columns WHERE table_name = 'EMP';
■ 컬럼 이름 수정
DESC hr.emp
ALTER TABLE hr.emp RENAME COLUMN id TO emp_id;
■ 제약조건 이름 수정
ALTER TABLE hr.emp RENAME CONSTRAINT emp_id_pk TO emp_empid_pk;
■ 인덱스 이름 수정
ALTER INDEX emp_id_pk RENAME TO emp_id_idx;
SELECT*FROM user_indexes WHERE table_name = 'EMP';
SELECT*FROM user_ind_columns WHERE table_name = 'EMP';
■ FLASHBACK TABLE --- 휴지통 같은 기능
SHOW recyclebin; -> 내용 없으면 오류 나는 듯?
-> SP2-0564: "" 객체가 부적합합니다. 설명되지 않을 수 있습니다.
SELECT*FROM user_recyclebin; -> 3개 나옴
PURGE recyclebin; -> 휴지통 비우기, Recyclebin이(가) 비워졌습니다.
CREATE TABLE hr.emp_copy
AS
SELECT*FROM hr.employees;
SELECT*FROM user_objects WHERE object_name = 'EMP_COPY';
-> LAST_DDL_TIME, TIMESTAMP 마지막 객체 수정 날짜, 날짜/시간 확인 가능
DROP TABLE hr.emp_copy; -> 아차, 잘못 드랍을 한거예요 여러분
-> 삭제한 경우 위치 그대로(우리 눈엔 안보임), 이름을 BIN$로 변경
SELECT*FROM user_recyclebin; -> 걱정할게 없어요. 쓰레기통 확인
▽▽▽(결과창)
BIN$Sp5AWYnAThyP8NZT/OOkAQ==$0 EMP_COPY DROP TABLE USERS 2023-03-30:13:55:40 2023-03-30:13:57:42 567620 YES YES 20382 20382 20382 8
SELECT*FROM user_tables WHERE table_name = 'EMP_COPY';
SELECT*FROM user_objects WHERE object_name = 'EMP_COPY';
--> 둘다 아무것도 없음(휴지통에 넣었기 때문)
SELECT*FROM "BIN$Sp5AWYnAThyP8NZT/OOkAQ==$0";
-> 휴지통 속 이름으로 데이터 확인 가능(BIN& 시작 이름 쌍따옴표 안에 입력해줘야 함)
[메모]
CTAS 테이블 복제한 경우 테이블 구조, 데이터 그대로 & 제약조건은 not null 제약조건만 복제됨
❍ 삭제한 테이블 복원
FLASHBACK TABLE emp_copy TO BEFORE DROP;
SELECT*FROM user_recyclebin; --> 암것도 없음
ALTER TABLE hr.emp_copy RENAME CONSTRAINT "BIN$vrDh3UQeTMqv9+XEJPT33A==$0" TO emp_copy_name_nn; --> 제약조건 이름 변경
DROP TABLE hr.emp_copy PURGE;
=> purge : 영구히 테이블 삭제(recyclebin으로 들어가지 않음, 복원 불가)
(( 다시 hr.emp_copy 테이블 만들기))
CREATE TABLE hr.emp_copy
AS
SELECT*FROM hr.employees;
ALTER TABLE hr.emp_copy ADD CONSTRAINT emp_copy_id_pk PRIMARY KEY(employee_id);
SELECTFROM user_constraints WHERE table_name = 'EMP_COPY';
SELECTFROM user_cons_columns WHERE table_name = 'EMP_COPY';
SELECTFROM user_indexes WHERE table_name = 'EMP_COPY';
SELECTFROM user_ind_columns WHERE table_name = 'EMP_COPY';
purge recyclebin; --> 반복 버리기 수행 중!
DROP TABLE hr.emp_copy;
SELECT*FROM user_recyclebin;
CREATE TABLE hr.emp_copy
AS
SELECT*FROM hr.employees;
DROP TABLE hr.emp_copy; --> 또 버림!
SELECT*FROM user_recyclebin; --> 휴지통 또 확인함!
FLASHBACK TABLE hr.emp_copy TO BEFORE DROP;
Flashback을(를) 성공했습니다.
SELECT*FROM user_recyclebin; --> 복원된 것 확인 가능
----- ----- 무언가 잘못했다, INDEX가 없다!!! 하지만 갠춘 ----- -----
● 제약조건 이름 수정
ALTER TABLE hr.emp_copy RENAME CONSTRAINT “BIN$Ixigkt2DR36JjsshpjI+JQ==$0” TO emp_copy_id_pk;
● 인덱스 이름 수정
ALTER INDEX “BIN$Ixigkt2DR36JjsshpjI+JQ==$0” RENAME TO emp_copy_id_idx;
■ 계속되는 드랍과 생성, 휴지통 상태는?!
SELECT*FROM hr.emp_copy;
SELECT*FROM user_recyclebin;
purge recyclebin;
SELECT*FROM hr.emp_copy;
DROP TABLE hr.emp_copy;
CREATE TABLE hr.emp_copy
AS
SELECT*FROM hr.employees;
SELECT*FROM hr.emp_copy;
DROP TABLE hr.emp_copy;
SELECT*FROM recyclebin;
▽▽▽ (결과창)
BINz46uIcpoRHmFpNvyvDs7kg==$0 EMP_COPY DROP TABLE USERS 2023-03-30:14:16:24 2023-03-30:14:26:51 BINdFhAiNdqTMuloboHve3hBA==T+ItvIrfT4yg0IX4Vx2frg==$0 EMP_COPY DROP TABLE USERS 2023-03-30:14:30:03 2023-03-30:14:30:05
FLASHBACK TABLE hr.emp_copy TO BEFORE DROP;
-> Flashback을(를) 성공했습니다.
(recyclebin에 동일한 이름의 테이블이 있을 경우 가장 최근에 삭제된 테이블을 복원)
FLASHBACK TABLE hr.emp_copy TO BEFORE DROP;
오류 보고 -
ORA-38312: original name is used by an existing object
->> hr.emp_copy 이름으로 이미 복원해서 복원 못 함
->> 복원해야할 테이블이 이미 존재하는 경우 이름을 수정해서 복원해야 함
FLASHBACK TABLE hr.emp_copy TO BEFORE DROP RENAME TO emp_2023;
-> Flashback을(를) 성공했습니다.
-> flashback table 유료 기능임(license 없는데 사용하면 딕셔너리에 저장, 쓰지 말라고 함)
SELECT*FROM hr.emp_2023; -> 데이터 있음!!
[메모]
--index는 따로 복원하지 않음/ 테이블 복원시 자동 복원(복원 후 이름 바꿔야 함)
■ TRUNCATE
DELETE FROM hr.emp_2023;
--> 수천만 건의 데이터는 어디로 갔나?
-->> 행을 삭제(혹은 UPDATE) 하면 UNDO TABLESPACE에 저장을 함
(이유: ROLLBACK, 읽기 일관성을 위해서 이전값은 저장함)
SELEC\T*FROM hr.emp_2023;
ROLLBACK;
TRUNCATE TABLE hr.emp_2023;
-> Table HR.EMP_2023이(가) 잘렸습니다.
SELECT*FROM hr.emp_2023; -- 데이터 없음
rollback; -- truncate 문은 테이블을 초기화 상태로 만들기 때문에 rollback 불가함
SELECT*FROM hr.emp_2023; -- 데이터 없음
● 80% 버리고 20%만 남기고 싶다면?
-->>>20% 데이터 해당 테이블 생성, rename + 제약조건(not null 이외) 생성 후 기존 테이블 삭제
■ COMMENT
❍ 테이블 주석 확인
SELECT*FROM user_tab_comments WHERE table_name = 'EMP_2023';
❍ 테이블 주석 생성
COMMENT ON TABLE hr.emp_2023 IS '사원정보테이블';
▽▽▽ (결과창)
EMP_2023 TABLE 사원정보테이블
❍ 테이블 주석 삭제
COMMENT ON TABLE hr.emp_2023 IS ‘’; -> 이거 왜 안댕(해결됨: sqld 작따)
❍ 컬럼 주석 확인
SELECT*FROM user_col_comments WHERE table_name = 'EMP_2023';
❍ 컬럼 주석 생성
COMMENT ON COLUMN hr.emp_2023.employee_id IS '사원번호';
SELECT*FROM user_col_comments WHERE table_name = 'EMP_2023';
❍ 컬럼 주석 삭제
COMMENT ON COLUMN hr.emp_2023.employee_id IS ‘’;
● 분석할 테이블, 컬럼의 주석 내용 먼저 확인하기!
SELECT*FROM user_tab_comments WHERE table_name = 'EMPLOYEES';
SELECT*FROM user_col_comments WHERE table_name = 'EMPLOYEES';
■ VIEW --- 현장에서 쓰임이 많음
==== 안 괜찮은 방법 ====
((hr))
SELECT*FROM hr.employees;
SELECT*FROM user_tab_privs;
REVOKE SELECT ON hr.employees FROM insa; -- insa의 접속 권한 회수
REVOKE ALL ON hr.emp_20 FROM insa; -- insa의 모든 객체 권한 회수
SELECT*FROM user_tab_privs;
SELECT employee_id, last_name, first_name, job_id, department_id
FROM hr.employees;
--> insa는 다른 정보 외에 해당 정보만 볼 수 있어야 함
CREATE TABLE hr.emp_insa -- 새로운 테이블 생성
AS
SELECT employee_id, last_name, first_name, job_id, department_id
FROM hr.employees;
SELECT*FROM hr.emp_insa;
GRANT SELECT ON hr.emp_insa TO insa;
SELECT*FROM user_tab_privs;
((insa))
SELECT*FROM user_tab_privs;
((hr))
DROP TABLE hr.emp_insa PURGE; -- 테이블 삭제시 권한 부여 자동 삭제
● hr.employees 테이블 중 일부만 복제한 테이블을 insa에게 권한 부여시 문제점
1) 원본 테이블 업데이트가 복제 테이블에 반영되지 않음(sync 안 맞음, 두 개 테이블 유지, 관리 비용 큼)
2) 데이터 양이 너무 많음
======================
CREATE VIEW 뷰 이름
AS
SELECT -- 서브쿼리
FROM
CREATE VIEW hr.emp_insa
AS
SELECT employee_id, last_name, first_name, job_id, department_id
FROM hr.employees;
SELECT*FROM hr.emp_insa;
GRANT SELECT ON hr.emp_insa TO insa;
SELECT*FROM user_tab_privs;
-->> 직접 이 table을 보면 안 돼, 간접 access 지원
● VIEW인지 TABLE인지 여부 확인 방법
1) SELECT*FROM user_objects WHERE object_name = 'EMP_INSA';
▽▽▽(결과창)
object_type
EMP_INSA 20390 VIEW 23/03/30 23/03/30 2023-03-30:15:40:00
2) SELECT*FROM user_views WHERE view_name = 'EMP_INSA';
▽▽▽(결과창)
TEXT
EMP_INSA 82 "SELECT employee_id, last_name, first_name, job_id, department_id
FROM hr.employees“
-> 이것을 불러?
->> 이렇게 view는 select문만 가지고 있음
[문제103] 부서이름별 총액 급여, 평균 급여를 access하는 dept_sum_sal 뷰를 생성한 후 insa 유저에서 dept_sum_sal 뷰를 SELECT할 수 있는 권한을 부여해 주세요.
((hr 창에서 create view, grant select 수행))
CREATE VIEW dept_sum_sal -- hr. 앞에 붙여도 되고 안해도 됨
AS
SELECT d.department_name dept_name, sum(e.salary) sumsal, round(avg(e.salary)) avgsal
FROM hr.employees e, hr.departments d
WHERE e.department_id = d.department_id
GROUP BY department_name;
GRANT SELECT ON dept_sum_sal TO insa;
((insa 창에서 확인))
SELECT*FROM user_tab_privs;
SELECT*FROM hr.dept_sum_sal; --> 내가 한 것, 이거 안 좋음
((hr 창에서 수행))
CREATE VIEW dept_sum_sal2
AS
SELECT d.department_name, sum_sal, avg_sal
FROM (SELECT department_id, sum(salary) sum_sal, round(avg(salary)) avg_sal
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;
--> 이게 좋음, create view할 때는 inline view SELECT문에 열 별칭 필수!!!
-->> 그룹함수, 계산 등 이루어졌을 때 열 별칭 붙이는 습관 가지기!!!
-->>> 컬럼 이름에 괄호 들어갈 수 없음!!
((잘못된 예시1))
SELECT d.department_name, sum(salary), round(avg(salary))
FROM (SELECT department_id, sum(salary), round(avg(salary))
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;
===>>> 오류 발생 : ORA-00904: "SALARY": invalid identifier
00904. 00000 - "%s: invalid identifier"
((잘못된 예시2))
CREATE VIEW dept_sum_sal
AS
SELECT d.department_name, e.*
FROM (SELECT department_id, sum(salary), round(avg(salary))
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;
SELECT*FROM dept_sum_sal; --> 컬럼 안 예쁨 괄호도 많고
SELECT*FROM user_views WHERE view_name = 'DEPT_SUM_SAL2';
GRANT SELECT ON dept_sum_sal2 TO insa;
((insa))
SELECT*FROM hr.dept_sum_sal2;
❍ VIEW를 삭제하는 방법
DROP VIEW dept_sum_sal; --> 권한 부여한 경우 권한도 같이 삭제됨
❍ VIEW를 수정하는 방법
CREATE OR REPLACE VIEW dept_sum_sal
AS
SELECT d.department_name 부서이름, sum_sal 총액급여, avg_sal 평균급여
FROM (SELECT department_id, sum(salary) sum_sal, round(avg(salary)) avg_sal
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;
또 는
CREATE OR REPLACE VIEW dept_sum_sal
(부서이름, 총액급여, 평균급여)
AS
SELECT d.department_name, sum_sal, avg_sal
FROM (SELECT department_id, sum(salary) sum_sal, round(avg(salary)) avg_sal
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;
---> View DEPT_SUM_SAL이(가) 생성되었습니다.
SELECT*FROM dept_sum_sal; --> 열 별칭 변경사항 저장됨
❍ VIEW에 신규 데이터 INSERT 하기
(((샘플 테이블 만들 것임)))
((hr))
DROP TABLE hr.test PURGE;
-> 없으면 오류, 있으면 “Table HR.TEST이(가) 삭제되었습니다.”
CREATE TABLE hr.test
AS
SELECT employee_id id, last_name name, salary sal
FROM hr.employees
WHERE department_id = 20;
Table HR.TEST이(가) 생성되었습니다.
SELECT*FROM hr.test;
CREATE OR REPLACE VIEW test_view
AS
SELECT *
FROM hr.test;
View TEST_VIEW이(가) 생성되었습니다.
SELECT*FROM hr.test_view; --> SELECT*FROM hr.test; 이거랑 결과창 동일
INSERT INTO hr.test_view(id,name,sal) VALUES(300,'홍길동',1000);
1 행 이(가) 삽입되었습니다.
commit;
SELECT*FROM hr.test_view;
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
GRANT SELECT, INSERT, UPDATE, DELETE ON hr.test_view TO insa; --다 줘야 함
--> insa에서 사용할 수 있도록
Grant을(를) 성공했습니다.
((insa))
SELECT*FROM user_tab_privs;
SELECT*FROM hr.test_view; -> view가 참조하는 테이블 꼭 쓰기!!
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
INSERT INTO hr.test_view(id,name,sal) VALUES(400,'윤건',5000)
1 행 이(가) 삽입되었습니다.
SELECT*FROM hr.test_view;
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
400 윤건 5000
((hr))
SELECT*FROM hr.test_view; --> insa에서 방금 작업한 것 반영X
SELECT*FROM hr.test; 아직 transaction 진행중이기 때문임
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
((insa))
commit;
커밋 완료.
((hr))
SELECT*FROM hr.test_view; --> insa에서 방금 작업한 것 반영O
SELECT*FROM hr.test;
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
400 윤건 5000
❍ VIEW에 신규 데이터 UPDATE 하기
((insa))
UPDATE hr.test_view
SET sal = 10000
WHERE id = 400;
1 행 이(가) 업데이트되었습니다.
commit;
커밋 완료.
((hr))
SELECT*FROM hr.test;
SELECT*FROM hr.test_view; --> insa에서 방금 작업한 것 반영O
201 Hartstein 13000
202 Fay 6000
300 홍길동 1000
400 윤건 10000
❍ VIEW에 신규 데이터 DELETE 하기
((insa))
DELETE FROM hr.test_view WHERE id = 201;
1 행 이(가) 삭제되었습니다.
commit;
커밋 완료.
((hr))
SELECT*FROM hr.test;
SELECT*FROM hr.test_view; --> insa에서 방금 작업한 것 반영O
■ 단순 VIEW
((예시))
CREATE OR REPLACE VIEW test_view
AS
SELECT *
FROM hr.test;
■ 복합 VIEW
((예시))
CREATE VIEW dept_sum_sal2
AS
SELECT d.department_name, sum_sal, avg_sal
FROM (SELECT department_id, sum(salary) sum_sal, round(avg(salary)) avg_sal
FROM hr.employees
GROUP BY department_id) e, hr.departments d
WHERE e.department_id = d.department_id;