개발/교육

(데이터베이스)24일차

kakk789 2022. 4. 28. 12:26

VIEW 권한 주기

뷰 소유자(생성자)
GRANT 권한명(예: SELECT) ON 뷰이름 TO 권한받을ID
- SELECT 권한을 '권한받을ID' 에게 준 것

권한 받을 사람
SELECT * FROM 뷰소유자ID.뷰이름

VIEW 권한 제거

REVOKE 권한명(예: SELECT) ON 뷰이름 FROM 권한받은ID;

VIEW 수정

  • 동일한 이름의 VIEW가 존재하면 수정해주고 없다면 새로 생성하는 명령
CREATE OR REPLACE VIEW 뷰이름 AS SELECT ....

VIEW 삭제

DROP VIEW VIEW명

시스템 뷰

  • 오라클이 제공하는 뷰 (데이터사전)
user_tables       ==> 사용자가 만든 모든 테이블의 정보를 갖고 있음
user_objects      ==> 사용자가 만든 모든 객체의 정보를 갖고 있음 (테이블, 뷰, 제약 등 모든 객체 정보)
user_constraints ==> 사용자가 만든 모든 제약의 정보를 갖고 있음

user_tables 

  • 사용자가 만든 모든 테이블의 정보를 갖고 있음

USER_TABLE;

user_objects      

  • 사용자가 만든 모든 객체의 정보를 갖고 있음 (테이블, 뷰, 제약 등 모든 객체 정보)

USER_OBJECTS

user_constraints

  • 사용자가 만든 모든 제약의 정보를 갖고 있음
CONSTRAINT_NAME : 제약명
CONSTRAINT_TYPE :  제약의 종류
TABLE_NAME : 테이블이름
STATUS : 제약의 상태 (때로는 제약을 활성화, 비활성화 시킬 수 있음

제약 정보 검색 시 자주 사용되는 속성들과 쿼리문
SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,STATUS FROM user_constraints

제약의 활성 / 비활성화

ALTER TABLE 테이블명 DISABLE/ENABLE CONSTRAINT 제약명

예시
ALTER TABLE emp DISABLE/ENABLE CONSTRAINT SYS_C008327;

인덱스

  • 특정 컬럼에 인덱스를 만들어 검색 속도를 향상시킬 수 있음
  • 레코드의 수가 적을 때는 굳이 인덱스를 만들 필요가 없음. 당연히 레코드의 수가 많을 때 인덱스를 사용
  • 인덱스를 만들었는데 레코드의 값이 변경이 된다면 인덱스 재구성 필요
  • PK 로 설정한 컬럼은 자동으로 인덱스가 생성

인덱스 생성

생성법
CREATE INDEX 인덱스명 ON 테이블명(컬럼명1, [컬럼명2])

사용법
SELECT * FROM BOOK
WHERE 컬럼명1 = 'xx' [AND 컬럼명2 = 'yy'];

-> '컬럼명'을 검색(SELECT) 할 때에 검색속도 향상

인덱스 재구성 방법

ALTER INDEX 인덱스명 REBUILD;

인덱스 삭제

DROP INDEX 인덱스명;

인덱스 목록 보기 

  • 시스템에서 자동으로 생성한 인덱스는 SYS로 시작함
SELECT * FROM user_indexes;

데이터베이스 프로그래밍

  • DBMS에 데이터를 정의하고 저장된 데이터를 읽어와 데이터를 변경하는 프로그램을 작성하는 과정
  • 오라클에서는 PL/SQL 언어를 사용하여, SQL Server는 T-SQL 이라는 언어를 사용
  • 호스트 언어가 JSP, ASP, PHP 등의 웹 스크립트 언어인 경우 사용

PL/SQL의 종류

  • 프로시저
  • 리거
  • 사용자 정의 함수로 구성됨

프로시저(Procedure)

  • 메소드처럼 빈번하게 사용하는 SQL 명령어를 프로시저로 만들어서 사용 가능
  • 프로시저를 정의하려면 'CREATE PROCEDURE' 문을 사용함
    선언부와 실행부(BEGIN - END)로 구성

1. 프로시저 생성

CREATE OR REPLACE PROCEDURE 프로시저명(
   매개변수 IN 자료형    -> 입력 용도
   매개변수 IN 자료형    -> 입력 용도
   매개변수 IN 자료형    -> 입력 용도
   ...... 
  [매개변수 OUT 자료형] -> 출력 용도 ( OUT 을 쓸 경우 DECLARE로 출력 해야함 )
   ......
)
AS
  지역변수 
BEGIN
    동작 (INSERT .. ~)
    INSERT : 일반INSERT 문 처럼 사용
    DELETE : 일반 DELETE 문 처럼 사용
    SELECT: 해당 결과 값을 지역변수를 선언하고 INTO로 저장해야함
                ex) SELECT 속성 INTO 지역변수
END;
/
    CREATE OR REPLACE PROCEDURE insertCustomer(
        p_custid IN NUMBER,
        p_name IN VARCHAR2,
        p_address IN VARCHAR2,
        p_phone IN VARCHAR2
    )
    AS
    BEGIN
        INSERT INTO CUSTOMER VALUES(p_custid,p_name,p_address,p_phone);
    END;
    /

2. 프로시저 실행

EXEC 프로시저명 (매개변수1.....);
CALL 프로시저명 (매개변수1.....);
    EXEC insertCustomer(6, '홍길동','대한민국 부산', '000-5546-7777')

3. 결과 출력 방법

1. 매개변수로 out을 설정 하던지, AS문 변수를 하나 설정

2. dbms_output.put_line (AS문에서 설정한 출력할 값이 저장된 변수명)

3. set serveroutput on; 입력 하여 설정해줄 것

동작 개념
SELETE 의 결과가 dloc에 담겨있으니 해당 값을 AS문에서 선언한 변수인 p_dloc로 저장 후 출력하는 개념

4. 오류 확인 명령어 

SHOW ERRORS

5. DECLARE

(
매개변수 OUT NUMBER
)
....
.....
.....

DECLARE
  변수선언
begin
  명령어
end;
/

- 매개변수에 OUT 을 써줬기 때문에 변수와 출력문을 DECLARE 에서 따로 선언

고객 번호를 입력 받아 총 구매 가격을 출력

DECLARE 부분에서 result 변수의 역할

= custOrder 함수의 실행 결과는 담을 변수

    CREATE OR REPLACE PROCEDURE custOrder(

        p_custid IN NUMBER,
        p_printprice OUT NUMBER
    )
    AS
    BEGIN
        SELECT SUM(saleprice) INTO p_printprice 
        FROM CUSTOMER c, ORDERs o 
        WHERE o.custid = c.CUSTID 
        AND c.custid = 1;
    END;
    /

    DECLARE 
        result NUMBER;
    BEGIN
        custOrder(1, result);
        dbms_output.put_line(result);
    END;

6. CURSOR

  • 프로시저 안에서 select 한 행의 수가 여러 건(복수)이라면 cursor를 사용 해야 함. (하나의 행씩 가져와서 동작하도록 함.)
  • AS문에 'CURSOR' 선언
  • AS문에 데이터를 저장할 '변수'를 선언
  • 'CURSOR' 를 순회(LOOP) 하면서 한 행씩 뽑아(FETCH)하여 변수에 '저장'
  • EXIT WHEN으로 LOOP 문 탈출 가능
  • AS문에서는 SELECT를 할때 INTO 써 줄 필요 없음. (BEGIN에서 FETCH 할 때 INTO 사용 해야함)
AS
  변수명 자료형;
  CURSOR 커서이름 IS Select 문
BEGIN
  OPEN 커서이름;                                   --> 커서 동작
  LOOP                                                 --> 반복하면서 복수의 자료들을 뽑기위한 루프문
     FETCH 커서이름 INTO 변수명;              --> 커서에 있는 자료들을 가져와 변수에 저장
     EXIT WHEN 커서이름%NOTFOUND ;    --> 커서에 더이상 자료가 없으면 EXIT
     dbms_output.put_line(변수명) ;          --> EXIT 하지 않았을 경우 '변수명' 출력
  END LOOP;
  CLOSE 커서이름;

관리자의 이름을 전달받아 부하 직원을 출력 (CURSOR 사용)

- 부하직원이 여러 명 반환되므로 cursor를 써야함

   /* 쿼리문 */
   SELECT e.ename 
   FROM emp e, emp m 
   WHERE e.MGR = m.eno 
   AND m.ename = '관리자명';
   
   /* Procedure */
    CREATE OR REPLACE PROCEDURE printEmpMtoC(
        p_mname varchar2
    )
    AS
        p_cname VARCHAR2(20);
        CURSOR cn IS SELECT e.ename FROM emp e, 
        emp m WHERE e.MGR = m.eno AND m.ename = p_mname;
    BEGIN
        OPEN cn;
        LOOP
            FETCH cn INTO p_cname;
            EXIT WHEN cn%NOTFOUND;
            dbms_output.put_line(p_cname);

        END LOOP;
        CLOSE cn;
    END;
    /

트리거(Trigger)

  • DML 이벤트(insert, update, delete)가 발생할 때 자동으로 동작하는 프로시저
  • 연쇄하여 다른 테이블에도 적용할 필요가 존재할 때 사용
  • 프로시저는 직접 호출해야 하는데 트리거는 해당 시점에 자동으로 동작
CREATE OR REPLACE TRIGGER 트리거이름
  시점 : BEFORE / AFTER / INSTREA OF (얜 View 용)
  명령어 : INSERT
             UPDATE [OF] [컬럼명]
                  - 만약 [OF] [컬림명]이 붙으면 해당 컬럼의 데이터에 변경이 올 경우 동작
             DELETE

  ON 테이블명 FOR EACH ROW
  WHEN 조건
DECLARE
  변수선언
BEGIN
  트리거가 해야할 명령어(들)

  [IF문도 사용가능]
  if UPDATING  THEN
    속성명 :='변경 값';
  elsif DELETING THEN
    속성명 :='변경 값2';
  END IF;

END;
/

시스템 함수 UPDATING = 수정 되었다면 1반환

시스템 함수 DELETING = 삭제 되었다면 1반환

:new 와 :old

이해하려고 하지말고 외울부분이 있는데,

- UPDATE 또는 DELETE 실행 되기 전에 데이터가 잠깐? :OLD 테이블 로 넘어감

- INSERT 실행 되기 전에는 데이터가 :NEW 테이블로 넘어감

한 레코드(행)을 기준으로 생각하면 이해하기 쉽다
만약 한 행을 DELETE 하면 현재 기준(=NEW 기준)에는 한 행이 DELETE 되었기 때문에 당연히 NEW(현재 행)가 존재할 수가 없다.
출처 : https://www.youtube.com/watch?v=0KxIvQRPIIs
구분 :NEW :OLD
INSERT 추가한  레코드 없음
UPDATE 수정 후  레코드 수정 전 레코드
DELETE 없음 삭제 전  레코드
이미 지워진  레코드
:new
명령어가 실행된 새로운 레코드(행)를 의미 (INSERT, UPDATE)
만약 INSERT 가 되었다면 INSERT 되고난 후의 레코드(행)
만약 UPDATE 되었다면 UPDATE 되고난 후의 레코드(행)
만약 DELETE 되었다면 이미 삭제되었으니 없음
:old
명령어가 실행되기 전의 레코드 (UDPATE, DELETE)
만약 UPDATE 되었다면 UPDATE 전의 레코드(행)
만약 DELETE 되었다면 DELETE 전의 레코드(행)
만약 INSERT 되었다면 이전 데이터는 당연히 없으니 없음

아래 예시 설명

DEPT 테이블에 INSERT가 일어한 후(AFTER) 해당 행을 가져오고, BEGIN 구문을 실행해라

    CREATE OR REPLACE TRIGGER trg_dept_insert
    AFTER INSERT ON DEPT FOR EACH ROW
    DECLARE
    BEGIN
    INSERT INTO DEPT_BACK VALUES(:NEW.DNO, :NEW.DNAME, :NEW.DLOC );
    END;
    /

트리거 조회하기

    SELECT * FROM ALL_TRIGGERS;
    
    /*쉬운 예시*/
    SELECT * FROM all_triggers WHERE OWNER LIKE '%##%'

트리거 삭제

	DROP TRIGGER 트리거명;

반응형