190531_DAY <뷰>, <시퀀스>, <PL/SQL>

<VIEW.> 뷰

  • 물리적인 테이블을 근거한 논리적인 가상테이블.
  • 가상 : 실질적으로 데이터를 저장하고 있지 않는다. (독립적인 테이블은 아니다.)
  • 기본테이블에 대한 하나의 쿼리문 (TEXT를 저장하는 '객체')
  • 자주 사용되는 복잡하고 긴 쿼리문을 저장하는 객체
  • 특정컬럼만 보여지게끔하여 보안을 목적으로 사용
  • 뷰는 테이블이 하는거 다 할 수 있다, 근데 뷰는 원래 목적은 보여주는거야, 그래서 옵션을 줘서 DML을 제한하고 조회만! (추가 삭제 수정 못하게 막아줌)
  1. 텍스트를 저장한다. SELECT
  2. 복잡한 쿼리문 간편하게 뷰이름으로만 호출 가능
  3. 제한적인 데이터를 조회할 수 있게 해준다.
  • 형식

    CREATE VIEW 뷰이름
    AS select_statement;
    
    CREATE VIEW emp_copy
    AS SELECT * FROM emp;
    -- ORA-01031: insufficient privileges ( 권한 불충분 )
    -- 권한 부족
    
    -- <권한 부여> - 관리자로 접속
    -- 형식)
        GRANT system_privilege
        TO user_name;
    
    -- <권한 회수> - 관리자
    -- 형식)
        REVOKE system_privilege
        FROM user_name;
    
    -- 관리자 계정 연결
    SQL> conn system/oracle
    -- Connected.
    SQL> show user
    -- USER is "SYSTEM"
    SQL> GRANT CREATE VIEW TO SCOTT; -- 뷰 객체 생성 권한
    -- Grant succeeded.
    
    --이후 다시 뷰 만들어보자!
    CREATE VIEW emp_copy
    AS SELECT * FROM emp;
    
    CREATE VIEW emp_copy
    AS SELECT * FROM emp;
    -- View created.
    
    desc emp_copy; -- 로 확인

<데이터 베이스 관리자가 가지는 시스템 권한>

  • CREATE USER - 새롭게 사용자를 생성하는 권한
  • DROP USER - 사용자를 삭제하는 권한
  • DROP ANY TABLE - 임의의 테이블을 삭제할 수 있는 권한
  • QUERY REWRITE - 질의 재작성을 할 수 있는 권한
  • BACKUP ANY TABLE - 임의의 테이블을 백업할 수 있는 권한

<데이터베이스 관리 권한>

  • CREATE SESSION - 데이터베이스에 접속할 수 있는 권한
  • CREATE TABLE - 사용자 스키마에서 테이블을 생성할 수 있는 권한.
  • CREATE VIEW - 사용자 스키마에서 뷰을 생성할 수 있는 권한.
  • CREATE SEQUENCE - 사용자 스키마에서 시퀀스을 생성할 수 있는 권한.
  • CREATE PROCEDURE - 사용자 스키마에서 함수을 생성할 수 있는 권한.
문제)
30번 부서 사원들의 정보(사원번호, 사원명, 급여, 부서번호)를 출력 (emp_copy뷰객체 통해서)

SELECT empno, ename, sal, deptno
FROM emp_copy
WHERE deptno=30;

     EMPNO ENAME                       SAL     DEPTNO
---------- -------------------- ---------- ----------
      7499 ALLEN                      1600         30
      7521 WARD                       1250         30
      7654 MARTIN                     1250         30
      7698 BLAKE                      2850         30
      7844 TURNER                     1500         30
      7900 JAMES                       950         30

--===========================================================================

문제)
emp테이블(원본, 물리적테이블)에 홍길동 사원을 추가히시오!
INSERT INTO emp (empno, ename, sal, deptno)
            VALUES (8000, '홍길동', 3000, 30);

SELECT empno, ename, sal, deptno
FROM emp_copy
WHERE deptno=30;
-- emp_copy조회했는데

     EMPNO ENAME                       SAL     DEPTNO
---------- -------------------- ---------- ----------
      8000 홍길동                     3000         30
      7499 ALLEN                      1600         30
      7521 WARD                       1250         30
      7654 MARTIN                     1250         30
      7698 BLAKE                      2850         30
      7844 TURNER                     1500         30
      7900 JAMES                       950         30
-- 홍길동 생성 !, emp 수정해도 emp_copy(뷰) 에도 바로 반영된다.
-- 만약 CREATE TABLE emp2 AS SELECT * FROM emp; 로 생성한 후 추가했다면 emp2에는 반영 안되었을 텐데...
-- 뷰는 기준테이블(emp)을 참조하는(바라보는) 논리적 테이블!, 바라만 보기 때문에 실시간으로 같이 수정되는구나!

--DBMS에서는 user들이 만드는 객체에 대해 '시스템테이블'을 만들어 관리!!

        테이블생성      -----> tab
        제약 추가(생성)   -----> user_constraints
        뷰생성         -----> user_views   

desc user_views                                                

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 VIEW_NAME                                 NOT NULL VARCHAR2(30)
 TEXT_LENGTH                                        NUMBER
 TEXT                                               LONG
 TYPE_TEXT_LENGTH                                   NUMBER
 TYPE_TEXT                                          VARCHAR2(4000)
 OID_TEXT_LENGTH                                    NUMBER
 OID_TEXT                                           VARCHAR2(4000)
 VIEW_TYPE_OWNER                                    VARCHAR2(30)
 VIEW_TYPE                                          VARCHAR2(30)
 SUPERVIEW_NAME                                     VARCHAR2(30)
 EDITIONING_VIEW                                    VARCHAR2(1)
 READ_ONLY                                          VARCHAR2(1)  

select view_name, text from user_views;   

VIEW_NAME    TEXT
------------------------------------------------------------
EMP_COPY    select "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" from emp  

--===========================================================================

문제) 30번 부서에 근무하는 사원의 사원번호, 사원명, 급여를 자주 조회한다.
         이를 뷰로 생성하시오.

     create view emp_copy
     as select empno, ename, sal
        from   emp
        where  deptno=30;         
   ---> ORA-00955: name is already used by an existing object
           ---> 테이블과 마찬가지로 뷰객체도 이미 존재하는 이름을 사용할 수 없음!!

     create view emp30
     as select empno, ename, sal
        from   emp
        where  deptno=30;         
    -- ==> 뷰생성 성공!!

     select * from emp30;

     EMPNO ENAME                       SAL
---------- -------------------- ----------
      7499 ALLEN                      1600
      7521 WARD                       1250
      7654 MARTIN                     1250
      7698 BLAKE                      2850
      7844 TURNER                     1500
      7900 JAMES                       950
      8000 홍길동                                         3000         


<VIEW형식>

   CREATE  [OR REPLACE]  [FORCE|NOFORCE]  VIEW 뷰이름  [(alias)]
   AS select_statement
   [WITH CHECK OPTION [CONSTRAINT 제약명]]
   [WITH READ ONLY [CONSTRAINT 제약명]];

   -- 뷰 emp30 에 입사일, 부서번호를 추가!
CREATE VIEW emp30
AS SELECT empno, ename, sal, hiredate, deptno
FROM emp
WHERE deptno = 30;
-- ORA-00955: name is already used by an existing object
-- 이미 위에서 만듬

CREATE OR REPLACE VIEW emp30
--존재하지 않는 뷰는 새로 생성하고 존재하는 뷰의 경우에는 TEXT내용 교체
AS SELECT empno, ename, sal, hiredate, deptno
FROM emp
WHERE deptno = 30;

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 EMPNO                                     NOT NULL NUMBER(4)
 ENAME                                              VARCHAR2(10)
 SAL                                                NUMBER(7,2)
 HIREDATE                                           DATE
 DEPTNO                                             NUMBER(2)

 --===========================================================================

 문제)
 abc 테이블 ( 존재하지 않는 테이블 )의 모든 컬럼을 조회하는 뷰를 생성하시오 ( 뷰명 : abc_view )
 CREATE OR REPLACE VIEW abc_view
 AS SELECT * FROM abc;
 -- ORA-00942: table or view does not exist
 -- 엥? 위에서 존재하지 않는 뷰는 새로 생성하는게 아닌가?...

 CREATE OR REPLACE FORCE VIEW abc_view 
 AS SELECT * FROM abc;
 -- Warning: View created with compilation errors.
 -- 생성 하긴 했는데 에러 생길 수 있어~! 경고해줄게, 텍스트만 저장할게

  --===========================================================================

 문제) EMP30에서 mgr을 조회하시오
 SELECT empno, ename FROM emp30; -- 이건 잘 되는데

select empno, ename, mgr from emp30; -- 얘는 안되네
 --ORA-00904: "MGR": invalid identifier EMP30에 정의되지 않은 애는 조회 불가

 DELETE FROM emp30 WHERE empno = 7900;


 SQL> SELECT COUNT(*) FROM emp;

  COUNT(*)
----------
        14

SQL> SELECT COUNT(*) FROM emp30;

  COUNT(*)
----------
         6

SQL> ROLLBACK;
--Rollback complete.

SQL> DROP VIEW emp_copy;
--View dropped.

CREATE TABLE emp_copy 
AS SELECT * FROM emp;

--뷰생성--
CREATE OR REPLACE VIEW emp30
AS SELECT empno, ename, sal, deptno
FROM emp_copy
WHERE deptno = 30;

SELECT * FROM emp30;

<뷰를 통한 입력>
INSERT INTO emp30 VALUES (8000, '김용진', 3000, 30);
INSERT INTO emp30 VALUES (6000, '이진주', 3000, 30);

SQL> SELECT * FROM emp30;
    SELECT * FROM emp_copy; -- 뷰가 아닌 테이블에도 잘 들어옴

     EMPNO ENAME                       SAL     DEPTNO
---------- -------------------- ---------- ----------
      7499 ALLEN                      1600         30
      7521 WARD                       1250         30
      7654 MARTIN                     1250         30
      7698 BLAKE                      2850         30
      7844 TURNER                     1500         30
      7900 JAMES                       950         30
      8000 김용진                     3000         30
      6000 이진주                     3000         30

<뷰를 통한 삭제>
    delete from emp30;   -- 뷰emp30을 통한 테이블emp_copy삭제, 8행 삭제됨
    select * from emp30; -- 없대

SQL> select empno,ename from emp_copy;
     EMPNO ENAME
---------- --------------------
      7369 SMITH
      7566 JONES
      7782 CLARK
      7788 SCOTT
      7839 KING
      7876 ADAMS
      7902 FORD
      7934 MILLER
      8002 길라임

   ※ 20번 부서의 정보를 조회하는 뷰생성!!
   CREATE VIEW emp20
   AS SELECT empno, ename, sal, deptno
   FROM emp_copy
   WHERE deptno = 20
   WITH READ ONLY;
   -- 읽기 전용, DML 불가, 뷰생성
           <뷰를 통한 입력>
           INSERT INTO emp20 values (9000, '김주원', 900, 20);
           -- ORA-42399: cannot perform a DML operation on a read-only view

           <뷰를 통한 삭제>
           DELETE FROM emp20;
           -- ORA-42399: cannot perform a DML operation on a read-only view

           <뷰를 통한 수정>
           UPDATE emp20 SET sal = 9999;
           -- ORA-42399: cannot perform a DML operation on a read-only view
           CREATE[OR REPLACE] [FORCE | NOFORCE] VIEW 뷰 이름 [(alias)]
           AS select_statement
           [WITH CHECK OPTION [ CONSTRAINT 제약명]]
           [WITH READ ONLY [CONSTRAINT 제약명]];

           <뷰에 별명주기>
           CREATE OR REPLACE VIEW emp20 (나별명)
           AS SELECT empno, ename, sal, deptno
           FROM emp_copy
           WHERE deptno = 20;
           --ORA-01730: invalid number of column names specified
           --뷰이름 다음에 명시되는 alias는 컬럼에 대한 별명임!! 
           -- 컬럼 갯수만큼 alias 줘야 한다.

           CREATE OR REPLACE VIEW emp20 (사원번호, 사원명, 급여, 부서번호)
           AS SELECT empno, ename, sal, deptno
           FROM emp_copy
           WHERE deptno = 20;
           --뷰 생성 성공
           SELECT * FROM emp20;
             사원번호 사원명                     급여   부서번호
---------- -------------------- ---------- ----------
      7369 SMITH                       800         20
      7566 JONES                      2975         20
      7788 SCOTT                      3000         20
      7876 ADAMS                      1100         20
      7902 FORD                       3000         20

 --===========================================================================

문제) emp20뷰에서 사원번호와 사원명만 조회하시오!!
    select empno,ename
    from emp20;     
   ==> ORA-00904: "ENAME": invalid identifier
         --->  뷰생성시 별명을 정의했다면 조회시에는 별명만 사용해야 함!!

    select 사원번호, 사원명
    from emp20;

        사원번호 사원명
---------- --------------------
      7369 SMITH
      7566 JONES
      7788 SCOTT
      7876 ADAMS
      7902 FORD
      8002 길라임                  

 --===========================================================================

문제) 'ADAMS'사원을 10번 부서로 이동하시오.(emp20뷰를 통해)
UPDATE emp20 SET 부서번호 = 10
WHERE 사원번호 = 7876;

SQL> SELECT * FROM emp20;

  사원번호 사원명                     급여   부서번호
---------- -------------------- ---------- ----------
      7369 SMITH                       800         20
      7566 JONES                      2975         20
      7788 SCOTT                      3000         20
      7902 FORD                       3000         20

 --===========================================================================

문제) '김유신'사원을 30번 부서에 추가하시오.(emp20뷰를 통해)
insert into emp20  values (8004,'김유신',2000,30);
select * from emp20;

 --===========================================================================

    CREATE  [OR REPLACE]  [FORCE|NOFORCE]  VIEW 뷰이름  [(alias)]
   AS select_statement
   [WITH CHECK OPTION [CONSTRAINT 제약명]]
   [WITH READ ONLY [CONSTRAINT 제약명]];     

       CREATE OR REPLACE VIEW emp20 (사원번호, 사원명, 급여, 부서번호)
       AS SELECT empno, ename, sal, deptno
       FROM emp_copy
       WHERE deptno = 20 WITH CHECK OPTION; -- CHECK OPTION : DEPT20에 위반되는 추가, 수정을 제한

문제) 
'FORD'사원을 10번 부서로 이동하시오(emp20뷰를 통해)
UPDATE emp20 SET 부서번호 = 10
WHERE 사원번호 = 7369;
--=> ORA-01402: view WITH CHECK OPTION where-clause violation

문제) '손오공'사원을 30번 부서에 추가하시오.(emp20뷰를 통해)
insert into emp20 values (8006,'손오공',2000,30);
--==> ORA-01402: view WITH CHECK OPTION where-clause violation

insert into emp20 values (8006,'손오공',2000,20);
--=> 입력성공!!

<인라인 뷰>

  • 서브쿼리문에서 바깥쪽 SELECT문(메인쿼리)의 FROM절에 사용된 서브쿼리문

  • 내부에 사용되는 서브쿼리는 별칭이 부여, 이렇게 부여된 별칭이 뷰처럼 사용

    SELECT ...., -- 메인쿼리
                (SELECT ...) -- 서브쿼리
    FROM ....(SELECT ... -- 서브쿼리, 인라인뷰!
             ) Alias
    
    WHERE (SELECT ...) -- 서브쿼리
    ...;

<Top-N 구하기>

  • ROWID : 주소로서 ROW가 실제로 저장되어 있는 공간을 표시

  • ROWNUM : 번호로서 ROW의 주소 순서대로 출력되어짐.

    ​ 출력되는 행에 대해 첫행부터 순차적인 번호를 부여 ( 1,2,3, ...... )

    SELECT empno, ename, sal, rownum
    FROM emp;
    
         EMPNO ENAME                       SAL     ROWNUM
    ---------- -------------------- ---------- ----------
          7369 SMITH                       800          1
          7499 ALLEN                      1600          2
          7521 WARD                       1250          3
          7566 JONES                      2975          4
          7654 MARTIN                     1250          5
          7698 BLAKE                      2850          6
          7782 CLARK                      2450          7
          7788 SCOTT                      3000          8
          7839 KING                       5000          9
          7844 TURNER                     1500         10
          7876 ADAMS                      1100         11
          7900 JAMES                       950         12
          7902 FORD                       3000         13
          7934 MILLER                     1300         14

    문제 ) 위의 출력된 사원 중 세명만 (ROWNUM : 1~3 출력)
    SELECT empno, ename, sal
    FROM emp
    WHERE rownum BETWEEN 1 AND 3;
    
         EMPNO ENAME                       SAL
    ---------- -------------------- ----------
          7369 SMITH                       800
          7499 ALLEN                      1600
          7521 WARD                       1250
    
     --===========================================================================
    
    문제 ) 가장 급여를 많이 받는 3명의 사원 정보(사원번호, 사원명, 급여)를 ROWNUM을 사용해서 출력하시오.
    
    SELECT empno, ename, sal
    FROM emp
    WHERE rownum BETWEEN 1 AND 3
    ORDER BY sal DESC; -- 실행순서때문에 원하는 값 안나옴, 순서를 바꿔주어야 한다.
    
    SELECT empno, ename, sal        --실행4
    FROM  (SELECT empno, ename, sal --실행2
           FROM EMP                 --실행1
           ORDER BY sal desc)            --실행3
    WHERE rownum BETWEEN 1 AND 3;      --실행5
         EMPNO ENAME                       SAL
    ---------- -------------------- ----------
          7839 KING                       5000
          7902 FORD                       3000
          7788 SCOTT                      3000
    
     --===========================================================================
    
    문제) 가장 오래된(오래 근무한) 사원 3명의 사원번호 사원명, 입사일을 출력하시오
    SELECT empno, ename, hiredate
    FROM (SELECT empno, ename, hiredate
             FROM EMP
             ORDER BY HIREDATE asc)
    WHERE rownum BETWEEN 1 AND 3 ;
         EMPNO ENAME                HIREDATE
    ---------- -------------------- --------
          7369 SMITH                80/12/17
          7499 ALLEN                81/02/20
          7521 WARD                 81/02/22
    
     --===========================================================================
    
    문제) 급여를 4번째로 많이 받는 사원부터 6번째까지의 사원의 정보(사원번호, 사원명, 급여)를 출력하시오
    
    SELECT empno, ename, sal
    FROM (SELECT empno, ename, sal
          FROM emp
          ORDER BY sal DESC
         )
    WHERE rownum BETWEEN 4 AND 6;
    --결과 없음, 이유 : rownum은 항상 1부터 1씩 증가하는 값을 카운트 해야 함!
    
    SELECT empno, ename, sal
    FROM (SELECT empno, ename, sal, rownum rb-- rownum 이 두개가 돌아다니니 별명 지어줘야 함
          FROM (SELECT empno, ename, sal
                  FROM emp
                  ORDER BY sal DESC
                )
         )
    WHERE rb BETWEEN 4 AND 6;
    

<SEQUENCE시퀀스> : 자동번호 부여

  • 숫자값이 일정한 규칙에 의해서 연속적으로 자동증가.

  • 테이블에 종속적이지 않다(테이블과 독립적)
    형식)

    CREATE SEQUENCE sequence_name  
                   [INCREMENT BY] 증가치
                   [START WITH] 초기값
                   [MAXVALUE n|NOMAXVALUE]
                   [MINVALUE|NOMINVALUE]
                   [CYCLE|NOCYCLE]
                   [CACHE|NOCACHE];

    maxvalue: 시퀀스가 가질 수 있는 최대값 지정.

    ​ nomaxvalue일 경우 ascending순서일 경우 10의 27승
    ​ descending일 경우 -1

    ​ minvalue: 시퀀스가 가질 수 있는 최대값 지정.
    ​ nominvalue일 경우 ascending 1
    ​ descending 10의 26승으로 설정.
    cache: 메모리상의 시퀀스 값을 관리하도록 하는 것인데 기본값은 20.
    ​ nocache는 메모리 상에서 시퀀스를 관리하지 않음.

    • 사용법)

      시퀀스명.nextval -- 발생된 번호값( 그다음 )
      시퀀스명.currval -- 현재 번호값
      
      CREATE SEQUENCE test_seq; -- 기본 1부터 시작해서 1씩 증가되는 숫자값
      --시퀀스 생성
      
      DROP SEQUENCE test_seq;
      
      CREATE SEQUENCE test_seq
                      START WITH 1
                      INCREMENT BY 1
                      NOCYCLE
                      NOCACHE;
                      --시퀀스 생성
      현재 숫자 보기 (조회)
      SELECT test_seq.currval FROM dual;
      -- ORA-08002: sequence TEST_SEQ.CURRVAL is not yet defined in this session
      
      자동 번호(숫자) 얻어오기
      SELECT test_seq.nextval FROM dual;
      SELECT test_seq.nextval FROM dual;
      SELECT test_seq.nextval FROM dual;
      SELECT test_seq.nextval FROM dual;
      SELECT test_seq.nextval FROM dual; -- 5번!
      
      현재 숫자 보기 (조회)
      SELECT test_seq.currval FROM dual;
         CURRVAL
      ----------
               5
      
      테이블에 적용한 사례)
      alter table dept3
      drop primary key cascade;
      
      DROP TABLE dept3;
      
      CREATE TABLE dept3
      AS SELECT * FROM dept
      WHERE 1 = 0;
      
      <dept2 테이블 deptno 에 PRIMARY KEY설정>
      alter table dept3
      add constraint dept3_pk primary key (deptno);
      
      <행 데이터 입력>
         insert into dept3 values (10, '영업부', '서초');
         insert into dept3 values (20, '자재부', '대전');
         insert into dept3 values (30, '개발부', '남터');
      
         select * from dept3;
      
      ---------------------------------------------------
      -- 오랜 시간이 흘러 새로운 부서에 정보를 입력할 때
      데이터 ==> '기획부'        '강남'
      INSERT INTO dept3 (dname, loc) VALUES ( '기획부', '강남'); -- 에러
      
      INSERT INTO dept3 (dname, loc) VALUES ( '기획부', '강남'. '잠실'); --에러
      
      --입력 성공
      SELECT MAX(deptno) FROM dept;
      
      select deptno from dept3;
      
      insert into dept3 (deptno, dname, loc) values (40, '기획부', '강남');
      ---------------------시퀀스 객체를 사용했다면
      
       --===========================================================================
      
      문제) dept3부서테이블의 전체 데이터를 삭제하시오!!
          DELETE FROM dept3;
          TRUNCATE TABLE dept3;
      
       --===========================================================================
      
      문제) dept3 테이블 내의 deptno에 적용할 시퀀스 객체를 생성하시오
      -- (10부터 시작해서 10씩 증가)
      CREATE SEQUENCE dept3_seq
                      start with 10
                      increment by 10
                      nocycle
                      nocache;
      
      ※시퀀스 적용된 부서번호 생성!!
      <행 데이터 입력>
      INSERT INTO dept3 VALUES(dept3_seq.nextval , '영업부', '서초');
      INSERT INTO dept3 VALUES(dept3_seq.nextval , '자재부', '대전');
      INSERT INTO dept3 VALUES(dept3_seq.nextval , '개발부', '남터');
      
      SQL> select * from dept3;
      
          DEPTNO DNAME                        LOC
      ---------- ---------------------------- --------------------------
              10 영업부                       서초
              20 자재부                       대전
              30 개발부                       남터
              40 기획부                       강남
      
       --===========================================================================
       * Oracle 11g에서 시퀀스 사용시 주의할 점!!
        deferred_segment_creation=true(기본값) ===> false로 변경
      
        alter system set deferred_segment_creation=false;    
        ORA-01031: insufficient privileges ==> 권한불충분
      
      SQL> conn system/oracle      
      Connected.
      
      SQL> alter system set deferred_segment_creation=false;
      System altered.
      
      SQL> conn scott/tiger
      Connected.          

<PL/SQL>

  • SQL의 장점은 쿼리문 하나로 원하는 데이터를 검색 조작할 수 있다는 점인데, SQL문 자체는 비절차적 언어이기 때문에 몇개의 쿼리문 사이에 어떠한 연결 및 절차성이 있어야 하는 경우는 사용할 수 없다.

        insert into ~ values ~;
  • 이 점을 극복하기 위해서 SQL 언어에 절차적인 프로그래밍 언어를 가미해 만든 것이 PL/SQL

    if( select 결과가 내가 원하는 값이라면 )
    {
        insert into ~ values ~;
    }

<PL/SQL구조> - 눈사람을 생각해줘~!

  • DECLARE SECTION (선언부)

    • PL/SQL에서 사용하는 모든 변수나 상수를 선언
  • EXECUTABLE SECTION (실행부)

    • 절차적형식으로 SQL을 실행할 수 있도록 절차적요소인 제어문, 반복문
    • 함수정의 등 로직기술
  • EXCEPTION SECTION (예외처리)

    • 실행 중 발생되는 에러를 해결하기 위한 문장으로 구성

<변수선언>

변수명 자료형;

vempno number(4);

vempno emp.empno%type; --기존 존재하는 emp테이블의 empno컬럼이 갖는 자료형을 참조하겠다.

<레퍼런스 변수>

  • %TYPE (한 개의 칼럼), %ROWTYPE (한 행을 구성하는 모든 컬럼을 참조)
  • vemp emp&ROWTYPE;-- emp테이블이 갖는 모든 컬럼의 자료형을 vemp 변수로 참조하겠음.
형식)
declare -- 선언부
        -- (실행부에 필요한) 변수선언
begin  -- 실행부 {
        -- SQL문
end;/ -- } 끝난다~ /는 run의 의미임

-------------------------------------------------------------------------------------------
문제) 화면 콘솔에 '안녕, PL/SQL~!' 을 출력하시오.
     declare 
     begin 
        dbms_output.put_line('안녕, PL/SQL~!!');
     end; 
     /

문제)
7788사번을 갖는 사원의 사원번호와 사원명, 급여를 화면에 출력

DECLARE

BEGIN
    SELECT empno, ename, sal
    FROM emp
    WHERE empno = 7788;
    dbms_output.put_line(ename)
END;
/
-- 실행 안되네...
-------------------------------------------------------------------------------
DECLARE
    -- 실행부에서 사용할 변수 선언!
    -- 형식) 변수명 자료형;
    vempno number(4); --SELECT문에서 호출한 애들은 변수 선언 필수!
    vename varchar2(15);
    vsal emp.sal%TYPE; --기억 안나...emp테이블에서 가져올래!
BEGIN
    SELECT empno, ename, sal 
    -- 얘네들은 변수가 아니라 칼럼이야!
    INTO vempno, vename, vsal 
    --v 안뭍여도 된다~! 근데 식별때문에 씀
    -- into는 PL/SQL에서만 쓴다.
    FROM emp
    WHERE empno = 7788;

    --조회문(select) 사용시 into절을 사용해야 하는 이유?
    --select문을 실행하고 난 후 begin~end에서 조회한 데이터를 유지하려면
    --변수라는 곳에 담아야 하기 때문에
    --select 컬럼명 into 변수명!!
    dbms_output.put_line( '사원번호 : ' || vempno ); --조회된 칼럼명 인식X, 데이터를 담은 변수명 인식O
    dbms_output.put_line( '사원명 : ' || vename || '  급여 : ' || vsal);

END;
/

glogin

  • 오라클 서버 실행 되기 전에 항상 읽는 문서 여기에 미리 set해두면 항상 옵션이 설정된다.

<PL/SQL 형식 다시 정리>

DECLARE --선언부
--실행부에서 사용할 변수 선언

BEGIN --실행부 시작
    -- SQL문(DQL, DML)!!

    SELECT empno, ename, sal INTO 변수명1, 변수명2, 변수명3
    FROM emp;

    -- 이 영역에서 empno, ename, sal의 대한 정보가 사라짐!!
    -- 조회된 결과 데이터를 저장할 변수 정의가 필요하다.
    -- INSERT, DELETE문, UPDATE문

    --조건문 또는 반복문과 함께 하는 SQL문 작성!!

    --함수 호출
END; --실행부 끝
/

<조건문 IF>

  • 형식)

    <조건문 if>
      형식)
           if  ( 조건식   )  -- ()소괄호 생략 가능
              then -- { 시작을 표현
    
                     --조건식을 만족했을 때 실행할 문장;
    
    
     end if;  -- } 끝을 표현

    ----> if_test.sql
    ----> 두 수를 비교해서 크다, 작다를 출력!!






궁금상자

  • glogin에 좋은 옵션?! SET SQLPROMPT '&_USER.@&_CONNECT_IDENTIFIER.> '
    SET TIME ON
    SET TIMING ON
    SET TERMOUT ON
    SET SERVEROUTPUT ON
    SET FEED ON
    SET LINES 120
    SET PAGES 40
    SET ECHO ON

+ Recent posts