블로그 이미지
신비마마

태그목록

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

calendar

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 31

처음 ORA-3136을 접했을때 생각해봤던 건데 도움이 될까 해서 정리해서 올립니다.

 10g가 되면서 inbound_connect_timeout 이 60초로 바뀌게 되었고 그로 인해서 가끔씩 alert에 제목과 같은 메지시가 나오곤 합니다.

 우선 ORA-3136이 발생되는 경우를 살펴보면

 CASE 1

 WIPPY@/oracle> sqlplus /@rac1
SQL*Plus: Release 10.2.0.4.0 - Production on Wed Jan 7 13:33:27 2009
Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.
ERROR:
ORA-01017: invalid username/password; logon denied
Enter user-name:

 이상태에서 타이핑 없이 대기를 하게되면 60초 후에 alert log에 ORA-3136 이 떨어지게 됩니다.

 그렇다면 그 60초 동안 어떤일이 발생하는가?

 1. ps -ef|grep LOCAL=NO 로 확인해 보면 process가 하나 늘어나 있는 것을 볼 수 있습니다.

 2. v$process 나 v$resource_limit를 보면 process가 하나 늘어나 있는 것을 볼 수 있습니다.

 위를 통해서 60초를 강제로 설정해 놓은 이유를 알 수 있습니다.

 누군가 악의적인 목적으로 저런식의 접속을 한다음 끊지 않으면 설정해 놓은 process개수를 다 채워버리게 되고 정상적인 connection이 처리되지 못하는 문제가 있겠죠. 따라서 60초를 주기로 oracle에서는 저런 process를 강제로 죽이는 것입니다.

 ORA-3136을 발생시키지는 않지만 유사한 경우가 있습니다.

 CASE 2

WIPPY@/oracle> telnet 192.168.0.11 1521
Trying 192.168.0.11...
Connected to 192.168.0.11 (192.168.0.11).
Escape character is '^]'.

위와 같이 했을 경우에는 다음과 같은 현상이 나타나게 됩니다.

1. ps -ef|grep LOCAL=NO 로 확인해 보면 process하나 늘어나 있는 것을 볼 수 있습니다.

2. v$process 나 v$resource_limit를 보면 변화가 없습니다.

즉 OS상에서는 process가 뜨지만 oracle의 view에는 반영이 되지 않는 상황입니다.

이러한 상황도 system resource를 사용하는 것이기 때문에 그다지 좋은 상황은 아니겠죠.

위에 유사한 두가지 CASE에 대해서 설명을 했는데 ORA-3136 에 대해서 좀 찾아보신 분들은 알겠지만 이 메세지를 안나오게 하기위해서는 sqlnet.ora 에 SQLNET.INBOUND_CONNECT_TIMEOUT = 0 설정을 하거나 listener.ora에 INBOUND_CONNECT_TIMEOUT_<listener_name> = 0 을 설정하라고 합니다.

제가 테스트 해본 결과에 의하면

sqlnet.ora - SQLNET.INBOUND_CONNECT_TIMEOUT = 0 : sqlplus /@RAC1 에만 영향을 줍니다.

listener.ora - INBOUND_CONNECT_TIMEOUT_<listener_name> = 0  : telnet 192.168.0.11 1521 에만 영향을 줍니다.

즉 APP의 접속 형태에 따라 sqlner.ora와 listener.ora를 취사선택하거나 둘다 설정을 해야할 필요성이 있는 것입니다. INBOUND_CONNECT_TIMEOUT을 설정할때는 위와 같은 내용을 인지하고 설정을 하셔야 할것으로 생각됩니다. 무작정 ERROR를 보이지 않게 하기 위해서 설정을 한다면 보안상 심각한 문제를 야기할 수도 있으니까요.

즉 ORA-3136이 발생하게 되면 connection이 늦게 처리되는 APP에 대해서 먼저 확인하고 60초 안에 접속이 이루어 지도록 APP단의 수정을 해야 하는 것이 우선이라고 생각합니다.

## 10.2.0.4 linux에서 테스트한 결과 입니다. 버전에 따라 차이가 있을 수 있음을 .. 이해하시길..

 

1. as of timestamp로 테이블 데이터 복구하기
   - > select * from 테이블명 as of timestamp to_timestamp (날짜,날짜형식) 또는 sysdate-5/1440 

2. as of timestamp로 프로시져 복구하기
   - > select * from dba_source as of timestamp to_timestamp (날짜,날짜형식) 또는 sysdate-5/1440  where name = '프로시져명'

Sample query)
SQL> select obj#,name from obj$ as of timestamp  sysdate-5/1440
          where name =’SP_TEST’;

SQL> select obj#,source from source$ as of timestamp sysdate-6/1440
          where obj#=53258;

3. Recyclebin의 테이블 복구하기
Flashback Drop - Procedure
In Oracle 10g, when you drop a table, the table is not really dropped. Rather, the table is renamed. The data in the table is still available. You can use the Flashback Drop technologies to recover an accidentally dropped table. The procedure is as follows,


Step 1: Check whether the dropped table is still available in the recycle bin, command.

User level

Scott@prod> show recyclebin;

Database level

dba@prod> Select * from dba_recyclebin;

The original_name column shows the dropped table’s original name. It also has the recycle bin’s name and the dropped time.

Step 2: Use the Flashback Drop command to recover the table

Scott@prod> Flashback Table Employees to before drop [Rename to New_Employees];

Or you can use the system generated name as follows

Scott@prod> Flashback Table “BIN$YkyfmFKl8MLgQwppGAzwwg==$0" to before drop [Rename to New_Employees];

Step 3: To permanently drop the table.

Scott@prod> Drop Table Employees purge;

Scott@prod> purge dba_recyclebin;
Related Posts : Flashback Recovery Timestamp and SCN Conversion
Flashback Table - Privileges
Flashback Table - Procedure
Flashback Query
Important Points - Flashback Table

10g/9i에서 LINKAGG 함수를 만들어보자

2010. 1. 25. 17:53 | Posted by 신비마마

ASK TOM_Oracle : [멋져부러~]

9i:

SELECT deptno, CURSOR(SELECT * FROM emp where deptno=dept.deptno) nested_TABLE
  FROM dept;

-- User defined agregate through pipelined function 
CREATE or replace FUNCTION CONCAT_LIST( cur SYS_REFCURSOR )
  RETURN  VARCHAR2 IS
    ret VARCHAR2(32000);
    tmp VARCHAR2(4000);
BEGIN
    loop
        fetch cur into tmp;
        exit when cur%NOTFOUND;
            ret := ret || ',' || tmp;
    end loop;
    RETURN ret;
END;
/

SELECT distinct
    deptno,
    SUBSTR(CONCAT_LIST(CURSOR(
        SELECT ename FROM emp ee WHERE e.deptno = ee.deptno
    )),1,40) employees
FROM emp e;


Followup   November 28, 2001 - 2pm Central time zone:

Or, even better, in 9i -- use a user defined aggregate so you don't have run the concat_list 
function once per row and then through out the dups (it would be better to write:

  select deptno, SUBSTR(CONCAT_LIST(CURSOR(
        SELECT ename FROM emp ee WHERE e.deptno = ee.deptno
    )),1,40) employees
    from ( select distinct deptno from emp );

)


But a good general purpose solution is:


scott@ORA9I.WORLD> create or replace type StringAggType as object
  2  (
  3     theString varchar2(4000),
  4  
  5     static function
  6          ODCIAggregateInitialize(sctx IN OUT StringAggType )
  7          return number,
  8  
  9     member function
 10          ODCIAggregateIterate(self IN OUT StringAggType ,
 11                               value IN varchar2 )
 12          return number,
 13  
 14     member function
 15          ODCIAggregateTerminate(self IN StringAggType,
 16                                 returnValue OUT  varchar2,
 17                                 flags IN number)
 18          return number,
 19  
 20     member function
 21          ODCIAggregateMerge(self IN OUT StringAggType,
 22                             ctx2 IN StringAggType)
 23          return number
 24  );
 25  /

Type created.

scott@ORA9I.WORLD> 
scott@ORA9I.WORLD> create or replace type body StringAggType
  2  is
  3  
  4  static function ODCIAggregateInitialize(sctx IN OUT StringAggType)
  5  return number
  6  is
  7  begin
  8      sctx := StringAggType( null );
  9      return ODCIConst.Success;
 10  end;
 11  
 12  member function ODCIAggregateIterate(self IN OUT StringAggType,
 13                                       value IN varchar2 )
 14  return number
 15  is
 16  begin
 17      self.theString := self.theString || ',' || value;
 18      return ODCIConst.Success;
 19  end;
 20  
 21  member function ODCIAggregateTerminate(self IN StringAggType,
 22                                         returnValue OUT varchar2,
 23                                         flags IN number)
 24  return number
 25  is
 26  begin
 27      returnValue := rtrim( ltrim( self.theString, ',' ), ',' );
 28      return ODCIConst.Success;
 29  end;
 30  
 31  member function ODCIAggregateMerge(self IN OUT StringAggType,
 32                                     ctx2 IN StringAggType)
 33  return number
 34  is
 35  begin
 36      self.theString := self.theString || ',' || ctx2.theString;
 37      return ODCIConst.Success;
 38  end;
 39  
 40  
 41  end;
 42  /

Type body created.

scott@ORA9I.WORLD> 
scott@ORA9I.WORLD> CREATE or replace
  2  FUNCTION stringAgg(input varchar2 )
  3  RETURN varchar2
  4  PARALLEL_ENABLE AGGREGATE USING StringAggType;
  5  /

Function created.

scott@ORA9I.WORLD> 
scott@ORA9I.WORLD> column enames format a30
scott@ORA9I.WORLD> select deptno, stringAgg(ename) enames
  2    from emp
  3   group by deptno
  4  /

    DEPTNO ENAMES
---------- ------------------------------
        10 CLARK,KING,MILLER
        20 SMITH,FORD,ADAMS,SCOTT,JONES
        30 ALLEN,BLAKE,MARTIN,TURNER,JAME
           S,WARD


scott@ORA9I.WORLD> 

Oracle 11g의 LINKAGG를 10g/9i에서 써보자

2010. 1. 25. 17:49 | Posted by 신비마마
오동규 님의 블로그에 세로로 출력되는 데이터를 가로로 출력하는 몇 가지 재미있는 기법들 소개되고 있다.

즉 아래와 같은 데이터를

SELECT DEPTNO, ENAME
FROM EMP;

DEPTNO ENAME
------ ----------
10 CLARK
10 KING
10 MILLER
20 SMITH
20 ADAMS
20 FORD
20 SCOTT
20 JONES
30 ALLEN
30 BLAKE
30 MARTIN
30 JAMES
30 TURNER
30 WARD


아래와 같이 출력하기를 원한다.

DEPTNO ENAME
------- ------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES


이런 요구사항은 매우 빈번하고 또 일반적이다.

이 블로그에서는 Oracle, MySQL, SQL Server 등에서 이런 출력을 가능하게 하는 다양한 방법을 소개하고 있다. Oracle에서 사용 가능한 방법은 다음과 같이 소개되어 있다.

select deptno,
ltrim(sys_connect_by_path(ename,','),',') ename
from (
select deptno,
ename,
row_number() over (partition by deptno order by empno) rn,
count(*) over (partition by deptno) cnt
from emp
)
where level = cnt
start with rn = 1
connect by prior deptno = deptno and prior rn = rn-1 ;


analytic function과 connect by를 적절히 이용하는 강력한 기법이다. (MySQL는 간단한 함수 하나로 이것을 할 수 있다는게 부러울 따름이다!)

이에 덧붙여 Oracle에서 비슷한 효과를 낼 수 있는 간단한 기법 하나를 소개하고자 한다.
간단한 기법이란 아래와 같이 Cursor 함수를 사용하는 것이다.

SCOTT@ukja10> select
  2  e.deptno, cursor(select ename from emp where deptno = e.deptno)
  3  from emp e
  4  group by e.deptno
  5  ;


출력 결과는 다음과 같다.

    DEPTNO CURSOR(SELECTENAMEFR
---------- --------------------
        30 CURSOR STATEMENT : 2

CURSOR STATEMENT : 2

ENAME
------------------------------
ALLEN
WARD
MARTIN
BLAKE
TURNER
JAMES

6 rows selected.

        20 CURSOR STATEMENT : 2

CURSOR STATEMENT : 2

ENAME
------------------------------
SMITH
JONES
SCOTT
ADAMS
FORD

        10 CURSOR STATEMENT : 2

CURSOR STATEMENT : 2

ENAME
------------------------------
CLARK
KING
MILLER


엄밀하게 말하면 가로로 출력하는게 아니라 Cursor를 컬럼처럼 리턴받아서 이 Cursor에 대해 Fetch를 하는 방식이다. JDBC 등에서 이를 출력받아서 Fetch 하면서 디스플레이하면 마치 가로로 출력한 것과 동일한 효과를 얻을 수 있다. 이 방법의 장점 하나는 매우 복잡한 요구 사항도 쉽게 처리가 가능하다는 것이다.

Oracle의 PL/SQL은 매우 강력해서 우리가 생각한 것보다 훨씬 많은 일을 할 수 있다. 잘 활용하면 원하는 작업을 보다 간단하게 처리할 수 있는 기회가 있을 것이다.


[출처] 오동규님의 블로그

UTL_FILE package의 설명

2010. 1. 21. 11:08 | Posted by 신비마마
◈ 테이블의 데이터를 txt파일로 생성하는 예제입니다.(UTL_FILE package)
 
    Oracle 7.3 부터 UTL_FILE package를 이용해서 OS파일에 대한 read/write를 수행할 수 있습니다.


◈ UTL_FILE package의 설명

 Function/Procedure

 Description

 FOPEN

 Input이나 Output을 위해 file을 연다.
 file이 존재하지 않을 경우 file을 생성한다.

 IS_OPEN

 file handler를 이용해 file이 open되었는지 여부를 return한다.

 FCLOSE

 file을 닫는다.

 FCLOSE_ALL

 열려 있는 모든 file을 닫는다.

 GET_LINE

 open된 file로부터 한 line을 읽는다.

 PUT

 open된 file에 한 line을 write한다.
 ( Line terminator를 붙이지 않는다.)

 PUT_LINE

 open된 file에 한 line을 write한다. ( Line terminator를 붙인다.)

 PUTF

 string을 formatting에 의해 write한다. (printf처럼)

 NEW_LINE

 open된 file에 line terminator을 write한다.

 FFLUSH

 open된 모든 file의 내용을 file에 physical하게 write한다.



◈ Oracle 7.3 부터 오라클 9i R1까지는  %ORACLE_HOME%\admin\<SID>\init<SID>.ora 파일에
    txt파일이 생성될 디렉토리를 지정해야 합니다.


   1) %ORACLE_HOME%\admin\<SID>\init<SID>.ora파일을 열어서 아래의
      파라미터를 추가합니다.
    
      UTL_FILE_DIR=C:\temp

   2) db shutdown 후 restartup함.

   3) 만약 UTL_FILE package를 인식하지 못하는 경우에 아래의 script를 실행시키면 됩니다.
        -- sys유저로 접속
           SQLPLUS sys/manager
                   
       SQL> @%ORACLE_HOME%\rdbms\admin\utlfile.sql
           ..
       SQL> @%ORACLE_HOME%\rdbms\admin\prvtfile.plb


◈ Oracle 9i R2 에서는 CREATE DIRECTORY명령으로 DIRECTORY를 생성하면 됩니다.

  1) SYS 나 SYSTEM USER 로 접속 합니다.

     C:\>SQLPLUS /NOLOG
     SQL> conn sys/manager

  2) DIRECTORY를 생성 합니다.

     SQL> CREATE DIRECTORY LOG_DIR AS 'C:\temp';
     DIRECTORY CREATED.

  3) 생성된 DIRECTORY에 대한 read권한을 부여합니다. .

     SQL> GRANT READ ON DIRECTORY log_dir TO PUBLIC;



테이블 데이터를 파일로 생성하는 예제(Oracle 9i R2에서 했습니다.)


CREATE OR REPLACE PROCEDURE PL_WriteFile(fname varchar2) IS
 
    v_output UTL_FILE.FILE_TYPE;
    v_result VARCHAR2(4000);
    CURSOR sql_cur IS
    SELECT empno, ename, deptno
    FROM emp;
    
    BEGIN
 
     v_output := UTL_FILE.FOPEN('LOG_DIR', fname, 'A');

        FOR v_cur IN sql_cur LOOP
            v_result := v_cur.empno||'  '||v_cur.ename||'  '||v_cur.deptno;
            UTL_FILE.PUT_LINE(v_output, v_result);
        END LOOP; 

        UTL_FILE.FCLOSE(v_output);

     EXCEPTION
        WHEN UTL_FILE.INVALID_PATH THEN
            DBMS_OUTPUT.PUT_LINE('INVALID PATH');
        WHEN UTL_FILE.INVALID_MODE THEN
            DBMS_OUTPUT.PUT_LINE('INVALID MODE');
        WHEN UTL_FILE.INVALID_OPERATION THEN
            DBMS_OUTPUT.PUT_LINE('INVALID OPERATION');
    END;
/
 
프로시저가 생성되었습니다.
 
SQL> exec PL_WriteFile('output.txt');
 
PL/SQL 처리가 정상적으로 완료되었습니다.
 
 C:\temp 디렉토리에 파일이 생성되었는지 확인해 보세요..




◈ 위에서 생성한 파일을 읽어와서 출력하는 예제(Oracle 9i R2에서 했습니다.)
 
   CREATE OR REPLACE PROCEDURE PL_ReadFile(fname varchar2)  IS

       v_input UTL_FILE.FILE_TYPE;              
       retrieved_buffer VARCHAR2(100); -- Line retrieved from flat file
 
  BEGIN
 
      -- 파일을 Read
      v_input :=  UTL_FILE.FOPEN('LOG_DIR',fname,'R');
 
      LOOP

         UTL_FILE.GET_LINE (v_input, retrieved_buffer);  
 
         DBMS_OUTPUT.PUT_LINE(retrieved_buffer);
 
     END LOOP;
           
     -- CLose the file.
     UTL_FILE.FCLOSE(v_input);
 
     EXCEPTION
 
        WHEN NO_DATA_FOUND THEN
             DBMS_OUTPUT.PUT_LINE('no_data_found');
             UTL_FILE.FCLOSE(v_input);
        WHEN UTL_FILE.INVALID_PATH THEN
             DBMS_OUTPUT.PUT_LINE('UTL_FILE.INVALID_PATH');
             UTL_FILE.FCLOSE(v_input);
        WHEN UTL_FILE.READ_ERROR THEN
             DBMS_OUTPUT.PUT_LINE(' UTL_FILE.READ_ERROR');
             UTL_FILE.FCLOSE(v_input);           
        WHEN OTHERS THEN
             DBMS_OUTPUT.PUT_LINE('other stuff');
             UTL_FILE.FCLOSE(v_input);
        END;
/
 

 SQL> SET SERVEROUTPUT ON;
 SQL> EXEC PL_ReadFile('output.txt');
 
 
7369  SMITH  20
7499  ALLEN  30
7521  WARD  30
7566  JONES  20
7654  MARTIN  30
7698  BLAKE  30
....

PL/SQL 처리가 정상적으로 완료되었습니다.



참고사항

 - v9.2 이전에는 utl_file function 에 대한 directory 를 access 하기 위해서는
   UTL_FILE_DIR parameter 를 init<sid>.ora file 에 기술하여야만 했습니다.
   
   그러나, UTL_FILE_DIR 을 access 하는 것에 대해 더이상 recommand 하지 않으며,
   UTL_FILE_DIR 대신에 CREATE DIRECTORY 기능을 recommand 합니다.
 
   DIRECTORY object는 application 관리자에서 보다 유연하고 융통성 있는
   제어를 제공하며, db의 shutdown 없는 dynamic 한 유지관리을 할 수 있게 합니다.
 
   CREATE DIRECTORY 에 대한 권한은 default 로 SYS 와 SYSTEM user 에 대해서만
   부여되어 있습니다.
 
 
 - UTL_FILE.FOPEN('LOG_DIR',fname,'R')에서
  'R'은 read를,'W'는 write를, 'A'는 append를 의미합니다. 


참고 : 디렉토리 패스 변경

CREATE OR REPLACE DIRECTORY
BACK_DDL AS
'/home/uniop/DB/ProcTest/sinbi_job'


 

STEP 1 : 예외의 이름을 선언(선언절)

STEP 2 : PRAGMA EXCEPTION_INIT문장으로 예외의 이름과 오라클 서버
                  오류 번호를 결합(선언절)

STEP 3 : 예외가 발생할 경우 해당 예외를 참조한다(예외절) 

 

 

리 정의되지 않은 예외 예제

SQL> CREATE OR REPLACE PROCEDURE NonPreException_Test
       IS
not_null_test    EXCEPTION; -- STEP 1
/* not_null_test는 선언된 예외 이름
-1400
Error 처리번호는 표준 Oracle7 Server Error 번호 */
PRAGMA EXCEPTION_INIT(not_null_test, -1400);       -- STEP 2
BEGIN
DBMS_OUTPUT.ENABLE;
-- empno를 입력하지 않아서 NOT NULL 에러 발생
INSERT INTO emp(ename, deptno)
VALUES(’tiger’, 30);
EXCEPTION
WHEN not_null_test THEN    -- STEP 3
DBMS_OUTPUT.PUT_LINE(’not null 에러 발생 ’);
END;
/

프로시져가 생성되었습니다.

실행 결과

SQL> SET SERVEROUTPUT ON ;    -- (DBMS_OUTPUT.PUT_LINE을 출력하기 위해 사용)

SQL> EXECUTE NonPreException_Test;
not null 에러 발생

PL/SQL 처리가 정상적으로 완료되었습니다.
 

 

  ================================================
    * 데이터베이스 정보공유 커뮤니티 oracleclub.com
    * 강좌 작성자 : 김정식 (oramaster _at_ naver.com)
  ================================================
※ oracleclub 강좌를 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
※ oracleclub 강좌는 개인의 학습용으로만 사용 할 수 있습니다. 학원 홍보용이나 수익을 얻기 위한 용도로
    사용을 하시면 안됩니다. ^^

pfile 및 spfile 수정방법과 주의점

2010. 1. 15. 17:18 | Posted by 신비마마

Oracle9i부터는 database의 initial parameter를 지정하는 initSID.ora file외에
server parameter file이라고 불리는 spfileSID.ora가 새로 소개되었다.
이 spfile을 사용하게 되면 alter system을 통해 database가 운영 중에
parameter를 수정할 수 있게 되면서 parameter 수정때마다 database를 restart
시켜야 하는 필요을 줄여주고, 앞으로 소개될 dynamic한 server tuning에
중요한 역할을 할 수 있다.

 

Explanation
-----------

이 문서에서는 이러한 spfile에 대해서 실제 사용하면서 알아두어야 할 다음과
같은 내용에 대해서 정리하였다.


1. spfile을 vi로 직접 변경한 경우의 영향
2. db open시 spfile을 읽었는지 확인하는 방법
3. initSID.ora를 spfileSID.ora로 migration하거나 그 반대의 방법
4. alter system으로 parameter변경시 scope에 대해서
5. v$parameter와 v$spparameter에 대해서 (static parameter 확인)


1. spfileSID.ora 화일을 vi로 직접 변경한 경우의 영향

   spfile이 크기 않은 관계로 vi등으로 읽으면 마치 text 화일처럼 parameter가
   보이는데 이 화일은 실제로는 binary file이므로 직접 변경하면 안된다.
   특히 이 화일의 header에는 checksum과 기본적인 meta-data 정보등을
   포함하여 manual하게 변경하게 되면 이 checksum의 값이 맞지 않게 되면서,
   이후 startup시 이 화일을 읽지 않고 initSID.ora file을 읽게 된다.

   db를 운영하면서 spfile에 계속 parameter가 변경된 경우라면 이러한 문제로
   tuning등을 통해 변경된 parameter value를 모두 잃게될 수 있는것이다.


2. db open 시 spfile을 읽었는지 확인하는 방법

   db가 open 시에 참조한 initial parameter file이 무엇인지를 확인하기
   위해서는 다음과 같이 조회하면 된다.

 

      SQL> show parameter pfile

      NAME                            TYPE        VALUE
      ------------------------------ ----------- ---------------------
      spfile                          string      ?/dbs/spfile@.ora 


   여기에서 ?는 ORACLE_HOME을 나타내고 @는 SID를 나타낸다.


3. initSID.ora를 spfileSID.ora로 migration하거나 그 반대의 방법

   spfile을 사용하다가 그 화일의 내용을 initSID.ora에 backup 차원에서
   반영시켜 두거나, 혹은 spfile대신 initSID.ora를 사용하고자 하는 경우,
   또는 반대로 initSID.ora를 참조하여 spfileSID.ora를 생성하고 하는
   경우 다음과 같이 간단히 작업하면 된다.

 

      SQL>connect / as sysdba
      SQL>create pfile='initORA9i.ora' from spfile='spfileORA9i.ora';
      SQL>create spfile='spfileORA9i.ora' from pfile='initORA9i.ora';

 

   위 문장에서 화일명 대신 직접 directory까지 절대 path로 지정할 수 있고,
   화일명은 임의로 지정 후 나중에 사용시 initSID.ora나 spfileSID.ora 형태로
   만들어줄 수 있다.
  
   default인 $ORACLE_HOME/dbs directory이고 SID가 붙는 이름 형태이면 간단히,
   다음과 같이 지정하여도 된다.

 

      SQL>create pfile from spfile;
      SQL>create spfile from pfile;

 

   sysdba 권한이 없으면 권한 부족 오류가 발생한다.

 

4. alter system으로 parameter 변경 시 scope에 대해서

   spfile을 사용하게 되면 앞에서도 언급한 것과 같이 spfile을 직접 변경하는
   대신 alter system command를 통해 initial parameter를 수정할 수 있다.

   단 이때 alter system command 뒤에 scope를 지정할 수 있는 데 scope로
   지정가능한 값은 memory/spfile/both 세가지가 된다.
   memory가 이중 default여서 scope를 지정하지 않으면 memory가 된다.

 

   memory: 변경이 현재 상태에만 영향을 미치며 db가 restartup되면,
           변경 이전값으로 돌아간다.

   spfile: 변경 내용을 spfile에만 저장하고 현재 상태에는 영향을 미치지
           않게 한다.
           static parameter의 경우는 이 scope만이 지정가능하다.
           즉, spfile을 사용하더라도 static parameter에 대해서는 db
           운영중에 바로 값을 변경하여 restartup없이 반영하는 것은 불가능
           한 것이다.

   both:   변경 내용을 현재상태에도 바로 반영하고, spfile에도 반영시켜,
           이후 rebooting시에도 영향을 미치도록 한다.

   지정하는 방법은 다음과 같다.

 

   SQL>alter system set open_cursors=300;
   SQL>alter system set open_cursors=300 scope=spfile;
   SQL>alter system set open_cursors=300 scope=both;

 

   단, spfile을 참조하지 않고 init.ora를 참조하여 db가 open한 경우 이러한
   alter system 명령을 통해 initial parameter를 변경하려고 하면
   다음과 같은 오류가 발생한다.

   특히 spfile에 외부의 변경이 가해져 spfile이 참조되지 않은 경우에 주로
   다음 오류를 만날 수 있다.

 

      ORA-02095: specified initialization parameter cannot be modified


5. v$parameter와 v$spparameter에 대해서 (static parameter 확인)

   initial parameter의 종류에는 db가 운영 중에는 바로 그 값을 변경하여
   반영시킬 수 없고, 다음 startup 후에만 변경된 값이 영향을 주게되는
   parameter가 있다.
   이러한 parameter를 static parameter라고 부른다.
 
   이 static parameter의 경우는 그래서 alter system으로 변경하더라도,
   scope=spfile 로만 지정 가능한 것이다.
   이러한 static parameter를 scope를 지정 안 해서 memory로 하거나 both로
   하게 되면 4번에서 설명한 ORA-2095 오류가 발생하게 된다.

 

   그럼 static parameter는 어떻게 확인할 수 있는가?

 

      SQL>select name, issys_modifiable from v$parameter;

 

   여기에서 보면, issys_modifiable의 값으로 다음 세 가지가 나타난다.

 

   FLASE:     static parameter로 scope=spfile로만 값을 변경 가능하다.
              즉 값을 변경해도 이후 startup 시부터 영향을 미치게 된다.
   IMMEDIATE: 값을 변경하면 현재 session부터 바로 영향을 받게된다.
   DEFERRED:  변경된 값이 이후 접속되는 session부터 영향을 준다.

  
   alter system을 통해 parameter를 변경하는 경우 변경된 값이 반영이 잘
   되었는가를 확인하려면 다음과 같이 show parameter나 v$parameter를
   조회하고, 현재 반영은 안 되었더라도 spfile에 저장은 되었는지를 확인하
   려면 v$spparameter를 조회하면 된다.

 

      SQL>show parameter open_cursors
      SQL>select value from v$prameter where name = 'open_cursors';
      SQL>select value from v$spparameter where name = 'open_cursors';

 

   즉, scope=spfile로 parameter를 변경한 경우는 v$spparameter에만 변경
   된 값이 나타나고, show parameter나 v$parameter에서는 변경 전 값이
   나타나게 된다.

 

출처: 네이버 지식iN (magicdba (2006-06-09 19:28 작성)


COUNT DISTINCT

2009. 12. 9. 00:35 | Posted by 신비마마

COUNT DISTINCT

This morning I saw an e-mail with the title "SQL puzzle?" in my inbox. That's a good title to make me read that one first. The poster was stunned by the results of the following two queries:

SQL> SELECT COUNT(DISTINCT bdl.nrl_id)
2 FROM a_table bdl
3 WHERE bdl.periode >= to_date('20081023092701','yyyymmddhh24miss')
4 ;

COUNT(DISTINCTBDL.NRL_ID)
-------------------------
61111

1 rij is geselecteerd.

SQL> SELECT COUNT(*)
2 FROM (SELECT DISTINCT bdl.nrl_id
3 FROM a_table bdl
4 WHERE bdl.periode >= to_date('20081023092701','yyyymmddhh24miss')
5 )
6 ;

COUNT(*)
----------
61112

1 rij is geselecteerd.


Of course it's possible that a record was inserted in the meantime, but that was not the case here.

The explanation was quite simple. See this example:

rwijk@ORA11GR1> select comm from emp
2 /

COMM
----------

300
500

1400




0





14 rijen zijn geselecteerd.

rwijk@ORA11GR1> select distinct comm from emp
2 /

COMM
----------

1400
500
300
0

5 rijen zijn geselecteerd.

rwijk@ORA11GR1> select count(*) from (select distinct comm from emp)
2 /

COUNT(*)
----------
5

1 rij is geselecteerd.

rwijk@ORA11GR1> select count(distinct comm) from emp
2 /

COUNT(DISTINCTCOMM)
-------------------
4

1 rij is geselecteerd.


Again those pesky null values. From the documentation:
"All aggregate functions except COUNT(*), GROUPING, and GROUPING_ID ignore nulls."
A distinct doesn't ignore nulls, and the count(*) on top of it doesn't either.

At first glance, a "select count(distinct ...)" appears equal to a "select count(*) from (select distinct ...)", but as shown: it is not.



UPDATE


I forgot to mention that a "select count(comm) from (select distinct comm...)" [note: count(comm) instead of count(*)] is equal to a "select count(distinct comm) ...":

rwijk@ORA11GR1> select count(comm) from (select distinct comm from emp);

COUNT(COMM)
-----------
4

1 rij is geselecteerd.
 
[출처] ABOUT ORALCE

count(*)와 count(column) 의 차이

2009. 12. 9. 00:06 | Posted by 신비마마
왠지 count할 때 어떤 컬럼을 기준으로 count를 할 것인가를 정해주면
왠지 더 멋지게 빠르게 잘 해줄것만 같은 기분이 들었습니다.
그래서 실험을 해봤죠.
count안에 들어가는 칼럼은 당연히 index가 걸려있는 칼럼입니다.

1. select count(*) from table;
2. select count(column) from table;
3. select /*+INDEX_FES(table column) */ count(*) from table;
4. select /*+INDEX_FES(table column) count(column) from table;

참고로 INDEX_FES 힌트는 INDEX FAST SCAN하게 하는겁니다.

빠르기는
3 > 1 > 4 > 2 순입니다.
어떤 컬럼의 인덱스를 FAST SCAN하는지를 정해주고 count(*)를 하는게 제일 빠르더군요.
생각보다 오라클은 머리가 좋습니다.
count(*)는 옵티마이저가 제일 좋은 방법을 찾아서 숫자를 세어주는가보더라구요.
아~ 츄닝의 길은 멀고도 험하다!

[출처] 구원님의 성큼성큼 BLOG

! 위 쿼리에서 주의할점 count함수내 컬럼을 명시할 경우 해당컬럼에서 NULL인 로우는 제외하지만 컬럼명시가아닌 *로 지정한다면 모든 행을 리턴하므로 결과값이 상이할 수 있는여지가 있음!!


-> Better performance

TIP: Performance Tuning

Since the COUNT function will return the same results regardless of what NOT NULL field(s) you include as the COUNT function parameters (ie: within the brackets), you can change the syntax of the COUNT function to COUNT(1) to get better performance as the database engine will not have to fetch back the data fields.

For example, based on the example above, the following syntax would result in better performance:

SELECT department, COUNT(1) as "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department;

Now, the COUNT function does not need to retrieve all fields from the employees table as it had to when you used the COUNT(*) syntax. It will merely retrieve the numeric value of 1 for each record that meets your criteria.


SELECT * INTO와 INSERT INTO SELECT..의 차이점

2009. 12. 8. 23:58 | Posted by 신비마마

1.SELECT * INTO사용법

   SELECT  INTO 구문은 원본은 있고 대상 테이블은 새롭게 생성하려 할 경우 사용합니다.

   TABLE A에서 모든 데이터를 가져와 A_COPY라는 테이블을 생성하여 데이터를 INSERT하고 싶습니다.

   물론 A_COPY라는 테이블은 현재 만들어져있지 않습니다.

 

   SELECT * INTO A_COPY FROM A

 

   위와 같이 하면 A테이블과 같은 컬럼과 데이터를 가지는 A_COPY라는 테이블이 생성됩니다.

   그럼 A테이블의 특정 컬럼만 가져오려면?

 

   SELECT * INTO A_COPY

   FROM (

              SELECT COL1,COL2,COL3.... FROM A 

             ) AS TEMP_TABLE

   위와 같이 하면 A테이블의 특정 컬럼만 가져와서 A_COPY라는 테이블을 생성하여 데이터를 INSERT합니다.

 

2.INSERT INTO SELECT 사용법

   INSERT INTO 구문은 원본과 대상테이블이 모두 있을 경우 사용합니다.

   TABLE A에서 모든 데이터를 가져와 B라는 테이블에 INSERT 하고 싶습니다.

  

   INSERT INTO B SELECT * FROM A

   위에서 TABLE A와 TABLE B는 스키마가 동일해야 합니다.

 

   만일 A보다 컬럼수가 적을 경우에는

   INSERT INTO B SELECT COL1,COL2,COL3 FROM A

   와 같이 사용할 수 있습니다.


[출처] 허둥사마님 블로그
이전 1 2 3 4 5 6 다음