오라클 커서(Cursor)

기본 문법

DECLARE
    CURSUR [커서이름] IS [SELECT 문];
BEGIN
    OPEN [커서이름];
    FETCH [커서이름] INTO [변수];
    CLOSE [커서이름];
END;

예제 준비


오라클 커서란

커서는 SELECT문 또는 DML문 처리에 대한 정보를 저장하는 전용 SQL 메모리 영역에 대한 포인터이다. DML문의 커서 관리는 오라클 데이터베이스에서 처리하지만, PL/SQL은 커서를 정의하고 조작하여 SELECT문을 실행하는 여러 방법을 제공한다.

일반적인 방법들은 다음과 같다.

  • SELECT-INTO 문
  • 명시적 커서로부터 가져오기
  • 커서 FOR 반복문 사용
  • 동적 쿼리에 EXECUTE IMMEDAITE INTO 사용
  • 커서 변수 사용

SELECT-INTO문

SELECT-INTO는 SELECT문에서 하나의 행을 가져오는 가장 빠르고 간단한 방법을 제공한다.

SELECT select_list INTO variable_list FROM remainder_of_query

remainder_of_query에는 테이블 또는 뷰, WHERE 절, 기타 절이 포함된다. variable_list의 수와 유형은 select_list의 요소 수와 유형과 일치해야 한다.

SELECT문이 2개 이상의 행을 조회하면 TOO_MANY_ROWS 예외가 발생하고, 조회 데이터가 없으면 NO_DATA_FOUND 예외가 발생한다.

  • 기본 예제
-- * ORACLE Live SQL OE(Order Entry) 스키마를 활용한 SELECT INTO 커서 예제

-- 카테고리 이름이 office1인 데이터의 카테고리 설명을 가져온다.
DECLARE
    v_category_desc oe.categories_tab.category_description%TYPE;
BEGIN
    SELECT
        category_description INTO v_category_desc
    FROM oe.categories_tab
    WHERE category_name = 'office1';

    DBMS_OUTPUT.put_line(v_category_desc);
END;

-- > 결과: capitalizable assets (desks, chairs, phones ...)

-- * NO_DATA_FOUND 예외 발생 예제
DECLARE
    v_category_desc oe.categories_tab.category_description%TYPE;
BEGIN
    SELECT
        category_description INTO v_category_desc
    FROM oe.categories_tab
    WHERE category_name = 'office0';

    DBMS_OUTPUT.put_line(v_category_desc);
END;

-- > 결과: ORA-01403: no data found ORA-06512: at line 4

-- * TOO_MANY_ROWS 예외 발생 예제
DECLARE
    v_category_desc oe.categories_tab.category_description%TYPE;
BEGIN
    SELECT
        category_description INTO v_category_desc
    FROM oe.categories_tab;

    DBMS_OUTPUT.put_line(v_category_desc);
END;

-- > 결과: ORA-01422: exact fetch returns more than requested number of rows ORA-06512: at line 4
  • 1행 전체를 SELECT INTO 예제
-- CATEGORIES_TAB 테이블에서 카테고리 이름이 office1인 데이터의 행 전체을 가져온다.
DECLARE
    v_category_tab oe.categories_tab%ROWTYPE;
BEGIN
    SELECT
        * INTO v_category_tab
    FROM oe.categories_tab
    WHERE category_name = 'office1';

    DBMS_OUTPUT.put_line(v_category_tab.category_name);
    DBMS_OUTPUT.put_line(v_category_tab.category_description);
END;

-- > 결과
/*
office1
capitalizable assets (desks, chairs, phones ...)
*/
  • 두 변수, 두 테이블 예제
-- 상품과 카테고리 테이블을 조인하여 상품 아이디 1797 데이터와 그 카테고리의 특정 정보를 조회한다.
DECLARE
    v_category_id oe.categories_tab.category_id%TYPE;
    v_category_name oe.categories_tab.category_name%TYPE;
    v_product_id oe.product_information.product_id%TYPE;
    v_product_name oe.product_information.product_name%TYPE;
BEGIN
    SELECT
        c.category_id, c.category_name, p.product_id  , p.product_name
        INTO
        v_category_id, v_category_name, v_product_id, v_product_name
    FROM oe.categories_tab c
    JOIN oe.product_information p ON c.category_id = p.category_id
    WHERE p.product_id = '1797';

    DBMS_OUTPUT.put_line(
        'PRODUCT[' || v_product_id || ']' || v_product_name 
        || ' belongs to CATEGORY[' || v_category_id || '] ' || v_category_name
    );
END;

-- > 결과: PRODUCT[1797] "Inkjet C/8/HQ" belongs to CATEGORY[12] "hardware2"
  • SELECT INTO 예외
  1. ORA-00947 not enough values: SELECT 조회 결과 컬럼 수보다 변수가 적음
  2. ORA-00913 too many values: SELECT 조회 결과 컬럼 수보다 변수가 많음
  3. ORA-06502 PL/SQL: numeric or value error: SELECT 조회 결과 컬럼과 변수의 자료형이 맞지 않음
-- PL/SQL: ORA-00947: not enough values
DECLARE
    v_category_id oe.categories_tab.category_id%TYPE;
    v_category_name oe.categories_tab.category_name%TYPE;
    v_product_id oe.product_information.product_id%TYPE;
    v_product_name oe.product_information.product_name%TYPE;
BEGIN
    SELECT
        c.category_id, c.category_name, p.product_id  , p.product_name
        INTO
        v_category_id, v_category_name, v_product_id
    FROM oe.categories_tab c
    JOIN oe.product_information p ON c.category_id = p.category_id
    WHERE p.product_id = '1797';

    DBMS_OUTPUT.put_line(
        'PRODUCT[' || v_product_id || '] "' || v_product_name 
        || '" belongs to CATEGORY[' || v_category_id || '] "' || v_category_name || '"'
    );
END;

-- PL/SQL: ORA-00913: too many values
DECLARE
    v_category_id oe.categories_tab.category_id%TYPE;
    v_category_name oe.categories_tab.category_name%TYPE;
    v_product_id oe.product_information.product_id%TYPE;
    v_product_name oe.product_information.product_name%TYPE;
    v_add_one VARCHAR2(10 Char);
BEGIN
    SELECT
        c.category_id, c.category_name, p.product_id  , p.product_name
        INTO
        v_category_id, v_category_name, v_product_id, v_product_name, v_add_one
    FROM oe.categories_tab c
    JOIN oe.product_information p ON c.category_id = p.category_id
    WHERE p.product_id = '1797';

    DBMS_OUTPUT.put_line(
        'PRODUCT[' || v_product_id || '] "' || v_product_name 
        || '" belongs to CATEGORY[' || v_category_id || '] "' || v_category_name || '"'
    );
END;

-- ORA-06502: PL/SQL: numeric or value error: character to number conversion error
DECLARE
    v_category_id oe.categories_tab.category_id%TYPE;
    v_category_name oe.categories_tab.category_name%TYPE;
    v_product_id oe.product_information.product_id%TYPE;
    v_product_name NUMBER;
BEGIN
    SELECT
        c.category_id, c.category_name, p.product_id  , p.product_name
        INTO
        v_category_id, v_category_name, v_product_id, v_product_name
    FROM oe.categories_tab c
    JOIN oe.product_information p ON c.category_id = p.category_id
    WHERE p.product_id = '1797';

    DBMS_OUTPUT.put_line(
        'PRODUCT[' || v_product_id || '] "' || v_product_name 
        || '" belongs to CATEGORY[' || v_category_id || '] "' || v_category_name || '"'
    );
END;

명시적 커서로부터 가져오기

SELECT INTO는 Oracle DB가 묵시적으로 SELECT문을 위한 커서를 열어 행을 가져오고 작업이 종료되거나 예외가 발생하면 자동으로 커서를 닫는다. 반면 사용자가 명시적으로 커서를 선언하고 열고, 가져오고, 닫는 동작을 할 수 있다. SELECT INTO 문과 달리 커서를 선언부에서 따로 초기화를 해야한다.

OE.ORDERS 테이블에서 SALES_REP_ID로 그룹화하여 ORDER_TOTAL의 합이 많은 순서대로 2000달러씩 보너스를 주는 커서를 프로그래밍해보자. 보너스는 10000달러가 있다고 가정한다.

DECLARE
    v_total_bonus INTEGER := 10000;

    CURSOR sales_rep_cur
    IS
        SELECT 
            * 
        FROM (
            SELECT
                sales_rep_id, SUM(order_total) sum_order_total
            FROM oe.orders
            WHERE sales_rep_id IS NOT NULL
            GROUP BY sales_rep_id
        )
        ORDER BY sum_order_total DESC
    ;

    v_sales_rep_id sales_rep_cur%ROWTYPE;

BEGIN
    OPEN sales_rep_cur;
    LOOP
        FETCH sales_rep_cur INTO v_sales_rep_id;
        EXIT WHEN sales_rep_cur%NOTFOUND;

        v_total_bonus := v_total_bonus - 2000;
        DBMS_OUTPUT.put_line('SALES[' || v_sales_rep_id.sales_rep_id || '] get bonus $2000');

        EXIT WHEN v_total_bonus <= 0;
    END LOOP;

    CLOSE sales_rep_cur;

END;
-- 결과
/*
SALES[161] get bonus $2000
SALES[156] get bonus $2000
SALES[154] get bonus $2000
SALES[158] get bonus $2000
SALES[159] get bonus $2000
*/

커서 FOR 반복문 사용

FOR 반복문을 사용하여 커서를 열고 닫는 것을 생략하고 좀더 간편하게 작성할 수 있다. 위에서 본 예제를 FOR 반복문을 사용하여 프로그래밍 해보자.

DECLARE
    v_total_bonus INTEGER := 10000;

    CURSOR sales_rep_cur
    IS
        SELECT 
            * 
        FROM (
            SELECT
                sales_rep_id, SUM(order_total) sum_order_total
            FROM oe.orders
            WHERE sales_rep_id IS NOT NULL
            GROUP BY sales_rep_id
        )
        ORDER BY sum_order_total DESC
    ;

BEGIN
    FOR sales_rep IN sales_rep_cur
    LOOP
        v_total_bonus := v_total_bonus - 2000;
        DBMS_OUTPUT.put_line('SALES[' || sales_rep.sales_rep_id || '] get bonus $2000'
            || ', sales $' || sales_rep.sum_order_total || ' in this month' 
        );
        EXIT WHEN v_total_bonus <= 0;
    END LOOP;

END;

-- 결과
/*
SALES[161] get bonus $2000, sales $661734.5 in this month
SALES[156] get bonus $2000, sales $202617.6 in this month
SALES[154] get bonus $2000, sales $171973.1 in this month
SALES[158] get bonus $2000, sales $156296.2 in this month
SALES[159] get bonus $2000, sales $151167.2 in this month
*/

-- 다른 변수가 없다면 선언부를 생략할 수 있다
BEGIN
    FOR sales_rep IN (
        SELECT 
            * 
        FROM (
            SELECT
                sales_rep_id, SUM(order_total) sum_order_total
            FROM oe.orders
            WHERE sales_rep_id IS NOT NULL
            GROUP BY sales_rep_id
        )
        ORDER BY sum_order_total DESC
    )
    LOOP
        DBMS_OUTPUT.put_line('SALESMAN[' || sales_rep.sales_rep_id || ']'
            || ' sales $' || sales_rep.sum_order_total || ' in this month' 
        );
    END LOOP;
END;

-- 결과
/*
SALESMAN[161] sales $661734.5 in this month
SALESMAN[156] sales $202617.6 in this month
SALESMAN[154] sales $171973.1 in this month
SALESMAN[158] sales $156296.2 in this month
SALESMAN[159] sales $151167.2 in this month
SALESMAN[155] sales $134415.2 in this month
SALESMAN[163] sales $128249.5 in this month
SALESMAN[153] sales $114215.7 in this month
SALESMAN[160] sales $88238.4 in this month
*/

동적 쿼리 사용(EXECUTE IMMEDIATE INTO)

EXECUTE IMMEDIATE INTO 문을 사용하여 SELECT문을 즉시 실행하여 변수에 담을 수 있다. Function과 Procedure를 활용하여 동적쿼리를 사용하는 PL/SQL을 프로그래밍 해보자.

실제 환경에서는 동적 쿼리는 SQL 인젝션 위험이 있어 보안에 주의 해야 한다.

-- 단일 결과 동적 쿼리
CREATE OR REPLACE FUNCTION 
single_number_value (
   table_in    IN VARCHAR2,
   column_in   IN VARCHAR2,
   where_in    IN VARCHAR2)
   RETURN NUMBER
IS
   l_return   NUMBER;
BEGIN
   EXECUTE IMMEDIATE
         'SELECT '
      || column_in
      || ' FROM '
      || table_in
      || ' WHERE '
      || where_in
      INTO l_return;
   RETURN l_return;
END;
-- Function created.

-- SQL Worksheet에서 따로 따로 써서 RUN 해야 한다.
BEGIN
   DBMS_OUTPUT.put_line (
      single_number_value (
                'oe.product_information',
                'category_id',
                'product_id=1797'));
END;
-- 결과: 12

-- 여러 결과 동적 쿼리 (BULK COLLECT 사용)
CREATE OR REPLACE PROCEDURE 
show_number_values (
   table_in    IN VARCHAR2,
   column_in   IN VARCHAR2,
   where_in    IN VARCHAR2)
IS
   TYPE values_t IS TABLE OF NUMBER;

   l_values   values_t;
BEGIN
   EXECUTE IMMEDIATE
         'SELECT '
      || column_in
      || ' FROM '
      || table_in
      || ' WHERE '
      || where_in
      BULK COLLECT INTO l_values;

   FOR indx IN 1 .. l_values.COUNT
   LOOP
      DBMS_OUTPUT.put_line 
      (l_values (indx));
   END LOOP;
END;
-- Procedure created.

BEGIN
   show_number_values (
      'oe.orders',
      'order_total',
      'order_total >= 25000 
       order by order_total desc');
END;
-- 결과
/*
295892
282694.3
268651.8
144054.8
120131.3
103834.4
103679.3
94513.5
92829.4
...
*/

커서 변수

커서 변수는 커서 또는 결과집합을 가리키는 변수이다. 명시적 커서와 달리 커서 변수를 프로시저나 함수의 인자로 전달할 수 있다. 커서 변수는 주로 결과 집합을 응답하는 PL/SQL을 작성할 때 많이 사용된다.

-- 매출이 가장 높은 상품 구하는 함수 생성
CREATE OR REPLACE FUNCTION
find_top_sales_product (
    result_count_in NUMBER
) RETURN SYS_REFCURSOR
IS
    cur SYS_REFCURSOR;
BEGIN
    OPEN cur FOR
    SELECT
            product_id, sales
        FROM (
            SELECT
                product_id, sum(quantity * unit_price) sales
            FROM oe.order_items
            GROUP BY product_id
            ORDER BY sales DESC
        )
        WHERE ROWNUM <= result_count_in;

    RETURN cur;
END;

-- 함수를 호출하여 상위 10개의 출력하는 PL/SQL
DECLARE
   v_products_cur   SYS_REFCURSOR;
   v_product_id NUMBER;
   v_sales NUMBER;
BEGIN
   v_products_cur := find_top_sales_product(10);

   LOOP
    FETCH v_products_cur INTO v_product_id, v_sales;
    EXIT WHEN v_products_cur%NOTFOUND;
      DBMS_OUTPUT.put_line('Product[' || v_product_id || '] sales $' || v_sales);
   END LOOP;

END;
-- 결과
/*
Product[2350] sales $922708.6
Product[3127] sales $364351
Product[2359] sales $180872.8
Product[2252] sales $134079
Product[3003] sales $97464.4
Product[2311] sales $89411.7
Product[3106] sales $82490
Product[2236] sales $79741.2
Product[2289] sales $78099
Product[2245] sales $61908
*/

적절한 방법 선택

  • 하나의 행을 조회할 때는 SELECT INTO 문 또는 동적 쿼리를 사용
  • 모든 행을 조회할 때 본문이 하나 이상의 DML문을 실행하지 않으면 FOR 반복문 사용
  • BULK COLLECT로 가져와야 할 경우 명시적 커서를 사용하지만 각 FETCH에서 조회 결과 수를 제한할 것
  • 쿼리 결과가 런타임에 달라질 경우 또는 결과를 PL/SQL이 아닌 환경으로 전달해야할 경우 커서 변수 사용
  • 코드를 작성하는 동안 SELECT 문을 완전히 구성할 수 없는 경우에만 동적 쿼리(EXECUTE IMMEDIATE) 사용

참고

DROP문

  • 테이블을 삭제하는 명령어
  • 테이블의 구조와 데이터를 모두 삭제하므로 사용에 주의해야 한다.
  • 삭제하려는 테이블의 기본키를 다른 테이블에서 참조하고 있다면 삭제가 거절된다.(제약조건 위배)
  • 참조하는 테이블부터 삭제하거나 CASCADE CONSTRAINTS 옵션을 사용하여 무결성 제약조건을 동시에 삭제하면 된다.
  • 테이블을 삭제하면 테이블의 컬럼에 대해 생성된 인덱스도 함께 삭제된다.
  • 삭제된 테이블과 관련된 뷰와 시노님은 invalid 상태가 된다.
  • 형식
    DROP TABLE 테이블이름 [CASCADE CONSTRATINS] [PURGE]

ALTER문

  • 객체에 대한 모든 변경을 위해 사용
  • 생성된 테이블의 속성과 속성에 관한 제약, 그리고 기본키 및 외래키를 변경한다
형식
ALTER TABLE 테이블이름
    [ADD 속성이름 데이터타입] -- 컬럼 추가
    [DROP COLUMN 속성이름] -- 컬럼 삭제
    [MODIFY 속성이름 데이터타입] -- 컬럼 수정
    [MODIFY 속성이름 데이터타입 [NULL | NOT NULL]] -- 컬럼 수정 (널 허용/비허용)
    [ADD PRIMARY KEY(속성이름)] -- 기본키 추가
    [[ADD | DROP] 제약이름] -- 제약조건 추가 또는 삭제

ALTER TABLE

  • 새로운 컬럼을 추가, 삭제 변경할 수 있다.
  • 새로운 컬럼을 추가하면 기존의 테이블의 마지막 컬럼이 된다.

 

추가 

수정 

삭제 

 column

가능

가능

가능 

constraint 

가능 

불가능 

가능 



ALTER TABLE ADD

  • 테이블에 컬럼 추가 또는 컬러멩 constraint(제약조건)이 없을 경우 constraint를 추가하는데 사용한다.
  • 컬럼 추가시 테이블의 행이 존재한다면, 새로 추가되는 컬럼은 이미 존재하는 모든 행의 값을 NULL로 초기화한다.
  • 컬럼추가 형식
ALTER TABLE 테이블명
    ADD (컬럼명 데이터타입 [DEFAULT 값] [, 컬럼명 데이터타입] .... );
  • 제약조건(Constraint) 추가 형식
ALTER TABLE 테이블명
    ADD (컬럼명 데이터타입 CONSTRAINT constraint명 constraint실제값
    [, 컬럼명 데이터타입]...);
  • 한 번의 ADD 명령으로 여러 개의 컬럼 추가 가능하고, 하나의 컬럼만 추가하는 경우에는 괄호를 생각해도 된다.
  • CONSTRAINT 변경 여부 확인은 USER_CONSTRAINTS 뷰를 사용하여 확인할 수 있다.
  • CREATE TABLE AS….와 같은 서브쿼리를 사용하여 만든 테이블은 NOT NULL만 복사되며, PRIMARY KEY와 같은 제약조건은 복사되지 않는다.
  • 그러므로 서브쿼리로 만든 테이블에 CONSTRAINT를 추가해 주어야 한다.
  • 추가된 컬럼은 테이블의 마지막 부분에 생성되며 사용자가 컬럼의 위치를 지정할 수 없다.
  • 추가된 컬럼에도 기본 값을 지정할 수 있다.
  • 기존 데이터가 존재하면 추가된 컬럼 값은 NULL로 입력 되고, 새로 입력되는 데이터에 대해서만 기본 값이 적용된다.

ALTER TABLE MODIFY

  • 테이블의 컬럼을 변경하고자 할 때 사용
  • 형식
ALTER TABLE 테이블명
    MODIFY (컬럼명 데이터타입 [DEFAULT 값] [, 컬럼명 데이터타입] ... );
  • 데이터의 타입, 크기, 기본값을 변경할 수 있다.
  • 변경 대상 컬럼에 데이터가 없거나 NULL 값만 존재할 경우에만 SIZE를 줄일 수 있다.
  • 데이터 타입의 변경은 CHAR와 VARCHAR2 상호간의 변경만 가능하다.
  • 컬럼 크기의 변경은 지정된 데이터의 크기보다 같거나 클 경우에만 가능하다.
  • NOT NULL 컬럼인 경우에는 크기의 확대만 가능하다.
  • 컬럼의 기본값 변경은 그 이후에 삽입되는 행부터 영향을 준다.
  • ALTER TABLE … MODIFY를 이용하여 CONSTRAINTS를 수정할 수 없다.

 구분

데이터 타입 변경 가능사항 

크기

 NULL 컬럼

문자 숫자 날짜

확대, 축소 가능 

NOT NULL 컬럼 

CHAR VARCHAR2

확대만 가능

ALTER RENAME COLUMN

  • 컬럼명 변경
  • 형식
ALTER TABLE 테이블명
    RENAME COLUMN 기존컬럼명 TO 변경할컬럼명;

ALTER TABLE DROP COLUMN 컬럼명

  • 특정 테이블의 컬럼을 삭제
  • 형식
ALTER TABLE 테이블명
    DROP COLUMN 컬럼명;
  • 컬럼을 삭제하면 해당 컬럼에 저장된 데이터도 함께 삭제된다.
  • 한번에 하나의 컬럼만 삭제할 수 있다.
  • 삭제 후 테이블에는 적어도 하나의 컬럼은 존재해야 한다.
  • DDL문으로 삭제된 컬럼은 복구할 수 없다.



DDL 문

  • Data Definition Language
  • 데이터 구조의 생성(CREATE), 변경(ALTER), 제거(DROP) 명령 언어

CREATE 문

  • 테이블을 구성하고, 속성과 속성에 관한 제약 그리고 기본키(PK) 및 외래키(FK)를 정의하는 명령어

형식


CREATE TABLE [테이블이름] (
 [속성이름] [데이터타입] (NULL | NOT NULL | UNIQUE | DEFAULT 기본값 | CHECK 체크조건)
(PRIMARY KEY 속성이름(들))
(FOREIGN KEY 속성이름 REFERENCES 참조테이블이름(참조속성이름))
(ON DELETE (CASCADE | SET NULL))
)

예제


CREATE TABLE EMPLOYEE (
    E_ID VARCHAR2(30 Byte) PRIMARY KEY, -- 기본키(PK) 설정한다.
    E_NAME VARCHAR2(20 Byte) NOT NULL, -- NULL을 허용하지 않는다.
    E_DEPT_CODE NUMBER,
    DEL_YN CHAR(1 Byte) NOT NULL DEFAULT 'N', -- NULL을 허용하지 않으며 기본값을 'N'으로 한다.
    REG_TS DATE NOT NULL DEFAULT SYSDATE -- NULL을 허용하지 않으며 기본값을 시스템시간으로 한다.
    FOREIGN KEY E_DEPT_CODE REFERENCES DEPT_INFO(DEPT_CODE)
    -- 외래키 설정 E_DEPT_CODE 컬럼이 DEPT_INFO 테이블의 DEPT_CODE 컬럼 참조한다.
)

Structured Query Language(SQL)이란?

  • 구조적 쿼리 언어로 데이터베이스에 질의(쿼리)하는 것을 의미한다.

  • SQL을 이용해 단순한 쿼리뿐만 아니라 데이터베이스를 만들거나 제거하고, 데이터베이스 내에 테이블을 삽입, 갱신, 삭제하거나 다양한 운영 작업을 할 수 있기 때문이다. 

  • SQL은 1974년 IBM 연구소에서 발표한 SEQUEL(structured English Query Language)에서 유래한 것으로, 실험적 관계 데이터베이스 시스템인 SYSTEM R의 인터페이스로 설계 구현하였으나 현재 사용중인 DBMS인 DB2와 SQL?DS의 데이터 언어로 사용되고 있다.
  • SQL은 IBM뿐만 아니라 다른 DB에서도 채택하여 SQL을 지원하는 많은 관계 데이터베이스 시스템에 서 사용하고 있다. 현재의 표준인 SQL은 1992년 개정된 것으로 SQL/92 또는 SQL-92, SQL2로 불린다.

SQL 언어의 특징

  • 관계 대수와 관계해석을 기초로 한 고급 데이터 언어
  • 이해하기 쉬운 형태로 표현
  • 대화식 질의어로 사용 가능
  • 데이터 정의, 데이터 조작, 제어기능 제공
  • COBOL, C, PASCAL 등의 언어에 삽입
  • 레코드 집합 단위로 처리
  • 비절차적언어

SQL의 주요 기능

  • data 정의: 저장 데이터의 구조와 데이터 항목들간의 관련성을 정의
  • data 검색: 저장된 데이터를 검색
  • data 조작: 데이터를 삽입, 삭제, 수정
  • 접근 제어: 허가되지 않은 사용자의 사용을 제한
  • data 공유: 동시 사용자들의 사용을 허용/방지
  • 대화식 질의
  • data에 대한 다중 뷰 제공
  • 동적 data 정의

테이블(table)과 뷰(view)

  • SQL은 기본적으로 릴레이션(relation:관계) 즉 테이블을 대상으로 수행되며 테이블에는 기본 테이블(base table)과 뷰(view)가 있다.
  • 기본 테이블은 사용자가 데이터베이스를 생성하는 과정이나 응용 프로그램을 위해 작성하는데 반해, 뷰는 독자적으로 만들어지지 못하고 특정 기본 테이블로 부터 유도되어 만들어 지는 가상 테이블이다. 일반적으로 테이블이라함은 기본 테이블을 의미한다.

PL/SQL과 SQL*Plus

  • PL/SQL이란? : SQL에 Application Logic을 추가하여 확장한 oracle의 절차적인 언어(Procedural Language)를 의미함
  • SQL*Plus이란? : SQL 및 PL/SQL 문장을 인식하고 실행시켜주는 Oracle Tool, 사용자와 물리적 Database 간의 Interface를 담당하는 도구, 즉, DBMS와 user간의 통신수단임

구분

특징

SQL

• 프로그래밍 경험이 적거나 전혀 없는 사용자들도 사용

• 비 절차적 언어

• 시스템을 생성하고 유지 관리하기 위해 요구되는 시간을 절약

• 영어와 유사한 언어

PL/SQL

• SQL 데이터 조작과 질의 명령문은 절차적인 code 단위 안에 포함

• error 처리 가능 이식성

• 데이터 캡슐화, 정보 숨김, 객체지향 같은 현대적 소프트웨어 엔제니어링 기능을 제공하여Oracle server와 Tool set에 대한 최신식의 프로그래밍을 가는케함

SQL*Plus

• 파일로부터 SQL 입력을 받음

• SQL 문장을 수정하기 위한 line 편집을 제공

• 환경적인 설정을 제어

• 질의 결과를 기본적인 레포트 형태로 format

• Local과 Remote DATABASE를 access


SQL 문장 종류

QUERY

=DQL(Data Query Language)

• DB에서 원하는 데이터의 검색

SELECT

DDL

(Data Definition Language)

• 데이터 구조의 생성, 변경, 제거

CREATE

DROP

ALTER

DML

(Data Manipulation Language)

• 테이블에 새로운 행의 삽입, 삭제, 수정

• 데이터베이스 객체 이름 변경

• 데이터 및 저장공간 회수

INSERT

DELETE

UPDATE

RENAME

TRUNCATE

DCL

(Data Control Language)

• DB와 구조에서 접근 권한의 부여와 제거

GRANT

REVOKE

TCL

(Transaction Control Language)

• DML에 의한 변경을 관리

COMMIT

ROLLBACK

SAVEPOINT


SQL 문장 작성법

  • SQL 문장은 대소문자를 구별하지 않는다.
  • SQL*Plus에서 SQL 문장은 SQL 프롬프트에 입력되며, 이후의 Line은 줄번호가 붙는다.
  • SQL 명령을 종료할 때는 세미콜론(;)을 반드시 붙여야 한다.
  • 맨 마지막 명령어 1개가 SQL buffer에 저장된다.
  • SQL 문장은 한 줄 이상일 수 있다.
  • SQL 명령어를 구성하고 있는 단어중 어디에서나 분리해도 된다.
  • 한 개의 line에 한 개의 절(select, from, where) 형태로 나누어 입력하는 것을 권한다.그러나 한 개의 단어를 두 줄로 나누어 입력해서는 안된다.
  • keyword는 대문자로 입력하도록 권한다.
  • 다른 모든 단어 즉, table 이름, column 이름은 소문자로 입력을 권한다.
  • keyword는 단축하거나 줄로 나누어 쓸 수 없다.
  • 절은 대개 줄을 나누어 쓰도고 권한다.
  • 탭과 줄 넣기는 읽기 쉽게 하기 위해 사용을 권한다.


+ Recent posts