[PLSQL] dense_rank()

ORACLE | 2009. 10. 24. 21:39
Posted by Haronoid
  • dense_rank() over (partition by 그룹1, 그룹2)
    • 그룹단위의 순위를 번호로 표시
    • dense_rank는 같은그룹은 전부 같은 순위로 하며, 다음그룹은 현재 순위의 다음 순위로 시작
    • 그룹단위의 표시 수를 제어할 때 사용할 수 있다
예제 SQL>
select CA1, CA2, danse_rank() over (partition by CA1, CA2)
from
(
select 'A' CA1, 'B' CA2 from dual
union all
select 'A' CA1, 'B' CA2 from dual
union all
select 'A' CA1, 'C' CA2 from dual
union all
select 'A' CA1, 'C' CA2 from dual
union all
select 'A' CA1, 'D' CA2 from dual
)
->
1: A B 1
2: A B 1
3: A C 2
4: A C 2
5: A D 3

 
  • rpad(문자열 , 표지수, 매꿔줄문자)
    • 문자열을 오른쪽에서 6번째문자까지 표현
    • 문자열이 표지수 보다 적을 경우 매꿔줄문자를 대신 체워서 표지수까지 표현
    • 문자열의 표지수위치가 멀티바이트 문자일 경우 대상 멀티바이트문자를 제외하고, 빈자리를 매꿔줄 문자로 체워서 표시
    • 바이트단위로 문자수를 계산
    • 멀티바이트에서의 문자끈김으로인한 에러처리를 안해줘도 됨
예제 SQL>
select rpad('abcd', 6, '_") from dual;
-> abcd__
select rpad('abcde한글', 6, '_") from dual;
-> abcde_
select rpad('abcd한글', 6, '_") from dual;
-> abcd한



iPhone 에서 작성된 글입니다.
 

[PLSQL] 로우단위의 누적합 구하기

ORACLE | 2009. 10. 24. 21:08
Posted by Haronoid
  • sum(대상열) over (partition by 그룹1, 그룹2 order by 누적순서)
    • "누적순서"의 순서로 "대상열"을 순차적으로 합한 값을 표현
    • partition by 를 넣는것으로 그룹단위의 누적합을 구할 수 있다..
예제 sql)
select CA1, CA2, sum(CLM1) over (partition by CA1, CA2 order by CLM2)
from (
select 1 CLM1, 1 CLM2, 'A' CA1, 'B' CA2 from dual;
union all
select 1 CLM1, 2 CLM2, 'A' CA1, 'B' CA2 from dual;
union all
select 1 CLM1, 3 CLM2, 'A' CA1, 'C' CA2 from dual;
union all
select 1 CLM1, 4 CLM2, 'A' CA1, 'C' CA2 from dual;
union all
select 1 CLM1, 5 CLM2, 'A' CA1, 'C' CA2 from dual;
)
->
1:  A B 1
2:  A B 2
3:  A C 1
4:  A C 2
5:  A C 3
 

[PLSQL] Hash형 변수 선언

ORACLE | 2009. 5. 28. 23:55
Posted by Haronoid

"변수(키) = 값" 형태로 사용가능한 변수 선언 및 사용

  1. declare
  2.     type T_HASH is table of varchar2(10) index by varchar2(10);
  3.     HASHVAL T_HASH;
  4. begin
  5.     HASHVAL('key1') := 'orange';

        HASHVAL('key2') := 'apple';

        HASHVAL('key3') := 'banana';

        dbms_output.put_line('key1=' || HASHVAL('key1'));

        dbms_output.put_line('key2=' || HASHVAL('key2'));

        dbms_output.put_line('key3=' || HASHVAL('key3'));

    end;

실행결과

  1. key2=apple

    key3=banana

    key1=orange

 

결과에서 처럼 HASHVAL변수를 ()속에 키문자열을 넣음으로서 값을 얻는것이 가능하다.

type T_HASH is table of varchar2(10) index by varchar2(10);

table of varchar2(10)을 변경해 줌으로서 결과 값의 타입을 변경할 수 있다.

index by varchar2(10)의 타입을 변경하여 키의 타입을 변경할 수 있다.

이 글은 스프링노트에서 작성되었습니다.

 

[ORA] Oracle Distinct 문제..

ORACLE | 2008. 3. 22. 21:54
Posted by Haronoid
최근 Distinct 가 행의 정렬 순서를 바꾼다는 사실이 발견..
2중 구조의 Select문에서 내부에 Order by 한 내용을 바깥에서 Distinct를 사용하면,
Order by 내용은 무시 된다.

Ex)
select distinct 1
from (
select 1 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 2 from dual
union all
select 5 from dual
union all
order by 1
)
 

[ORA] Oracle CSV 작성

ORACLE | 2008. 2. 24. 12:14
Posted by Haronoid
참고 : http://www.oracle-base.com/articles/9i/GeneratingCSVFiles.php

>사전준비
CONNECT sys/password@w2k1 AS SYSDBA
CREATE OR REPLACE DIRECTORY EXTRACT_DIR AS 'c:\oracle\extract';
GRANT READ, WRITE ON DIRECTORY EXTRACT_DIR TO SCOTT;
GRANT EXECUTE ON UTL_FILE TO SCOTT;
>실행
CONNECT scott/tiger@w2k1
CREATE OR REPLACE PROCEDURE EMP_CSV AS
  CURSOR c_data IS
    SELECT empno,
           ename,
           job,
           mgr,
           TO_CHAR(hiredate,'DD-MON-YYYY') AS hiredate,
           sal,
           comm,
           deptno
    FROM   emp
    ORDER BY ename;
    
  v_file  UTL_FILE.FILE_TYPE;
BEGIN
  v_file := UTL_FILE.FOPEN(location     => 'EXTRACT_DIR',
                           filename     => 'emp_csv.txt',
                           open_mode    => 'w',
                           max_linesize => 32767);
  FOR cur_rec IN c_data LOOP
    UTL_FILE.PUT_LINE(v_file,
                      cur_rec.empno    || ',' ||
                      cur_rec.ename    || ',' ||
                      cur_rec.job      || ',' ||
                      cur_rec.mgr      || ',' ||
                      cur_rec.hiredate || ',' ||
                      cur_rec.empno    || ',' ||
                      cur_rec.sal      || ',' ||
                      cur_rec.comm     || ',' ||
                      cur_rec.deptno);
  END LOOP;
  UTL_FILE.FCLOSE(v_file);
 
EXCEPTION
  WHEN OTHERS THEN
    UTL_FILE.FCLOSE(v_file);
END;
/
>예외처리
EXCEPTION
  WHEN UTL_FILE.INVALID_PATH THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20000, 'File location is invalid.');
   
  WHEN UTL_FILE.INVALID_MODE THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20001, 'The open_mode parameter in FOPEN is invalid.');

  WHEN UTL_FILE.INVALID_FILEHANDLE THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20002, 'File handle is invalid.');

  WHEN UTL_FILE.INVALID_OPERATION THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20003, 'File could not be opened or operated on as requested.');

  WHEN UTL_FILE.READ_ERROR THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20004, 'Operating system error occurred during the read operation.');

  WHEN UTL_FILE.WRITE_ERROR THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20005, 'Operating system error occurred during the write operation.');

  WHEN UTL_FILE.INTERNAL_ERROR THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20006, 'Unspecified PL/SQL error.');

  WHEN UTL_FILE.CHARSETMISMATCH THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20007, 'A file is opened using FOPEN_NCHAR, but later I/O ' ||
                                    'operations use nonchar functions such as PUTF or GET_LINE.');

  WHEN UTL_FILE.FILE_OPEN THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20008, 'The requested operation failed because the file is open.');

  WHEN UTL_FILE.INVALID_MAXLINESIZE THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20009, 'The MAX_LINESIZE value for FOPEN() is invalid; it should ' ||
                                    'be within the range 1 to 32767.');

  WHEN UTL_FILE.INVALID_FILENAME THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20010, 'The filename parameter is invalid.');

  WHEN UTL_FILE.ACCESS_DENIED THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20011, 'Permission to access to the file location is denied.');

  WHEN UTL_FILE.INVALID_OFFSET THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20012, 'The ABSOLUTE_OFFSET parameter for FSEEK() is invalid; ' ||
                                    'it should be greater than 0 and less than the total ' ||
                                    'number of bytes in the file.');

  WHEN UTL_FILE.DELETE_FAILED THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20013, 'The requested file delete operation failed.');

  WHEN UTL_FILE.RENAME_FAILED THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE_APPLICATION_ERROR(-20014, 'The requested file rename operation failed.');

  WHEN OTHERS THEN
    UTL_FILE.FCLOSE(v_file);
    RAISE;
END;

 
참고 : http://www.adp-gmbh.ch/ora/sql/create_directory.html

우선 디렉토리를 마운트해야 한다.
명령은 Create Directiory
【형식】
    CREATE [OR REPLACE] DIRECTORY 객체명 AS 경로명

• object명에 schema는 기술할 수 없다.
• directory의 길이는 30byte를 넘을 수 없다.
• path명에 file이 위치해 있는 OS의 절대경로를 기술한다.
• CREATE ANY DIRECTORY 시스템 권한이 있아야 한다.
예제)
읽어올 데이터 파일이
/temp/data
폴더라면

1. 디렉토리를 생성
SQL> conn system/manager as sysdba

SQL> create directory test_dir
  2  AS '/temp/data';
 
2. 사용자에게 디렉도리 권한을 부여
SQL> grant read,write on directory test_dir to scott;

3. 사용자로 접속
SQL> conn scott/tiger
Connected.

create or replace directory foo_dir as '/tmp';

create directory some_dir;
grant read, write on directory some_dir to micky_mouse;

create or replace directory dir_temp as 'c:\temp';

declare
  f utl_file.file_type;
begin
  f := utl_file.fopen('DIR_TEMP', 'something.txt', 'w');
  utl_file.put_line(f, 'line one: some text');
  utl_file.put_line(f, 'line two: more text');
  utl_file.fclose(f);
end;
/
SQL> create or replace directory UTL_FILE_DIR as '/opt/oracle/utl_file';


Directory created.

SQL> declare
  2    fhandle utl_file.file_type;
  3  begin
  4    fhandle := utl_file.fopen('UTL_FILE_DIR', 'example.txt', 'w');
  5    utl_file.put_line(fhandle , 'eygle test write one');
  6    utl_file.put_line(fhandle , 'eygle test write two');
  7    utl_file.fclose(fhandle);
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL> !
[oracle@jumper 9.2.0]$ more /opt/oracle/utl_file/example.txt
eygle test write one
eygle test write two
[oracle@jumper 9.2.0]$
SQL> declare
  2    fhandle   utl_file.file_type;
  3    fp_buffer varchar2(4000);
  4  begin
  5    fhandle := utl_file.fopen ('UTL_FILE_DIR','example.txt', 'R');
  6 
  7    utl_file.get_line (fhandle , fp_buffer );
  8    dbms_output.put_line(fp_buffer );
  9    utl_file.get_line (fhandle , fp_buffer );
 10    dbms_output.put_line(fp_buffer );
 11    utl_file.fclose(fhandle);
 12  end;
 13  /
eygle test write one
eygle test write two

PL/SQL procedure successfully completed.
SQL> select * from dba_directories;

OWNER                          DIRECTORY_NAME                 DIRECTORY_PATH
------------------------------ ------------------------------ ------------------------------
SYS                            UTL_FILE_DIR                   /opt/oracle/utl_file
SYS                            BDUMP_DIR                      /opt/oracle/admin/conner/bdump
SYS                            EXP_DIR                        /opt/oracle/utl_file
SQL> drop directory exp_dir;

Directory dropped

SQL> select * from dba_directories;

OWNER                          DIRECTORY_NAME                 DIRECTORY_PATH
------------------------------ ------------------------------ ------------------------------
SYS                            UTL_FILE_DIR                   /opt/oracle/utl_file
SYS                            BDUMP_DIR                      /opt/oracle/admin/conner/bdump

 

[ORA] External Table

ORACLE | 2008. 2. 24. 11:54
Posted by Haronoid
참고 : http://radiocom.kunsan.ac.kr/lecture/oracle/statement_create/create_external_table.html
http://www.psoug.org/reference/externaltab.html


external 테이블은 DB 외부에 저장된 data 파일을 조작하기 위한 접근 방법의 하나로 읽기 전용 테이블이다.
external 테이블의 실제 데이터는 DB 외부에 존재하지만, external 테이블에 대한 metadata는 DB 내부에 존재하는 일종의 가상 테이블이다.
주로 ETL(extraction, transformation, loading)에 주로 사용되는데, ETL은 일종의 tool로 data 파일에 접근하고 조작하여 그 결과를 오라클 내로 loading하는 동작이다.

External 테이블에 대한 두 가지 access drivers
1) LOADER ACCESS DRIVER(oracle loader) :
Oracle의 Loader 기능을 이용해 external table로부터 데이터를 읽어 오는데 사용(SQL*Loader에 의해 해석될 수 있는 어떤 데이터 유형도 access 가능)
2) Import/Export ACCESS DRIVER(oracle Internal) :
Platform에 상관 없이 데이터의 Importing/Exporting이 가능

CREATE DIRECTORY 명령문을 사용하여 file의 위치 정보를 가진 객체를 먼저 생성한 후 CREATE TABLE 명령에 ORGANIZATION EXTERNAL이라는 절을 사용하여 external 테이블을 생성할 수 있다.

특징
 - 형식 : CREATE TABLE ....
ORGANIZATION EXTERNAL
- Read Olny
- DML작업 불가능
- Index 생성 불가능

----------------------------------------------------------------------------------------------------
1) CREATE TABLE 명령을 사용하여 external table을 생성한다.
external table은 SQL 명령문을 사용하여 질의가 가능하며, external table에 대해 DML 작업을 수행 할 수 없다. 또한 external table에 대한 index 생성이 불가능하다.

【형식】
    CREATE TABLE [스키마.]테이블명
    컬럼명 데이터타입 [DEFAULT 값]...
    ORGANIZATION EXTERNAL (
    [TYPE access_driver형식]
    [DEFAULT DIRECTORY 객체명]
    [ACCESS PARAMETERS (access_parameters절...)]
    [LOCATION (경로:파일명...)]
    [REJECT LIMIT n | UNLIMITED]

• type : 접근방식을 기술하는것으로 oracle loader나 oracle internal 방식중 하나(default=oracle loader)
• default directory : external table의 위치 정보를 가진 object를 사용
• create directory : 명령어를 사용하여 생성한 object를 기술한다. access driver가 error에 대한 log 정보를 기록하기 위해서도 사용
• access_parameters : access driver의 parameter를 정의 한다. log file, discard file, bad file을 적을 수 있다.
• location : 각 external data source에 대한 external locator를 기술하는 곳으로주로 file을 사용한다.경로가 생략된 경우, default directory에 지정한 경로를 사용한다.
• reject limits : bad file에 저장되는 reject된 data의 건수를 제한한다. 디폴트=0, bad file은 access parameter 절에기술한다.
----------------------------------------------------------------------------------------------------
2) 우선 External table을 생성하기 전에 external table의 위치 정보를 가진 object를 생성한다.
CREATE DIRECTORY명령문을 사용하여 file의 위치 정보를 가진 object를 생성한다.

【형식】
    CREATE [OR REPLACE] DIRECTORY 객체명 AS 경로명

• object명에 schema는 기술할 수 없다.
• directory의 길이는 30byte를 넘을 수 없다.
• path명에 file이 위치해 있는 OS의 절대경로를 기술한다.
• CREATE ANY DIRECTORY 시스템 권한이 있아야 한다.

【예제】
1단계) 읽어올 데이터 파일
$ pwd  
/export/home/oracle/app/oracle/oradata
$ cat test.txt
0111,"COREA",
0222,"CHINA",
$

2단계) 디렉토리 만들기
SQL> conn system/manager as sysdba

SQL> create directory test_dir
  2  AS '/export/home/oracle/app/oracle/oradata';
 
디렉토리가 생성되었습니다.
 
SQL> grant read,write on directory test_dir to scott;
 
권한이 부여되었습니다.
 
SQL> conn scott/tiger
Connected.
 
세션이 변경되었습니다.
 
SQL>

3단계) 테이블 만들기(외부 데이터 읽어올)

SQL> create table test_ext (
  2    aa number(4),
  3    bb char(5))
  4  ORGANIZATION EXTERNAL         ☜ external table 생성을 의미
  5   (type oracle_loader        ☜ SQL*Loader를 사용하여 데이터를 load함
  6    default directory test_dir     ☜ 미리 생성한 directory object를 기술
  7    access parameters (        ☜ access driver의 변수값 지정
  8      records delimited by newline    ☜ 줄바꿈으로 record를 구분
  9      badfile 'test_bad.bad'        ☜ loading되지 못한 record를 저장할 file
 10      logfile 'test_log.log'        ☜ log 기록을 저장하는 file
 11      fields terminated by ',' optionally enclosed by '"'    ☜컬럼 구분시 컴마(,) 사용
 12       (aa, bb))
 13      location('test.txt'))        ☜ 읽어올 외부 파일의 이름
 14  reject limit unlimited;         ☜ bad file에 저장되는 unload되는 record 제한
 
테이블이 생성되었습니다.
 
SQL> select * from test_ext;
 
        AA BB
---------- -----
       111 COREA
       222 CHINA
 
SQL> 
SQL> desc test_ext;
 이름                  널?      유형
 --------------------- -------- ----------------------------
 AA                             NUMBER(4)
 BB                             CHAR(5)
 
SQL> select * from tab;
 
TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
DEPT                           TABLE
EMP                            TABLE
BONUS                          TABLE
SALGRADE                       TABLE
TEST_EXT                       TABLE
 
SQL>

 

ROW_NUMBER() OVER(ORDER BY CLMNAME)

ORACLE | 2007. 8. 21. 15:33
Posted by Haronoid
SELECT시 컬럼에 로우번호 넣기
ROW_NUMBER() OVER(PARTITION BY 패턴컬럼명 ORDER BY 정렬컬럼명)
  • ROW_NUMBER()번호를 넣는 함수 뒤에 OVER와 ORDER BY가 필수
  • PARTITION BY 키워드로 패턴별로 번호를 넣을수 있다.
  • ORDER BY에 ROWID를 넣으면 기존의 (로우)순서로 나오게 된다.
  • 오라클9i이후 버전부터 유효하다.

ex) ROW_NUMBER() OVER(ORDER BY CLM)
//테이블의 100번째부터 300번째까지의 라인을 출력
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY ROWID) ROW_NO,
TABLE_NAME.*
FROM TABLE_NAME )
WHERE ROW_NO BETWEEN 100 AND 300;

ex) PARTITION BY
아래의 결과를
------------------
| COL_1 | COL_2 |
|----------------|
| A | A1 |
| A | B1 |
| A | C1 |
| B | A2 |
| B | B2 |
| B | C2 |
| B | D2 |
| C | A3 |
| C | B3 |
| C | C3 |
| C | D3 |
| D | A4 |
| D | B4 |
| D | C4 |
------------------아래처럼 출력
--------------------
| COL_1 | COL_2 | NO
|-------------------
| A | A1 | 1
| A | B1 | 2
| A | C1 | 3
| B | A2 | 1
| B | B2 | 2
| B | C2 | 3
| B | D2 | 4
| C | A3 | 1
| C | B3 | 2
| C | C3 | 3
| C | D3 | 4
| D | A4 | 1
| D | B4 | 2
| D | C4 | 3
------------------
SELECT COL_1,
            COL_2,
            ROW_NUMBER() OVER(PARTITION BY COL_1 ORDER BY COL_2) NO
FROM TABLE_NAME

 

커맨드실행 SQLPLUS로 직접 SQL화일실행

ORACLE | 2007. 8. 21. 14:45
Posted by Haronoid
커맨드에서 sqlplus로 저장된 sql화일을 실행한다.
sqlplus userid/password @화일명

ex)
>sqlplus scott/scott @start.sql
 
블로그 이미지

Haronoid

기본적으로 프로그래밍 관련 메모를 중점으로 합니다. 자세한 설명이 결여되어 있을 가능성이 있습니다.

카테고리

분류 전체보기 (29)
프로그래밍 기본 (1)
VB&VBA (1)
JAVA (0)
ORACLE (10)
WidnowsCommandLine (2)
Excel (1)
Windows (1)
.NET (6)
MS SQL (6)