Jam's story

[Oracle ] dyas20- 동적쿼리 본문

카테고리 없음

[Oracle ] dyas20- 동적쿼리

애플쩀 2022. 4. 29. 10:59
동적쿼리의 필요성 

1.컴파일 시에 SQL 문장이 확정되지 않은 경우   

where 조건절, select 항목이 동적으로 변하는 경우

 

ㅇ 예) 클릭할때마다 결과가 달라진다. 

WHERE 부분이  계속 늘어날 수 없으니, 동적쿼리를 만든다. 

 

2.where select 항목이 동적으로 변하는 경우

 

3 PL/SQL 블록 상에서 DDL문을 실행해야 하는 경우
    DDL (create, alter, drop, truncate문)

 

4. PL/SQL 블록 상에서 alter system/session 명령어를 실행해야 하는 경우

  ->dba 가 아니라면 쓸 일이 거의 없다 .

 

 

 

동적쿼리를 사용하는 방법 

1)원시동적쿼리 (Native Dynamic SQL : nds) 

2)dbms_sql 패키지 사용 x

 

 

동적쿼리를 실행하는 방법 

 

1)exec(ute)  프로시저명 

2)execute immediate 동적쿼리문 [into 변수명, 변수명문] [using in/out/inout 파라미터문]

 

동적쿼리생성(작성)->실행 
-- SCOTT 계정 접속 --  

   1. 트랜잭션 설명.
   2. 동적쿼리
   3. 암호화/복호화
------------------------------------------------------------------------------------------   
ㄱ. 트랜잭션(Transaction)이란?
일의 처리가 완료되지 않은 중간 과정을 취소하여 일의 시작 전 단계로 되돌리는 기능이다.
즉,
결과가 도출되기까지의 중간 단계에서 문제가 발생하였을 경우
모든 중간 과정을 무효화하여 작업의 처음 시작 전 단계로 되돌리는 것이라 할 수 있다.

ㄴ. 일의 모두 완료를 알리는 commit과 일의 취소를 알리는 rollback이 쓰인다.

ㄷ. DML문을 실행하면 
  해당 트랜젝션에 의해 발생한 데이터가 다른 사용자에 의해 변경이 발생하지 않도록 LOCK(잠김현상)을 발생한다.  
  이 lock은 commit 또는 rollback문이 실행되면 해제된다.
ㄹ. 예) 트랜잭션 처리가 필요한 곳.
    [ 계좌 이체 작업 ]
    
    백경환 -> 김지민   100만원 이체
    
    1) 백경환 통장에서  UPDATE 100만원 차감하는 DML
    2) 김지민 통장에서  UPDATE  100만원 증가하는  DML
    
    1) + 2)  모두 완료  COMMIT;
    1) + 2)  하나라도 실패하면 ROLLBACK;
    
    예) 트랜잭션 처리 필요 + 트리거 생성 처리
    입고테이블                  INSERT 15
    A상품 15 입고
    
    재고테이블
    A상품   115개              UPDATE 

-- A 사용자가 원격으로 SCOTT 계정 접속 --
ㅁ. A 트랜잭션 테스트 
SELECT *
FROM emp;    

7369   SMITH   CLERK   7902   80/12/17   800      20
1) SMITH 사원의 JOB을 CLERK -> MANAGER 수정
UPDATE emp
SET job = 'MANAGER'
WHERE ename = 'SMITH';
-- 1 행 이(가) 업데이트되었습니다.  
-- DML문 실행하면 잠금(LOCK) 
-- COMMIT, ROLLBACK 잠금 해제 X    
7369   SMITH   MANAGER   7902   80/12/17   800      20  
COMMIT;
-- 커밋 완료.  
    
1) SMITH 사원의 JOB을 MANAGER -> CLERK 수정
UPDATE emp
SET job = 'CLERK'
WHERE ename = 'SMITH';    
-- 1 행 이(가) 업데이트되었습니다.   
-- DML문 실행하면 잠금(LOCK) 
-- COMMIT, ROLLBACK 잠금 해제 X 
COMMIT;


INSERT/UPDATE/DELETE DML 문 수행  커/롤    잠금해제X

-- DEAD LOCK( 데드락 )
백경환 - 책상수리 중  드라이버 X , 망치 O

-- A 망치 + 못X   UPDATE 실행중

DML 사용하면 자동으로 트랜잭션이 걸린다( LOCK ) -> 커밋, 롤백 잠금 해제

 DDL/ DCL 실행하면 트랜잭션 종료.
 데이터베이스 종료
 
-- SELECT DQL문에 사용할 수있는 절 : FOR UPDATE OF 문
SELECT *
FROM EMP
FOR UPDATE OF JOB NOWAIT;
DQL + 트랜잭션( LOCK ) 
COMMIT; ROLLBACK;

--------------------------------------------------
TCL문 - COMMIT, ROLLBACK,      SAVEPOINT문
COMMIT;  -- 커밋 완료!!!
-- 10:02 수업 시작
SELECT *
FROM dept;

LOCK
1) 삭제
SAVEPOINT sp_dept_delete;
DELETE FROM dept WHERE deptno = 60 ;     --잠금


2) 추가
SAVEPOINT sp_dept_insert;
INSERT INTO dept VALUES ( 50, 'AA','YY'); --잠금


3) 수정
SAVEPOINT sp_dept_update;
UPDATE dept
SET loc = 'SEOUL'
WHERE deptno = 40;  -- BOSTON             --잠금


SELECT *
FROM dept;

ROLLBACK;
ROLLBACK TO sp_dept_update;  -- SAVEPOINT 생략가능
ROLLBACK TO SAVEPOINT sp_dept_insert;
ROLLBACK TO SAVEPOINT sp_dept_delete;

------------------------------------------------------------------
-- ***** [ 동적 SQL ] *****
JAVA 동적 배열
    int [] m ;
    int length = 10;
    m = new int[length];

PL/SQL
 1. 동적 SQL ? 컴파일 시에 SQL문장이 확정이 되지 않는 경우  -> 실행할 때 SQl문장 확정

  SELECT *
  FROM 게시판테이블
  -- 제목 검색
  IF 제목 검색 THEN
    WHERE 제목 LIKE '길동';
  -- 제목   +  내용   검색
  ELSIF 제목 + 내용 THEN
    WHERE 제목 LIKE '길동' OR 내용 LIKE '길동' ;
  ELSIF 제목 + 내용 THEN
  END IF;
  5만 가지의 경우 

*** 2.   WHERE 조건절, SELECT 컬럼.... 항목이 동적으로 변하는 경우 사용한다. 
SELECT ???  ???...
FROM 
WHERE ? AND ? OR ? ????????...

*** 3. PL/SQL 에서 DDL 문을 실행하는 경우
  CREATE/ALTER/DROP + TRUNCATE 문
  
4. PL/SQL 에서 alter session/system 명령어를 실행하는 경우 DBA X


5. 동적 쿼리를 사용하는 2가지 방법
  ***** 1) 원시 동적 쿼리( Native Dynamic SQL :  NDS ) *****
  2) dbms_sql 패키지 사용 X

-- EXEC[UTE] 저장프로시저명( 파라미터,,);
-- SELECT ename INTO vename 변수 저장
CREATE OR REPLaCE PROCEDURE 프로시저명
(
   p IN OUT  INOUT 파라미터.
   p 파라미터.
   :
)
6. 동적 쿼리를 실행 방법     
  1) 형식
    EXECUTE IMMEDIATE  동적쿼리문
                       [INTO 변수명, 변수명 문 ]
                       [USING MODE(IN,OUT,INOUT) 파라미터, 파라미터,,,,문 ];
    
7. 동적 쿼리 생성(작성) -> 실행
 예1) 익명 프로시저를 사용해서 동적쿼리 작성 및 실행..
DECLARE
  vdsql varchar2(1000);  
  vdeptno emp.deptno%type;
  vempno emp.empno%type;
  vename emp.ename%type;
  vjob emp.job%type;
BEGIN
  -- ㄱ. 동적 퀄리 작성
  vdsql :=  'SELECT deptno, empno, ename, job ';
  vdsql :=   vdsql || 'FROM emp ';
  vdsql :=  vdsql ||  'WHERE empno = 7369 ' ;
  -- ㄴ. 동적 쿼리 실행
  EXECUTE IMMEDIATE vdsql
                    INTO vdeptno, vempno, vename, vjob ;

  DBMS_OUTPUT.PUT_LINE( vdeptno  || ', ' || vempno || ', ' || vename || ', ' || vjob );

-- EXCEPTION
END;

 예2) 저장 프로시저를 사용해서 동적쿼리 작성 및 실행..
CREATE OR REPLACE PROCEDURE up_dselEmp 
(
  pempno emp.empno%type
)
IS
  vdsql varchar2(1000);  
  vdeptno emp.deptno%type;
  vempno emp.empno%type;
  vename emp.ename%type;
  vjob emp.job%type;
BEGIN
  -- ㄱ. 동적 퀄리 작성
  vdsql :=  'SELECT deptno, empno, ename, job ';
  vdsql :=   vdsql || 'FROM emp ';
  vdsql :=  vdsql ||  'WHERE empno = :pempno ' ;
  -- ㄴ. 동적 쿼리 실행
  EXECUTE IMMEDIATE vdsql
                    INTO vdeptno, vempno, vename, vjob
                    USING pempno;

  DBMS_OUTPUT.PUT_LINE( vdeptno  || ', ' || vempno || ', ' || vename || ', ' || vjob );

-- EXCEPTION
END;

-- Procedure UP_DSELEMP이(가) 컴파일되었습니다.

EXEC UP_DSELEMP( 7369 );

SELECT * FROM Dept;
 예3) 저장 프로시저를 사용해서 동적쿼리 작성 및 실행..  ( INSERT )
CREATE OR REPLACE PROCEDURE up_dinsDept
(
  pdname dept.dname%type
  , ploc dept.loc%type
)
IS
  vdsql varchar2(1000);  
  vdeptno dept.deptno%type; -- 50
BEGIN

    SELECT MAX(deptno)+10 INTO vdeptno FROM dept;

  -- ㄱ. 동적 퀄리 작성
  vdsql :=  'INSERT INTO dept ';
  vdsql :=   vdsql || ' VALUES ( :deptno, :dname, :loc ) '; 
  
  -- ㄴ. 동적 쿼리 실행
  EXECUTE IMMEDIATE vdsql                    
                    USING vdeptno, pdname, ploc;

  -- COMMIT;
  
-- EXCEPTION
END;

-- Procedure UP_DINSDEPT이(가) 컴파일되었습니다.
SELECT * FROM dept;

EXEC UP_DINSDEPT( 'QC', 'SEOUL');

ROLLBACK;

예4) 익명프로시저를 사용해서  동적쿼리 + DDL ( CREATE 문 )

DECLARE 
  vsql varchar2(1000);
  vtableName varchar2(20);
BEGIN
   vtableName := 'tbl_nds';
   vsql := 'CREATE TABLE ' || vtableName ;
   -- vsql := 'CREATE TABLE  :tableName ' ;
   vsql := vsql || ' ( ' ;
   vsql := vsql || '         id number primary key  ' ;
   vsql := vsql || '         , name varchar2(20)  ' ;
   vsql := vsql || ' ) ' ;
   
   DBMS_OUTPUT.PUT_LINE( vsql );
   
   EXECUTE IMMEDIATE vsql;
                 -- USING vtableName;
   
END;
-- PL/SQL 프로시저가 성공적으로 완료되었습니다.

DESC tbl_nds;

예5) [OPEN FOR] 문 설명 ? [동적 SQL] 의 실행 결과가 [여러 개의 레코드(행)] 반환하는 [SELECT]문 + [커서]

CREATE OR REPLACE PROCEDURE up_nds02
(
  pdeptno dept.deptno%type
)
IS
  vsql varchar2(1000);
  vrow emp%ROWTYPE;
  vcursor SYS_REFCURSOR; -- 9i  REF CURSOR
BEGIN
   vsql := 'SELECT * ';
   vsql := vsql || 'FROM emp ';
   vsql := vsql || 'WHERE deptno = :deptno ';
   
   -- X EXECUTE IMMEDIATE 동적쿼리   
   -- OPEN FOR 문 사용한다. 
   OPEN  vcursor FOR vsql USING pdeptno;
   
   LOOP
      FETCH vcursor INTO vrow;
      EXIT WHEN vcursor%NOTFOUND;
      DBMS_OUTPUT.PUT_LINE( vrow.empno || ', ' || vrow.ename );
   END LOOP;
   
   CLOSE vcursor;
END;

-- Procedure UP_NDS02이(가) 컴파일되었습니다.
EXEC UP_NDS02( 30 );
EXEC UP_NDS02( 10 );
Comments