일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- oracle
- solaris network
- Unix
- Network
- grid
- bash
- mariaDB
- rac
- 오라클
- MySQL
- PERL
- SQL
- perl one-liner
- 연산자
- patch
- php5
- fdisk
- dba
- sqlplus
- Oracle RAC
- oracle install
- solaris
- memory
- cygwin
- command & perl
- perl + 정규표현식
- prompt
- RHEL4
- perl string
- Linux
Archives
- Today
- Total
DATA 전문가로 가는 길
[SQL] Oracle Merge 문법 자동 생성기(PL/SQL) 본문
오라클 Marge문을 자동으로 생성 하는 방법에 대해서 작성하고자 합니다. 업무를 진행할 때 Insert와 Update를 동시에 하고자 한다면 Merge문을 최대한 활용하게 됩니다. 한번 작성하면 다시 변경할 일을 없기는 하지만, 여러개의 원장 데이터를 서비스 테이블로 옮기는 작업을 매번 진행할 때 유용하게 사용 가능 합니다.
따라서 아래 내용은 단일 테이블을 기준으로 작성했으나, 필요에 따라 프로시저를 반복 호출해서 사용해도 됩니다.
1. Oracle Merge문 자동 생성 PL/SQL
DECLARE V_OWNER VARCHAR2(30); V_PE_TABLE_NM VARCHAR2(40); V_PT_TABLE_NM VARCHAR2(40); BEGIN V_OWNER := 'HR'; /* 스키마명 */ V_PE_TABLE_NM := 'EMPLOYEES'; /* 원장 테이블명 */ V_PT_TABLE_NM := 'EMPLOYEES'; /* 타겟 테이블명 */ DECLARE CURSOR C IS SELECT A.OWNER ,A.TABLE_NAME ,A.COLUMN_NAME ,A.DATA_TYPE ,A.COLUMN_ID ,A.LAST_COLUMN_ID ,b.COLUMN_NAME AS PK_COLUMN_NAME FROM ( SELECT A.OWNER ,A.TABLE_NAME ,A.COLUMN_NAME ,DECODE(A.DATA_TYPE, 'VARCHAR2', A.DATA_TYPE||'('||A.DATA_LENGTH||')' , 'CHAR', A.DATA_TYPE||'('||A.DATA_LENGTH||')' , 'NUMBER' , A.DATA_TYPE||'('||A.DATA_PRECISION||', '||A.DATA_SCALE||')' , 'DATE', 'DATE') AS DATA_TYPE ,A.COLUMN_ID AS COLUMN_ID ,LAST_VALUE(A.COLUMN_ID) OVER (PARTITION BY A.TABLE_NAME ORDER BY A.COLUMN_ID RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS LAST_COLUMN_ID -- 테이블 컬럼ID 중에서 최고 값 FROM DBA_TAB_COLUMNS A WHERE A.OWNER = V_OWNER AND A.TABLE_NAME = V_PT_TABLE_NM /* 특정 테이블에 대해서 만들 경우 */ ) A, ( SELECT B.COLUMN_NAME FROM DBA_CONSTRAINTS A ,DBA_CONS_COLUMNS B WHERE A.OWNER = V_OWNER AND A.TABLE_NAME = V_PT_TABLE_NM AND A.CONSTRAINT_TYPE = 'P' /* PK 컬럼을 조회 */ AND B.OWNER = A.OWNER AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME AND B.TABLE_NAME = A.TABLE_NAME ) B WHERE B.COLUMN_NAME (+)= A.COLUMN_NAME ORDER BY A.TABLE_NAME, A.COLUMN_ID ; BEGIN -- Oracle Merge Auto Script Start DBMS_OUTPUT.PUT_LINE('MERGE INTO '|| V_OWNER ||'.'||V_PT_TABLE_NM||' A USING'); DBMS_OUTPUT.PUT_LINE(' ('); DBMS_OUTPUT.PUT_LINE(' SELECT'); FOR CTL_LIST IN C LOOP -- SQL*Loader Control File 형식에 해당하는 콤마(,)를 마지막에는 제거 함. IF CTL_LIST.COLUMN_ID <> CTL_LIST.LAST_COLUMN_ID THEN DBMS_OUTPUT.PUT_LINE( ' S.' || CTL_LIST.COLUMN_NAME || ',' ); ELSE DBMS_OUTPUT.PUT_LINE( ' S.' || CTL_LIST.COLUMN_NAME ); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE(' FROM '|| V_OWNER ||'.'||V_PE_TABLE_NM||' S'); DBMS_OUTPUT.PUT_LINE(' ) B'); DBMS_OUTPUT.PUT_LINE('ON ('); FOR CTL_LIST IN C LOOP -- SQL*Loader Control File 형식에 해당하는 콤마(,)를 마지막에는 제거 함. IF CTL_LIST.PK_COLUMN_NAME IS NOT NULL AND CTL_LIST.COLUMN_ID = 1 THEN DBMS_OUTPUT.PUT_LINE( ' A.' || CTL_LIST.COLUMN_NAME || ' = B.' ||CTL_LIST.COLUMN_NAME ); ELSIF CTL_LIST.PK_COLUMN_NAME IS NOT NULL AND CTL_LIST.COLUMN_ID != 1 THEN DBMS_OUTPUT.PUT_LINE( ' AND A.' || CTL_LIST.COLUMN_NAME || ' = B.' ||CTL_LIST.COLUMN_NAME ); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE(' )'); DBMS_OUTPUT.PUT_LINE('WHEN MATCHED THEN'); DBMS_OUTPUT.PUT_LINE(' UPDATE SET'); FOR CTL_LIST IN C LOOP IF CTL_LIST.PK_COLUMN_NAME IS NULL THEN -- SQL*Loader Control File 형식에 해당하는 콤마(,)를 마지막에는 제거 함. IF CTL_LIST.COLUMN_ID <> CTL_LIST.LAST_COLUMN_ID THEN DBMS_OUTPUT.PUT_LINE( ' A.' || CTL_LIST.COLUMN_NAME || ' = B.' ||CTL_LIST.COLUMN_NAME || ',' ); ELSE DBMS_OUTPUT.PUT_LINE( ' A.' || CTL_LIST.COLUMN_NAME || ' = B.' ||CTL_LIST.COLUMN_NAME ); END IF; END IF; END LOOP; DBMS_OUTPUT.PUT_LINE('WHEN NOT MATCHED THEN '); DBMS_OUTPUT.PUT_LINE(' INSERT '); DBMS_OUTPUT.PUT_LINE(' ( '); FOR CTL_LIST IN C LOOP -- SQL*Loader Control File 형식에 해당하는 콤마(,)를 마지막에는 제거 함. IF CTL_LIST.COLUMN_ID <> CTL_LIST.LAST_COLUMN_ID THEN DBMS_OUTPUT.PUT_LINE( ' A.' || CTL_LIST.COLUMN_NAME || ',' ); ELSE DBMS_OUTPUT.PUT_LINE( ' A.' || CTL_LIST.COLUMN_NAME ); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE(' ) '); DBMS_OUTPUT.PUT_LINE(' VALUES '); DBMS_OUTPUT.PUT_LINE(' ( '); FOR CTL_LIST IN C LOOP -- SQL*Loader Control File 형식에 해당하는 콤마(,)를 마지막에는 제거 함. IF CTL_LIST.COLUMN_ID <> CTL_LIST.LAST_COLUMN_ID THEN DBMS_OUTPUT.PUT_LINE( ' B.' || CTL_LIST.COLUMN_NAME || ',' ); ELSE DBMS_OUTPUT.PUT_LINE( ' B.' || CTL_LIST.COLUMN_NAME ); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE(' ) '); DBMS_OUTPUT.PUT_LINE(';'); END; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERROR'); NULL; END; --
2. DBMS Output 결과
- HR 스키마에 속한 EMPLOYEES 테이블을 기준으로 Merge 문법을 자동으로 확인 가능 합니다.
- USING 절에 있는 원장 데이터에 대한 내용은 용도에 따라 변경 하시면 됩니다.
MERGE INTO HR.EMPLOYEES A USING ( SELECT S.EMPLOYEE_ID, S.FIRST_NAME, S.LAST_NAME, S.EMAIL, S.PHONE_NUMBER, S.HIRE_DATE, S.JOB_ID, S.SALARY, S.COMMISSION_PCT, S.MANAGER_ID, S.DEPARTMENT_ID FROM HR.EMPLOYEES S ) B ON ( A.EMPLOYEE_ID = B.EMPLOYEE_ID ) WHEN MATCHED THEN UPDATE SET A.FIRST_NAME = B.FIRST_NAME, A.LAST_NAME = B.LAST_NAME, A.EMAIL = B.EMAIL, A.PHONE_NUMBER = B.PHONE_NUMBER, A.HIRE_DATE = B.HIRE_DATE, A.JOB_ID = B.JOB_ID, A.SALARY = B.SALARY, A.COMMISSION_PCT = B.COMMISSION_PCT, A.MANAGER_ID = B.MANAGER_ID, A.DEPARTMENT_ID = B.DEPARTMENT_ID WHEN NOT MATCHED THEN INSERT ( A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.EMAIL, A.PHONE_NUMBER, A.HIRE_DATE, A.JOB_ID, A.SALARY, A.COMMISSION_PCT, A.MANAGER_ID, A.DEPARTMENT_ID ) VALUES ( B.EMPLOYEE_ID, B.FIRST_NAME, B.LAST_NAME, B.EMAIL, B.PHONE_NUMBER, B.HIRE_DATE, B.JOB_ID, B.SALARY, B.COMMISSION_PCT, B.MANAGER_ID, B.DEPARTMENT_ID ) ;
'Data Architecture > SQL Query' 카테고리의 다른 글
[SQL] MariaDB/MySQL 테이블 비교(Compare two table) (0) | 2019.07.29 |
---|---|
[SQL] MariaDB/MySQL 테이블 일련번호 중간에 빈 값 찾기 (0) | 2019.07.24 |
[SQL] MariaDB/MySQL MAX/MIN 최고값 최저값의 세부 속성 데이터 활용하기(최고일시, 최저일시 등) (0) | 2017.03.24 |
[SQL] Oracle 필수 스크립트 모음(딕셔너리, SQL 문법, 성능 분석) (0) | 2017.03.13 |
[SQL] MariaDB/Mysql 구분자(콤마, 파이프라인 등등)를 기준으로 열(row) 변환 (2) | 2017.02.16 |
Comments