127.
TRIGGER
특정 테이블에 INSERT, UPDATE, DELETE 와 같은 DML문이 수행되었을 때,
데이터베이스에서 자동으로 동작하도록 작성된 저장 프로그램
(사용자가 직접 호출해서 사용하는 것이 아니고 데이터 베이스에서 자동적으로 수행함)
126.
Trigger에 대한 설명
- Trigger는 데이터베이스에 의해서 자동으로 호출되고 수행된다.
- Trigger는 특정 테이블에서 INSERT, UPDATE, DELETE 문이 수행되었을 때 호출되도록 정의할 수 있다.
- Trigger는 Procedure와 달리 Commit, Rollback 과 같은 TCL을 사용할 수 없다.
- Trigger는 데이터베이스에 로그인하는 작업에도 정의할 수 있다.
125.
절차형 SQL 모듈에 대한 설명
- 저장형 프로시져는 SQL을 로직과 함께 데이터베이스 내에 저장해 놓은 명령문의 집합을 의미한다.
- 저장형 함수(사용자 정의 함수)는 단독적으로 실행되기 보다는 다른 SQL문을 통하여 호출되고,
그 결과를 리턴하는 SQL의 보조적인 역할을 한다.
- 트리거는 특정한 테이블에 INSERT, UPDATE, DELETE와 같은 DML문이 수행되었을 때
데이터베이스에서 자동으로 동작하도록 작성된 프로그램이다.
* 데이터의 무결성과 일관성을 위해 사용자 정의 함수를 사용하는것은 트리거의 용도 이다.
124.
임시부서(TMP_DEPT) 테이블로부터 부서(DEPT) 테이블에 데이터를 입력하는 PL/SQL
조건: 부서 테이블에 데이터를 입력하기 전, 부서테이블의 모든 데이터를 ROLLBACK이 불가능하도록 삭제가 필요하다.
[PL/SQL]
create or replace procedure insert_dept authid current_user as
begin
execute immediate 'TRUNCATE TABLE DEPT';
INSERT /*+ APPEND */ INTO DEPT (DEPTNO, DNAME, LOC)
SELECT DEPTNO, DNAME, LOC
FROM TMP_DEPT;
commit;
end;
/
> PL/SQL 에서는 동적 SQL 또는 DDL 문장을 실행할 때 EXECUTE IMMEDIATE를 사용해야한다.
123.
PL/SQL에 대한 설명
- 변수와 상수 등을 사용하여 일반 SQL 문장을 실행할 때 WHERE 절의 조건 등으로 대입할 수 있다.
- Procedure, User Defined Function, Trrigger 객체를 PL/SQL로 작성할 수 있다.
- Procedure 내부에 작성된 절차적 코드는 PL/SQL엔진이 처리하고 일반적인 SQL 문장은 SQL실행기가 처리한다.
- PL/SQL로 작성된 Procedure, User Define Function은 작성자 기준으로 트랜젝션 분할할 수 있다.
(프로시저 내에서 다른 프로시저 호출할 때 호출 프로시저 트랜젝션과는 별도로
PRAGMA AUTONOMOUS_TRANSACTION 을 선언하여 자율 트랜젝션 처리가 가능하다)
122.
User1 사용자가 릴레이션 R 을 생성하였다.
User1 : GRANT SELECT, INSERT, DELETE ON R TO User2 WITH GRANT OPTION;
User2 : GRANT SELECT, INSERT, DELETE ON R TO User3;
User1 : REVOKE DELETE ON R FROM User2;
User1 : REVOKE INSERT ON R FROM User2 CASCADE;
USER2 는 DELETE, INSERT 권한을 회수당했다.
USER3 은 USER1 의 CASCADE 명령으로 인해 INSERT 권한이 USER2와 함께 삭제되었다.
121.
DBMS 사용자를 생성하면 기본적으로 많은 권한을 부여하는데,
DBMS 관리자의 권한 관리의 부담과 복잡함을 줄이기 위해
다양한 권한을 그룹으로 묶어 관리할 수 있도록 [ROLE] 을 제공한다.
120.
UPDATE A_User.TB_A
SET col1='AAA'
WHERE col2=3
B_User 가 위 작업을 수행할 수 있도록 권한을 부여하는 명령문
GRANT SELECT, UPDATE ON A.User.TB_A TO B_User
119.
GRANT : ROLE 을 DBMS USER 에게 부여하기 위해 사용하는 명령어
REVOKE : ROLE 을 DBMS USER 에게서 회수하기 위해 사용하는 명령어
118.
[ Test - Oracle live server ]
create table TBL (
id varchar2(10),
start_val number,
end_val number
);
insert into TBL values('A', 10, 14);
insert into TBL values('A', 14, 15);
insert into TBL values('A', 15, 15);
insert into TBL values('A', 15, 18);
insert into TBL values('A', 20, 25);
insert into TBL(id, start_val) values('A', 25);
commit;
select * from tbl;
select id, start_val, end_val
from (
select id, start_val, nvl(end_val, 99) end_val,
(case when start_val = lag(end_val) over (partition by id
order by start_val, nvl(end_val, 99)) then 1
else 0
end) flag1,
(case when end_val = lead(start_val) over (partition by id
order by start_val, nvl(end_val, 99)) then 1
else 0
end) flag2
from tbl
)
where flag1 = 0 or flag2 = 0;
핵심:
case1: start_val 가 end_val 이전행의 값이랑 같은지 비교해서 같을때 결과값은 1, 다를때 결과값은 0이다.
case2: end_val 가 start_val 이후행의 값이랑 같은지 비교해서 같을때 결과값은 1, 다를때 결과값은 0이다.
서브에서 생성했던 flag 컬럼 중 0인값들의 행만 메인에서 select 한다.
117.
[ Test - Oracle live server ]
create table 사원(
사원ID number,
부서ID number,
사원명 varchar2(20),
연봉 number
);
insert into 사원 values (001, 100, '홍길동', 2500);
insert into 사원 values (002, 100, '강감찬', 3000);
insert into 사원 values (003, 200, '김유신', 4500);
insert into 사원 values (004, 200, '김선달', 3000);
insert into 사원 values (005, 200, '유학생', 2500);
insert into 사원 values (006, 300, '변사또', 4500);
insert into 사원 values (007, 300, '박문수', 3000);
commit;
select * from 사원;
select Y.사원ID, Y.부서ID, Y.사원명, Y.연봉
from (select 사원ID, max(연봉) over(partition by 부서ID) as 최고연봉
from 사원) X, 사원 Y
where X.사원ID = Y.사원ID
and X.최고연봉 = Y.연봉;
핵심:
Inline-view 를 통해 사원ID와 부서별최고연봉을 X테이블로 생성하여
최고연봉과 같은 연봉을 받는 사람만 출력한다.
116.
select 상품분류코드, AVG(상품가격) as 상품가격,
count(*) over(order by avg(상품가격)
range between 10000 preceding
and 10000 following) as 유사개수
from 상품
group by 상품분류코드;
유사개수 컬럼은 상품분류코드별 평균상품가격을 서로 비교하여
-10000 ~ +10000 사이에 존재하는 상품분류코드의 개수를 구한것이다.
range: 값
preceding: 이전
following: 이후
group by 이후 select 이 실행되기 때문에 상품분류코드별로 계산된다.
115.
[ Test - Oracle live server ]
create table 추천내역 (
추천경로 varchar2(20),
추천인 varchar2(20),
피추천인 varchar2(20),
추천점수 number
);
insert into 추천내역 values ('sns', '나한일', '강감찬', 75);
insert into 추천내역 values ('sns', '이순신', '강감찬', 80);
insert into 추천내역 values ('이벤트응모', '홍길동', '강감찬', 88);
insert into 추천내역 values ('이벤트응모', '저절로', '이순신', 78);
insert into 추천내역 values ('홈페이지', '저절로', '이대로', 93);
insert into 추천내역 values ('홈페이지', '홍두깨', '심청이', 98);
commit;
select * from 추천내역;
select 추천경로, 추천인, 피추천인, 추천점수
from (select 추천경로, 추천인, 피추천인, 추천점수,
row_number() over(partition by 추천경로 order by 추천점수 desc) as rnum
from 추천내역)
where rnum = 1;
- row_number : 동일한 순위더라도 고유한 순위를 부여한다.
114.
RANK() | DENSE_RANK() | ROW_NUMBER() |
1 | 1 | 1 |
2 | 2 | 2 |
2 | 2 | 3 |
4 | 3 | 4 |
5 | 4 | 5 |
113.
create table 고객(
고객번호 number primary key,
고객명 varchar2(20)
);
create table 월별매출(
월 varchar2(20),
고객번호 number,
매출액 number,
constraint multi_pk primary key (월, 고객번호)
);
insert into 고객 values (001, '홍길동');
insert into 고객 values (002, '이순신');
insert into 고객 values (003, '강감찬');
insert into 고객 values (004, '이상화');
insert into 고객 values (005, '이규혁');
commit;
insert into 월별매출 values ('202301', 001, 200);
insert into 월별매출 values ('202301', 002, 300);
insert into 월별매출 values ('202301', 003, 250);
insert into 월별매출 values ('202301', 004, 300);
insert into 월별매출 values ('202301', 005, 250);
insert into 월별매출 values ('202302', 001, 150);
insert into 월별매출 values ('202302', 002, 150);
insert into 월별매출 values ('202302', 004, 200);
insert into 월별매출 values ('202302', 005, 100);
insert into 월별매출 values ('202303', 002, 100);
insert into 월별매출 values ('202303', 003, 100);
insert into 월별매출 values ('202303', 004, 200);
insert into 월별매출 values ('202303', 005, 350);
commit;
select * from 월별매출;
select 고객번호, 고객명, 매출액, rank() over(order by 매출액 desc) as 순위
from (
select A.고객번호, max(A.고객명) as 고객명, sum(B.매출액) as 매출액
from 고객 A inner join 월별매출 B
on (A.고객번호 = B.고객번호)
group by A.고객번호
)
order by 순위;
- max(A.고객명) : group by 로 묶지 않았기 때문에 단순히 하나의 행으로 표기하려고 max 쓴 것으로 보임
- 동일순서에 대한 정렬은 답지와 위 코드의 실행결과가 약간 다름 (?)
112.
윈도우 함수에 대한 설명
- Partition 과 Group By 구문은 의미적으로 유사하다.
- Partition 구문이 없으면 전체 집합을 하나의 Partition 으로 정의한 것과 동일하다.
- 윈도우 함수는 결과에 대한 함수처리이기 때문에 결과 건수는 줄지 않는다.
- 윈도우 함수 적용 범위는 Partition을 넘을 수 없다.
111.
Groupping set 은 다양한 소계 집합을 만들 수 있다.
표시된 인수들에 대한 개별 집계를 구한다.
select 상품ID, 월, sum(매출액) as 매출액
from 월별매출
where 월 between '2014.10' and '2014.12'
group by grouping sets((상품ID, 월));
> (상품ID, 월) 별 집계 데이터를 출력한다. (괄호 주의)