ORACLE/SQL2023. 7. 2. 00:48
반응형

-- 유저 별
select 'select '||'count(*)'||' ' ||'from ' ||table_name||';'   from user_tables; 


-- 전체 건수 뽑는 쿼리 뽑기
select 'select '||'count(*)'||' ' ||' from '|| owner||'.' ||table_name||';'   from dba_tables
order by owner,table_name
;;

-- 유저 별 함수 사용
select table_name
,num_rows "통계건수"
,to_number(
dbms_xmlgen.getxmltype('SELECT COUNT(*) C FROM ' || TABLE_NAME).Extract('//text()'))  "실제 건수"
FROM dba_tables;



select table_name
,num_rows "통계건수"
,to_number(
dbms_xmlgen.getxmltype('SELECT COUNT(*) C FROM ' || TABLE_NAME).Extract('//text()'))  "실제 건수"
FROM user_tables;

반응형
Posted by [PineTree]
ORACLE/SQL2018. 7. 6. 11:36
반응형

COUNT(*) OVER () : 전체행 카운트


COUNT(*) OVER (PARTITION BY 컬럼) : 그룹단위로 나누어 카운트


MAX(컬럼) OVER() : 전체행 중에 최고값


MAX(컬럼) OVER(PARTITION BY 컬럼) : 그룹내 최고값


MIN(컬럼) OVER () : 전체행 중에 최소값


MIN(컬럼) OVER (PARTITION BY 컬럼) : 그룹내 최소값


SUM(컬럼) OVER () : 전체행 합


SUM(컬럼) OVER (PARTITION BY 컬럼) : 그룹내 합


AVG(컬럼) OVER () : 전체행 평균


AVG(컬럼) OVER (PARTITION BY 컬럼) : 그룹내 평균


STDDEV(컬럼) OVER () : 전체행 표준편차


STDDEV(컬럼) OVER (PARTITION BY 컬럼) : 그룹내 표준편차


RATIO_TO_REPORT(컬럼) OVER () : 현재행값/SUM(전체행값) 퍼센테이지로 나타낼경우 100곱하면 됩니다.


RATIO_TO_REPORT(컬럼) OVER (PARTITION BY 컬럼) : 현재행값 / SUM(그룹행값) 퍼센테이지로 나타낼경우 100곱하면 됩니다

반응형
Posted by [PineTree]
ORACLE/SQL2016. 4. 6. 17:29
반응형

출처: http://m.blog.yes24.com/metalzang/post/1785694

나누기 연산 하는 경우거나 평균값을 구하는 경우에 분모 값이 0 인 상태에서 연산을 하면 에러(ORA-01476)가 발생하는데...

이 경우 아래와 같은 예제를 활용하시면 해결하실 수 있습니다.

-- ORA-01476: 제수가 0 입니다.
-- 나누기 연산을 하여 값을 구하는 경우

select a/b result
from (select 100 a, 0 b from dual)

-- ORA-01476: 제수가 0 입니다.
-- 두개의 값에 따라 평균값을 구하는 경우
select avg(a/b) result
from (select 100 a, 0 b from dual)

-- NULLIF 함수를 사용하여 처리
-- 분모가 0 인 경우에 결과값은 0
select nvl(avg(a/nullif(b,0)),0) result
from (select 100 a, 0 b from dual)

-- 결과값 : 2, 0.5
select avg(200/100) result from dual
select avg(100/200) result from dual

-- DECODE 함수를 사용하여 처리.
select decode(b,0,0,null,0, a/b) result
from (select 100 a, 0 b from dual)

-- ORA-01476: 제수가 0 입니다.
-- AVG 함수를 사용하는 경우에는 분자/분모 모두 "0"이 아니여야 하므로
-- 아래와 같이 DECODE, NULLIF 함수를 사용하면 해결할 수 있음.
select decode(sum(b),0,0,null,0, avg(a/b)) result
from (
select 1001 a, 16 b from dual union all
select 2002 a, 10 b from dual
)

-- 131.38125 결과값
-- ROUND 함수로 인한 결과값 반올림(131.4)
select ROUND(decode(sum(b),0,0,null,0, avg(a/b)),1) result
from (
select 1001 a, 16 b from dual union all
select 2002 a, 10 b from dual
)

-- 131.38125 결과값
-- 지정한 소수점 단위로 절삭한다.(131.3)
select trunc(decode(sum(b),0,0,null,0, avg(a/b)),1) result
from (
select 1001 a, 16 b from dual union all
select 2002 a, 10 b from dual
)

반응형

'ORACLE > SQL' 카테고리의 다른 글

oracle table count 오라클 테이블 건수 확인  (0) 2023.07.02
오라클 Count over  (0) 2018.07.06
동시성제어 SELECT FOR UPDATE #1  (0) 2013.03.01
Oracle EXISTS Versus IN  (0) 2010.06.18
NOT IN과 NOT EXISTS의 차이점  (0) 2010.04.02
Posted by [PineTree]
ORACLE/SQL2013. 3. 1. 18:56
반응형

 

 

출처 : http://www.dator.co.kr/hotshin/textyle/236147

 

오라클 데이터베이스에서 선택된 행들에 대하여 배타적인 Lock을 설정 할 수 있는 기능이 SELECT FOR UPDATE 입니다. 요 기능에 대해서 잠시 살펴 봅니다. 어플리케이션에서 해당 기능을 프로그래밍 할 수도 있으나 오라클에서 제공되는 기능을 사용할 상황이 있겠죠.

활용하려는 상황

1. 특정한 테이블의 데이터(row)에 대하여 순차적 DML 처리를 가능하도록 하고자 하는 경우

2. 특정 데이터에 대해 동시 트랜잭션이 발생하여 데이터 정합성이 깨지는 것을 방지하고자 할 때

3. Update 처리 진행 중인 데이터를 다른 세션에서 읽는 것을 방지하고자 하는 경우

좀 장황해 보이네요. 좀 쉬운 표현으로는 A라는 사용자가 테이블의 특정 ROW UPDATE 하기 위해서 SELECT 하였으니까 다른 사용자들은 UPDATE 하지 말라는 것이죠.

활용 처

1. 영화 및 공연장의 특정 좌석을 예약하고자 한다.

2. 인터넷에서 판매되는 상품의 재고수량을 실시간으로 관리하고자 한다.

3. 은행의 예금 및 대출 통장의 잔액 변경의 일관성을 유지하고자 한다.

4. 인터넷 사이트의 포인트 잔액을 관리한다.

5. 기타 . . 등등

즉 하나의 리소스를 놓고 여러 트랜잭션에서 SELECT 한 후 INSERT/UPDATE/DELETE 로직을 처리하고자 할 때 먼저 SELECT 한 곳에서 리소스에 대해 LOCK을 걸고 COMMIT/ROLLBACK 하기 전에 다른 세션에서는 SELECT 되지 못하게 하는 기능이다. 프로그램적으로는 동시 처리하지 않고 순차적(Serial) 으로 처리 하라는 의미이다.

동시성 제어 시나리오
[그림1] 3명이 동시 상품구매 요청

그림1 동시상품구매.jpg

그림 한번 그려 보았네요. 잘 안보이죠. 더블 클릭. 따닥 ~~

[그림1]은 동일 상품에 대해 3명이 동시에 주문하려고 하였을 때 상품 수량의 변화를 나타내는 가상 시나리오이다. 특정 프로모션 기간일 때 다수의 사용자가 접속하여 상품을 주문하려고 하는 상황이다. 회사마다 이런 상황이 닥쳐을 때 대처하는 방법이 다를 수 있다. 어떤 회사는 업무 정책에 따라 동시성을 제어하지 않고 마이너스( - ) 수량 발생시 수작업 후속처리를 할 수 있고, 다른 회사는 수량 부족시 아예 에러를 발생시켜서 상품 부족시 주문발생을 억제 시킬 수도 있다.

SQL 구문

사용되는 구분과 예제를 살펴 봅니다. 오라클에서 LOCK은 테이블 단위가 아니라 처리할 데이터 ROW 레벨입니다.

1) FOR UPDATE with no option

LOCK를 획득하기 까지 무한정 기다린다.

해당 세션에서 transaction을 해제(commit, rollback) 하기 전까지는 결과셋에 대해서 lock이 걸림

SELECT A.*

FROM T_PRD_M A

WHERE PRD_CD = ' 10004'

FOR UPDATE;

2) FOR UPDATE nowait

lock를 회득하지 못하면 바로 exception 처리된다. (ORA-00054 오류 )

다른 세션에서 PRD_CD = ' 10004'에 대해서 lock을 잡고 있다면 에러가 발생

SELECT A.*

FROM T_PRD_M A

WHERE PRD_CD = ' 10004'

FOR UPDATE NOWAIT;

3) FOR UPDATE WAIT second

WAIT 시간() 만큼 동안 LOCK을 획득하기 위해 재시도한다.

주어진 시간 동안 LOCK을 획득하지 못하면 ORA-30006와 함께 해당 SQL문은 실패한다.

lock이 걸린 행들을 무한정 기다리게 되는 현상을 방지할 수 있으며, lock에 대한 대기 시간을 지정할 수 있기 때문에 로직 처리시간을 확보해야 하는 애플리케이션 개발에 사용 가능함.

SELECT A.*

FROM T_PRD_M A

WHERE PRD_CD = ' 10004'

FOR UPDATE WAIT 5; à 5초가 기다렸다가 lock을 획득하지 못하면 에러 발생

4) FOR UPDATE of

for update 구문은 FROM 절에 기술된 복수개의 테이블의 해당 행에 모두 LOCK을 설정한다. 이 때 of를 기술함으로 하여 특정 TABLE의 행에만 LOCK을 설정할 수 있다

SELECT A.*, C.*

FROM T_PRD_M A, T_CLS_M C

WHERE A.PRD_CD = '10004'

AND A.CLS_CD = C.CLS_CD

FOR UPDATE OF A.PRD_CD WAIT 5; à A테이블만 LOCK 겁니다.

FOR UPDATE OF C.CLS_CD WAIT 5; à C테이블에 LOCK을 겁니다.

FOR UPDATE OF WAIT 5; à A, B 테이블 모두에 LOCK 겁니다.

여기서 LOCK이 걸린다는 것은 위 SQL이 실행될 때 아래의 SQL들은 대기중으로 빠져서 기다린다는 이야기 겠죠

SELECT A.*, C.*

FROM T_PRD_M A, T_CLS_M C

WHERE A.PRD_CD = '10004'

AND A.CLS_CD = C.CLS_CD

FOR UPDATE OF A.PRD_CD WAIT 5;

동일한 SQL은 당연히 실행되지 않습니다

.

SELECT A.*

FROM T_PRD_M A

WHERE A.PRD_CD = '10004'

FOR UPDATE ;

T_PRD_M 10004 상품코드를 검색시 실행되지 않습니다. 당근 PRD_CD = ‘10005’는 실행되겠죠. LOCK 걸린 ROW가 아니기 때문에..

UPDATE T_PRD_M A

SET REG_ID = 'UPDATE'

WHERE A.PRD_CD = '10004';

어디선가 T_PRD_M 10004 상품코드를 UPDATE 하려고 한다면 LOCK 발생하여 대기상태로 빠집니다.

SELECT A.*

FROM T_PRD_M A

WHERE A.PRD_CD = '10004'

SQL은 정상적으로 실행 될까요 ?

빙고. LOCK과 상관이 없죠. 그냥 SELECT 됩니다.

SELECT FOR UPDATE 구문은 오라클 9부터 나온것이라고 하네요.

그리고 LOCK 걸린것은 commit; rollback; 될때 해제되겠죠

LOCK 세션 확인 쿼리는 아래와 같음.

SELECT A.SID, A.SERIAL#, B.TYPE, C.OBJECT_NAME

FROM V$SESSION A, V$LOCK B, USER_OBJECTS C

WHERE A.SID=B.SID

AND B.ID1=C.OBJECT_ID

AND a.schemaname= 'SH'-- 사용자명 넣기


동시성 제어 시나리오 2

[그림2] 동시 은행 입출금 처리

그림2 동시 입출금.jpg

그림2는 은행 예금 통장에서 여러 매체를 사용하여 입금 혹은 출금이 동시에 발생하는 예시입니다. 1개 통장의 입출금이 동시에 발생될 때 각각 처리 한다면 최종 잔액의 정합성을 보장할 수 없겠죠. 이때 입출금 처리를 Serial 하게 처리 해야 합니다. 위 상황에서도 SELECT FOR UPDATE 가 사용 될 수 있습니다.

조심해야 하는 것

뭐 모든 기능이 좋은 것이 있다면 단점도 있겠죠.

1) Select For Update 문장이 꼭 필요한 프로그램에서만 적용한다

- 일반 조회 및 검색 시에는 Select For Update를 사용하면 안 된다.

- 중요한 업무에 사용되는 테이블의 데이터 변경 시 동시성에 대한 제어를 하고자 하는 요건이 있는 경우에만 사용한다.

2) 동일한 SQL 처리 로직 구문에서는 동일한 Select For Update 구문을 사용하도록 함

3) Update 변경처리 직전에 “Select For Update”를 사용하여 check 및 검증용으로 사용한다.

4) 무분별한 lock의 사용은 시스템 리소스를 감소시키고, lock에 의한 시스템 중단이 발생 될 수 도 있다.

- Select For Update 구문이 들어가는 모듈을 공통화하고, 사용되는 SQL 본 수를 최소화 한다.

5) Program 및 프레임웍에서 Serial한 로직 처리가 가능한 경우 어플리케이션에서 해결 할 수 있도록 한다.

6) Select For Update 방식 중 가급적이면 “3. FOR UPDATE WAIT 시간” 를 사용하여 lock이 유지되는 것을 방지한다.

7) 대량 배치 처리시 해당된 모든 row에 대한 lock이 걸릴 수 있기 때문에 특별한 주의를 요한다.

8) Select For Update 구문을 사용하고자 할 경우 DA DBA에게 적용 사유를 공지한 후 사용하도록 한다. ( 이 구문을 사용하는 SQL과 프로그램 로직은 특별 관리 대상으로 선정한다 )

다음에는 Select For Update를 사용하지 않고 테이블과 데이터 발생규칙으로만 제어하는 사례를 살펴 보겠습니다.

반응형
Posted by [PineTree]
ORACLE/SQL2010. 6. 18. 14:51
반응형

출처 : http://energ.tistory.com/187

일반적으로 IN operation은 특정 table(view) data의 row 값에 따른 다른 table의 데이터를 추출해내고자 할 때 자주 사용되는데, 가끔 IN operation을 row가 있는지 check하는 용도로 사용하기도 한다. 그러나 row가 존재하는지에 대해서는 EXISTS라는 근사한 operation을 따로 제공하고 있다. 

주의해야 할 점은 EXISTS와 IN은 다른 점이 존재하므로 이에 대해 유의해야 한다.  EXISTS는 단지 해당 row가 존재하는지만 check하고 더이상 수행되지 않으나 IN은 실제 존재하는 데이터들의 모든 값까지 확인한다. 따라서 일반적으로 EXISTS operation이 더 좋은 성능을 보이므로 가능하면 EXISTS를 사용하는 것이 바람직해 보인다.

또한가지 EXISTS와 IN 사용시 주의해야 할 점은 join 되는 column에 NULL을 갖는 row가 존재한다면, NOT EXISTS는 true값을, NOT IN은 false 가 return 된다. 즉, NOT IN을 사용하면 조건에 맞는 데이터가 있다고 하더라도 NULL이 존재하면 "no rows selected"라고 나오게 된다. 따라서 NVL을 이용한 NULL 처리가 꼭 필요하다.

다음은 NOT EXISTS operation을 이용한 방법이다.
예제의 products table의 product_type_id column 데이터 중 일부가 NULL로 입력되어 있다.

SELECT product_type_id, name
FROM product_types outer
WHERE NOT EXISTS
  (SELECT 1
   FROM products inner
   WHERE inner.product_type_id = outer.product_type_id);

PRODUCT_TYPE_ID NAME
--------------- ----------
              5 Magazine

다음은 동일한 데이터에 대해 NOT IN을 사용했을 경우다. NULL data에 의해 조건 자체가 false가 되어 "no rows selected"라는 결과가 발생한다.

SELECT product_type_id, name
FROM product_types
WHERE product_type_id NOT IN
  (SELECT product_type_id
   FROM products);

no rows selected

다음은 NVL()을 이용해 NULL값을 처리한 후의 결과이다.

SELECT product_type_id, name
FROM product_types
WHERE product_type_id NOT IN
  (SELECT NVL(product_type_id, 0)
   FROM products);

PRODUCT_TYPE_ID NAME
--------------- ----------
              5 Magazine

NOT IN operation의 경우 위와 같은 사실을 미리 인지하고 있지 않다면 나중에 이러한 경우를 찾기는 매우 어려울 수 있다. 따라서 NULL에 대한 operation이나 table의 default column 값등의 지정 등의 세심한 주의가 필요하다.
반응형
Posted by [PineTree]
ORACLE/SQL2010. 4. 2. 16:58
반응형




이번달 퀴즈는 두가지 부정형 조인 NOT IN, NOT EXISTS 의 차이점을 설명하는것입니다.

문제를 명확히 하기 위해서 아래와 같은 상황을 고려하겠습니다.

테이블 : TEST1

     NO

Name

1

Lee

2

Kim

3

Park

<NULL>

Jang

<NULL>

<NULL>


테이블 : TEST2

NO

 

Name

 

1

Lee

2

Kim

3

Park

<NULL>

Jang

* <NULL>은 데이터가 NULL값인 경우입니다.


테스트 쿼리

1) NOT IN 의 경우

SELECT *
   FROM TEST1 A
  WHERE A.NO NOT IN (SELECT NO FROM TEST2)

2) NOT EXISTS 의 경우

SELECT *
   FROM TEST1 A
  WHERE NOT EXISTS (SELECT 1 FROM TEST2 B WHERE A.NO = B.NO)

위와 같은 상황에서 두 개의 테스트 쿼리를 실행하여 그 결과에 대해 왜 그렇게 나왔는지 설명하세요.



답안)

이번달 퀴즈의 문제는 NOT IN과 NOT EXISTS의 차이점이 무엇인가입니다.


1번, 2번의 경우에서 NO의 값 1,2,3은 모두 결과에 나오지 않습니다. 즉, TEST2에 속하지 않는것을 찾는것이므로 결과에 나오지 않게됩니다. 차이점은 NULL 값이 결과에 나오는가 아닌가에 있습니다.


NOT IN(1번)의 경우

where절의 조건이 맞는지 틀리는지를 찾는것입니다. 그런데 NULL은 조인에 참여하지 않기때문에 결과에서 빠집니다. 여기서 TEST1의 NULL값이 나오지 않은 이유는 IN 서브쿼리의 결과에 NULL유무에 영향을 받지 않습니다. 즉, TEST2의 NO컬럼에 NULL값이 없어도 TEST1의 NO컬럼의 NULL값은 결과에 나오지 않습니다.


NOT EXISTS(2번)의 경우

EXISTS는 서브쿼리가 TRUE인지 FALSE인지 체크하는 것이므로  NOT EXISTS는 서브쿼리가 FALSE이면 전체적으로 TRUE가 됩니다. 서브쿼리에서 TEST1과 TEST2의 조인시 NULL은 결과에서 빠지게 됩니다. 이것은 서브쿼리를 FALSE로 만들게 되고 전체적으로 TRUE가 되어 TEST1의 NULL값이 결과에 나오게 됩니다.


이번 퀴즈는 매우 쉬운것 같으나 자칫 잘못 생각할 수 있는 내용이기 때문에 퀴즈로 다루었습니다. 일반적으로 대용량을 처리할 때 성능상의 이유로 Hash Anti-Join, Merge Anti-Join으로 유도하기 위해 NOT EXISTS를 NOT IN으로 바꿔서 처리하기도 합니다. 이때 두 부정형 조인의 결과가 같다는 전제 조건이 있어야 합니다. 그러나 위에서와 같이 연결고리가 되는 컬럼의 값 중 NULL이 포함된 경우 결과가 다르다는것을 주의해야 합니다.



=========================================================================================================================
=========================================================================================================================



not in 과 not exists 차이점 / 부정형을 긍정으로 변경할때



일반적으로 대용량을 처리할때 성능상의 이유로 Not Exists로 되어 있는 것을


Not In으로 바꿔서 Hash나 Merge Anti Join으로 유도하는 경우가 있는데


이는 Not Exists와 Not In의 관계가 "="이 성립한다는 전제 조건에서 이루어 진다.


하지만 모든경우 Not Exists와 Not In의 관계가 "=" 성립하는지에 대한 의문에서


아래와 같이 테스트를 해보았습니다.


<결론>
   Not In 과 Not Exists는 다르다.
    + Not IN과 Not Exists의 차이점은 연결고리가 되는 컬럼의
      값중 null값을 처리하는 부분에서 차이가 난다.


<이유>
    + Not In 은 where 절의 조건이 만족하더라도
      연결고리 컬럼이 Null값을 가진 다면 결과에서 무조건 제외 된다.


    + Not Exists는 Not In과 달리 Null값을 가진 row들도 결과에 포함된다.


    + 간단히 생각해보면 in은 조건에 만족하는 row를 찾는 것이고
      exists는 exists이하 절이 true인지 아닌지를 체크하는 것이기 때문에
      연결고리 컬럼의 값이 null값을 가질때 null은 조인에 참여하지 못하기 때문에
      in은 조건에 만족하는 것을 찾을 수 없는 것이고
      exists는 false의 값을 return한다.
     
      따라서 연결고리 값이 null값을 가질때
      Not in은 조인 연산을 하지 않기 때문에 결과에서 제외되며
      Not Exists는 exists이하의 절이 false를 리턴하고 거기에 대한 Not이기 때문에
      결과적으로 true가 되어 결과에 포함된다.


<참고사항>


  1) 부정형을 긍정으로 변경할 때


    + Not In일 때는 상관 없지만 Not Exists일때는
      논리적으로 부정형을 긍정으로 변경 한 후 연결고리가 되는 컬럼이 null값 가질 경우에
      대해서 반드시 True가 되도록 처리해 줘야 된다.
    + 즉 null 값을 가지는 컬럼에 대해서도 결과에 포함 되도록 해야 된다.


  ex)
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
       FROM IRMS_SNG_MAS A
      WHERE A.WONJ_ST2 = '1'
        AND A.GAGIGONG_GB IN('2','3')
        AND NOT EXISTS(SELECT 'X'
                         FROM IRMS_SNG_MAS G
                        WHERE G.WONJ_ST2 = '1'
                          AND G.GAGIGONG_GB IN('2','3')
                          AND (G.MANGI_IL < :current_il AND NVL(G.SIL_BAL,0) = 0)
                          AND G.SNG_NO = A.SNG_NO
                          AND G.SNG_SEQ = A.SNG_SEQ)


   <부정형을 긍정형으로 변경>


     + MANGI_IL이 NULL값을 가질때 반드시 참이 되도록 해야 됨.
    
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
        FROM IRMS_SNG_MAS A
       WHERE A.WONJ_ST2 = '1'
         AND A.GAGIGONG_GB IN('2','3')
         AND NOT (NVL(A.MANGI_IL,'99991231') < :CURRENT_IL AND NVL(A.SIL_BAL,0) = 0)


<테스트 테이브>
TEST_AJ01
TEST_AJ02


<데이타>

TEST_AJ01
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   <null>
<null>   20030408


TEST_AJ02
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   20030408

# NULL값을 가진 컬럼의 값은 <null>이라고 표현하였음


<테스트 SQL문>
1)
    SELECT *
      FROM TEST_AJ01 A
     WHERE A.NO NOT IN (SELECT NO FROM TEST_AJ02)
  
   ==결과==  -- 0건
   No rows returned

2)
    SELECT *
      FROM TEST_AJ01 A
     WHERE NOT EXISTS (SELECT 'X' FROM TEST_AJ02 B WHERE A.NO = B.NO)

   ==결과==  -- 2건
   <null>    <null>
   <null>    20030408



==========================================================================================================================
==========================================================================================================================

TEST1 테이블의 데이터 중 TEST2에 속하지 않는 데이터만 가져오기 ( NOT IN, NOT EXISTS, JOIN, UNION 으로 해결 )

중복되지 않는 데이터만 가져와서 INSERT 하거나

중복되는 데이터만 가져와서 UPDATE 할 때 사용할 수도 있다.


CREATE TABLE TEST1 (
 IDX INTEGER,
 NAME VARCHAR(100)
)

CREATE TABLE TEST2 (
 IDX INTEGER,
 NAME VARCHAR(100)
)


INSERT INTO TEST1 VALUES (1, 'A')
INSERT INTO TEST1 VALUES (2, 'B')
INSERT INTO TEST1 VALUES (3, 'C')
INSERT INTO TEST1 VALUES (4, 'D')
INSERT INTO TEST1 VALUES (5, 'E')


INSERT INTO TEST2 VALUES (3, 'C')
INSERT INTO TEST2 VALUES (4, 'D')
INSERT INTO TEST2 VALUES (5, 'E')
INSERT INTO TEST2 VALUES (6, 'F')
INSERT INTO TEST2 VALUES (7, 'G')


SELECT * FROM TEST1
SELECT * FROM TEST2


-- NOT IN

SELECT *
  FROM TEST1
 WHERE IDX NOT IN (
SELECT IDX
  FROM TEST2 )


-- NOT EXISTS

SELECT *
  FROM TEST1 A
 WHERE NOT EXISTS (
SELECT *
  FROM TEST2 B
 WHERE A.IDX = B.IDX )


-- SYBASE JOIN
SELECT *
  FROM (
 SELECT A.*
   , B.IDX B_IDX
   FROM TEST1 A
      , TEST2 B
  WHERE A.IDX *= B.IDX
    ) A
   WHERE B_IDX IS NULL
 

-- ANSI JOIN

SELECT *
  FROM TEST1 A
  LEFT JOIN TEST2 B
    ON A.IDX = B.IDX
 WHERE B.IDX IS NULL
 

-- UNION ALL
SELECT A.IDX, A.NAME
  FROM (
  SELECT NAME
    , COUNT(*) CNT
    , COUNT(CASE WHEN GBN = 'A' THEN 1 END) A_CNT
    , IDX
    FROM (
    SELECT 'A' AS GBN
      , A.*
      FROM TEST1 A
    UNION ALL
    SELECT 'B'
      , B.*
      FROM TEST2 B
     ) A
   GROUP BY IDX, NAME
  ) A
 WHERE A.CNT < 2
   AND A_CNT = 1


출처 : http://blog.naver.com/tyboss?Redirect=Log&logNo=70051601411

반응형
Posted by [PineTree]
ORACLE/SQL2010. 1. 4. 14:58
반응형
1. EXECUTE IMMEDIATE를 이용한 Dynamic SQL  


Oracle 8i에서의 Dynamic SQL은 두가지 방법이 있습니다.

첫번째 방법은  "EXECUTE IMMEDIATE" 절을 사용하여 embedded dynamic sql을 구현하는
방법이고,

두번째 방법은 선언되어지는 것 대신에 실행시에 문장을 보내는 ref cursor의 확장된 개념으로
query를 위해 사용되어지는 방법 입니다.


여기서는 EXECUTE IMMEDIATE를 이용한 Dynamic SQL에 대해서 알아보겠습니다.

[Syntax]

        EXECUTE IMMEDIATE dynamic_sql_string
            [INTO {define_var1 [, define_var2] ... | plsql_record }]
            [USING [IN | OUT | IN OUT] bind_arg1 [,
                        [IN | OUT | IN OUT] bind_arg2] ...];

 


2. 간단하게 테이블을 생성하는 예제 입니다 

 
첫번째 예제는 간단하게 테이블을 생성하는 예제 입니다.
 
==========================================================

CREATE OR REPLACE PROCEDURE dynamic_sql_01
IS

    str varchar2(200);

BEGIN

    str := ’CREATE TABLE  total (total number)’;
    EXECUTE IMMEDIATE str;

END;

==========================================================

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

 
-- 프로시저를 실행해서 테이블을 생성 합니다.
SQL> EXEC dynamic_sql_01;
PL/SQL 처리가 정상적으로 완료되었습니다.
 
 
-- 생성된 테이블을 확인해 봅니다.
SQL> DESC total;
 이름                                      널?      유형
 ----------------------------------------- -------- -----------
 TOTAL                                              NUMBER



* 프로시저 생성시 "ORA-01031: 권한이 불충분합니다" 에러가 발생하면
  system유저로 접속을 해서 EXECUTE IMMEDIATE를 실행하는 유저에게
  CREATE ANY TABLE 권한을 부여 합니다.   

SQL> CONN system/manager  
SQL> GRANT create any table TO scott;

 


3. 테이블 생성 후 INSERT 예제


두번째 예제는 TABLE_ROWS라는 테이블을 생성하고, 다이나믹 하게 테이블명을 입력하면
테이블명과 테이블에 등록된 데이터수를 TABLE_ROWS에 INSERT하고 출력하는 예제 입니다.


=============================================================== 

CREATE OR REPLACE PROCEDURE dynamic_sql_02
 (v_table_name IN VARCHAR2)
IS
   
    v_str VARCHAR2(200);
    v_cnt NUMBER;
    v_temp VARCHAR2(50);
    
    CURSOR cur_exists IS
    SELECT TABLE_NAME
    FROM USER_TABLES
    WHERE table_name = ’TABLE_ROWS’;
    
BEGIN
    
    OPEN cur_exists
    FETCH cur_exists INTO v_temp;
    

   -- 테이블이 존재하면 테이블을 삭제 합니다.
    IF  cur_exists%FOUND THEN     
        v_str := ’DROP TABLE  table_rows’;
        EXECUTE IMMEDIATE v_str;
    END IF;    

    -- 테이블 생성
    v_str := ’CREATE  TABLE  table_rows (total number, table_name varchar2(50))’;
    EXECUTE IMMEDIATE v_str;    


   -- 데이터 카운트 조회
    v_str := ’SELECT COUNT(*) cnt FROM ’||v_table_name ;
    EXECUTE IMMEDIATE v_str INTO v_cnt ;


    -- 데이터 insert
    v_str := ’INSERT INTO table_rows  VALUES (’||v_cnt||’, :A1 )’;   
    EXECUTE IMMEDIATE v_str USING v_table_name;


    DBMS_OUTPUT.PUT_LINE(’ 테이블 명 : ’||v_table_name||’  데이터 수 : ’||v_cnt);    

    CLOSE cur_exists;     

END;
/
=============================================================== 

프로시저가 생성되었습니다.
 
SQL> SET SERVEROUTPUT ON:

-- emp 테이블명과 테이블의 데이터카운트를 INSERT합니다.
SQL> EXEC dynamic_sql_02(’emp’);
테이블 명 : emp  데이터 수 : 14

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


-- 정상적으로 처리되었는지 확인해 봅니다.
SQL> SELECT * FROM table_rows;
 
     TOTAL TABLE_NAME
---------- --------------
        14 emp

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

'ORACLE > SQL' 카테고리의 다른 글

Oracle EXISTS Versus IN  (0) 2010.06.18
NOT IN과 NOT EXISTS의 차이점  (0) 2010.04.02
SQL *Plus 명령어와 SQL문 구분하기  (0) 2010.01.03
DB 최적화를 고려한 다건조회 페이징처리  (0) 2010.01.03
SQL TIP  (0) 2010.01.03
Posted by [PineTree]
ORACLE/SQL2010. 1. 3. 14:13
반응형

┌──────────────┬─────────────────────┬────────┐
│구분 │ 설명 │ 예 │
├──────────────┼─────────────────────┼────────┤
│DML │데이터를 조회하거나 변경 │insert,update │
│(Data Manipulation Language)│ │delete,select │
│ │ │commit,rollback │
├──────────────┼─────────────────────┼────────┤
│DDL │데이터의 구조를 정의 │create,drop │
│(Data Definition Language) │ │alter,rename, │
│ │ │truncate │
├──────────────┼─────────────────────┼────────┤
│DCL │데이터베이스 사용자에게 부여된 권한을 정의│grant,revoke │
│(Data Control Language) │ │ │
└──────────────┴─────────────────────┴────────┘

SQL> select * from tab;

TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
ACCOUNT TABLE
BONUS TABLE
DEPARTMENT TABLE
DEPT TABLE
EMP TABLE
EMPLOYEE TABLE
RECEIPT TABLE
SALGRADE TABLE

SQL> desc emp -- desc(ribe)는 테이블 정의를 나타내는 명령어

이름 널? 유형
----------------------------------------- -------- ------------
EMPNO NOT NULL NUMBER(4)
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)


▶ 명령어 버퍼
-- SQL *Plus는 명령어 버퍼(command buffer)에서 현재의 SQL문을 보관한다.
-- 이 명령어 버퍼의 각각의 줄은 번호가 부여되어 있다.
-- 사용자는 명령어 버퍼의 내용을 편집하고, 호출하고 저장할 수 있으며,
-- SQL*Plus의 프롬프트에 list나 그의 축약표현인 L을 입력하여 버퍼의 내용을 나타내게 할 수 있다.


--------------------------------------------------------------------------------
명령어 설명
--------------------------------------------------------------------------------
L(LIST) SQL명령어 버퍼의 내용을 나열
L(LIST) n SQL명령어 버퍼의 내용중 n번째줄만 나열
L(LIST) m n SQL명령어 버퍼의 내용중 m번째 부터 n번째줄까지 나열
R(RUN) SQL명령어 버퍼에 있는 SQL문을 실행시킴
N(N은 숫자) N을 편집될 현재의 줄로 만듦
I(INSERT) 현재의 줄 다음에 새로운 줄을 삽입
새로운 줄이 현재의 줄이 됨
DEL(DELETE) 현재의 줄을 삭제
DEL n n번째 줄을 삭제
DEL m n m번째 부터 n번째 까지 줄을 삭제
A(APPEND) text 현재의 줄에 텍스트를 첨가
C(CHANGE)/string1/string2/ 문자열1(string1)의 내용을 문자열2(string2)로 변경함
CL(CLEAR) BUFF(BUFFER) SQL명령어 버퍼에 있는 SQL문을 삭제
CL(CLEAR) SCR(SCREEN) SQL*Plus 에디터 화면을 지움
--------------------------------------------------------------------------------

SQL> select empno,ename
2 from emp
3 where sal > (select avg(sal) from emp);

EMPNO ENAME
---------- ----------
7566 JONES
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7902 FORD

6 개의 행이 선택되었습니다.


1. 방금했던 질의의 내용을 다시 나타내게 하고 싶다면 즉, 현재 버퍼에 있는 내용을 나타내 보는것

SQL> l
1 select empno,ename
2 from emp
3* where sal > (select avg(sal) from emp)


2. 이번에는 평균 급여보다 적게 받는 사원들을 알고 싶어서 3번째 줄을 편집하고자 한다면 SQL프롬프트에서 3을 입력한다.

SQL> 3
3* where sal > (select avg(sal) from emp)

3. 3번째 줄이 현재의 줄이 되었고(라인 번호 옆에 * 표시가 있는 곳이 현재의 줄이다), '>'을 '<'로 변경하기 위해서
change명령(축약 c)을 사용한다.
SQL> c/>/<
3* where sal < (select avg(sal) from emp)

4. 다시 현재 버퍼의 내용을 확인해본다.
SQL> l
1 select empno,ename
2 from emp
3* where sal < (select avg(sal) from emp)

5. 이 질의 결과가 사원들의 이름순으로 정렬되기를 원한다. 그래서 현재 버퍼의 내용의 끝에 새로운 줄을 입력하기 위해서
input명령(축약어 i)을 사용한다.
SQL> i
4 order by ename
5

6. 다시 현재 버퍼의 내용을 확인한다.
SQL> l
1 select empno,ename
2 from emp
3 where sal < (select avg(sal) from emp)
4* order by ename

7. 그런데, 이들의 구체적인 급여도 알고 싶어서 첫번째 줄의 뒤에 찾는 컬럼 sal을 추가해야 한다.
먼저 위의 버퍼 내용에서는 현재의 줄이 4번째 줄이므로, 첫번째 줄로 현재의 줄을 바꾸기 위해서 1을 입력한다.
SQL> 1
1* select empno,ename

8. ,sal을 이 줄의 뒤에 추가시키기 위해 append명령(축약 a)을 사용한다.
SQL> a ,sal
1* select empno,ename,sal

9. 다시 현재 버퍼의 내용을 확인한다.
SQL> l
1 select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4* order by ename

10. 현재 버퍼에 있는 SQL문을 run 이나 /을 입력하여 실행시킨다.
SQL> /

EMPNO ENAME SAL
---------- ---------- ----------
7876 ADAMS 1100
7499 ALLEN 1600
7900 JAMES 950
7654 MARTIN 1250
7934 MILLER 1300
7369 SMITH 800
7844 TURNER 1500
7521 WARD 1250

8 개의 행이 선택되었습니다.


11. 편집명령어 ==> ed

SQL> select * from 사원
2 where 부서펀호=20;
where 부서펀호=20
*
2행에 오류:
ORA-00904: 열명이 부적합합니다


SQL> ed

select * from 사원
where 부서번호=20 ==> 메모장에서 펀을 번으로 수정한 후 alt+f , x , 엔터
/

file afiedt.buf(이)가 기록되었습니다

1 select * from 사원
2* where 부서번호=20

SQL> / ==> /으로 실행함



▶------ SQL문을 파일로 저장하기 -------◀

★★★
1. save 명령어를 사용하여 명령어 버퍼의 현재 내용만을 사용자가 명시하는 파일로 저장한다.
기본적으로 save 명령어는 .sql 이라는 확장자를 사용한다. 사용자는 다른 파일 확장자를 사용할 수 있다.
save 명령어는 자동적으로 덮어쓰기를 하지 않으므로
기존의 파일 위에 덮어쓰기를 하려면 replace 라는 옵션을 사용해야 한다.

SQL> l
1 select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4* order by ename

SQL> save c:\test\lowsal
file c:\test\lowsal(이)가 생성되었습니다

SQL> save c:\test\lowsal
SP2-0540: "c:\test\lowsal.sql" 파일은 이미 존재합니다.
"SAVE 파일명[.ext] REPLACE"을 사용합니다.

SQL> save c:\test\lowsal replace
file c:\test\lowsal(이)가 기록되었습니다

★★★
2. get을 사용하여 save 명령어를 사용하여 파일로 저장된 명령어 버퍼의 내용을 조회하고, r을 입력하여 SQL문을 실행시킨다.

SQL> get c:\test\lowsal
1 select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4* order by ename
SQL> r
1 select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4* order by ename

EMPNO ENAME SAL
---------- ---------- ----------
7876 ADAMS 1100
7499 ALLEN 1600
7900 JAMES 950
7654 MARTIN 1250
7934 MILLER 1300
7369 SMITH 800
7844 TURNER 1500
7521 WARD 1250

8 개의 행이 선택되었습니다.


★★★
3. 출력을 파일로 저장하기
spool 명령어는 질의 결과를 파일로 저장해주는 것이다.
spool off 명령어는 스풀링을 중단하는 SQL *Plus 명령어이다.

SQL> spool c:\test\spool_1
SQL> select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4 order by ename;

EMPNO ENAME SAL
---------- ---------- ----------
7876 ADAMS 1100
7499 ALLEN 1600
7900 JAMES 950
7654 MARTIN 1250
7934 MILLER 1300
7369 SMITH 800
7844 TURNER 1500
7521 WARD 1250

8 개의 행이 선택되었습니다.

SQL> select empno,ename,sal
2 from emp
3 where sal = (select max(sal) from emp);

EMPNO ENAME SAL
---------- ---------- ----------
7839 KING 5000

SQL> spool off

============================================================
c:\test\spool_1.lst 파일을 메모장에서 열어 보았을 때의 내용
SQL> select empno,ename,sal
2 from emp
3 where sal < (select avg(sal) from emp)
4 order by ename;

EMPNO ENAME SAL
---------- ---------- ----------
7876 ADAMS 1100
7499 ALLEN 1600
7900 JAMES 950
7654 MARTIN 1250
7934 MILLER 1300
7369 SMITH 800
7844 TURNER 1500
7521 WARD 1250

8 개의 행이 선택되었습니다.

SQL> select empno,ename,sal
2 from emp
3 where sal = (select max(sal) from emp);

EMPNO ENAME SAL
---------- ---------- ----------
7839 KING 5000

SQL> spool off
============================================================

★★★
4. 스크립트를 실행하기

c:\test\script1.sql 이라는 파일로 아래의 내용을 저장한다.

select empno,ename,job,sal
from emp
where job='CLERK';

SQL> @ c:\test\script1.sql

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7369 SMITH CLERK 800
7876 ADAMS CLERK 1100
7900 JAMES CLERK 950
7934 MILLER CLERK 1300

SQL> start c:\test\script1.sql

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7369 SMITH CLERK 800
7876 ADAMS CLERK 1100
7900 JAMES CLERK 950
7934 MILLER CLERK 1300


★★★
5. 출력의 포맷팅
SQL *Plus 명령어를 통해서 사용자가 형식, 총계와 소계를 명시할 수 있고 반복되는 값을 통제할 수 있다.
포맷팅 명령어는 임시적이다. 이것들은 동일한 SQL *Plus 세션 기간중 처리되는 SQL문에 대해서만 그 효력을 유지한다.

※ SQL*Plus 세션이란?
-- SQL *Plus에 연결할 때부터 SQL *Plus에서 연결을 끊을 때까지 발생하는 명령어와 그에 대한 반응을 말한다.

------------------------------------------------------------------------------------------------
명령어 목적
------------------------------------------------------------------------------------------------
col[umn] 컬럼의 옵션 컬럼의 형식을 바꾼다.
tti[tle] [문장|off|on] 보고서 각 페이지 상단의 머릿글을 나타낸다.
bti[tle] [문장|off|on] 보고서 각 페이지 하단의 머릿글을 나타낸다.
bre[ak] [on 반복을 배제할 리스트] 라인을 넘겨 중복값을 통제한다.
comp[ute] [함수 of{컬럼명} on {컬럼명}] 합계를 계산한다.
------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------
포맷 지정 요소 내용
------------------------------------------------------------------------------------------------
An (n은 폭을 나타내는 숫자) 문자와 날짜 컬럼에 대해서 n폭 만큼 출력 설정
9 자리수 표현
0 앞에 0을 붙임
$ 달러 사인 표시
L 국내 통화 표시
. 소숫점의 위치
, 천 단위 구분자
------------------------------------------------------------------------------------------------

1). emp 테이블에서, 사원들의 급여를 세 자리마다 콤마를 찍고 앞에 달러 사인($)을 표시하고 싶다면 다음과 같이 한다.

SQL> col sal format $9,999
SQL> select empno, ename, sal
2 from emp;

EMPNO ENAME SAL
---------- ---------- -------
7369 SMITH $800
7499 ALLEN $1,600
7521 WARD $1,250
7566 JONES $2,975
7654 MARTIN $1,250
7698 BLAKE $2,850
7782 CLARK $2,450
7788 SCOTT $3,000
7839 KING $5,000
7844 TURNER $1,500
7876 ADAMS $1,100

EMPNO ENAME SAL
---------- ---------- -------
7900 JAMES $950
7902 FORD $3,000
7934 MILLER $1,300

14 개의 행이 선택되었습니다.


2). 문자 컬럼의 경우, 사용자는 Format 명령어를 사용하여 컬럼의 넓이를 명시할 수 있다.
부서명을 한 줄에 다섯글자만 표현하고 다음줄에 나타내는 보고서를 만든다면 다음과 같이 한다.

SQL> col dname format a5
SQL> select * from dept;

DEPTNO DNAME LOC
---------- ----- -------------
10 ACCOU NEW YORK
NTING

20 RESEA DALLAS
RCH

30 SALES CHICAGO
40 OPERA BOSTON
TIONS

3). 위의 결과를 보기에 좋지 않은 형식이다. 그래서 포맷지정을 다시 원상복귀 시키기 위해서
현재의 포맷지정을 clear 옵션을 사용하여 지운다.
SQL> col dname clear
SQL> select * from dept;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


4). clear 옵션을 사용하지 않으면, SQL*Plus 세션을 끝낼때 까지 지정한 포맷형식이 계속 출력에 이용된다.
이번에는 부서의 지역명을 7자리의 포맷으로 맞추어 본다.

SQL> col loc format a7
SQL> select * from dept;

DEPTNO DNAME LOC
---------- -------------- -------
10 ACCOUNTING NEW YOR
K

20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


5). 사용자는 NEW YOR와 K처럼 단어 중간이 잘리는 것을 원치 않을 수도 있다.
단어가 토막나는 것을 막기 위하여, column명령어에 word_wrap을 추가한다.

SQL> col loc format a7 word_wrap
SQL> select * from dept;

DEPTNO DNAME LOC
---------- -------------- -------
10 ACCOUNTING NEW
YORK

20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


6). 워드래핑(Wrapping) 대신에, 사용자는 한 컬럼의 내용 끝을 잘라버리기 위하여
trunc 명령어를 사용할 수 있다.

SQL> col loc format a7 trunc
SQL> select * from dept;

DEPTNO DNAME LOC
---------- -------------- -------
10 ACCOUNTING NEW YOR
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

※ column 명령어로 컬럼의 형식을 설정한다면, SQL*Plus는 컬럼들이 다른 테이블에 있을지라도,
동일한 이름을 가진 모든 컬럼에 대하여 그 형식을 사용하게 된다.
사용자는 각각의 select문 앞에 다른 형식으로 column명령어를 재실행하거나,
Alias를 명시하여 각각의 컬럼명이 유일하게 할 수 있다.

7). 각 사원의 연봉을 구하기 위한 다음의 예는 컬럼 수식 sal*12에 대해 annual_salary라는 별칭을 사용한다.

SQL> select empno,ename,
2 sal*12 annual_salary
3 from emp;

EMPNO ENAME ANNUAL_SALARY
---------- ---------- -------------
7369 SMITH 9600
7499 ALLEN 19200
7521 WARD 15000
7566 JONES 35700
7654 MARTIN 15000
7698 BLAKE 34200
7782 CLARK 29400
7788 SCOTT 36000
7839 KING 60000
7844 TURNER 18000
7876 ADAMS 13200

EMPNO ENAME ANNUAL_SALARY
---------- ---------- -------------
7900 JAMES 11400
7902 FORD 36000
7934 MILLER 15600

14 개의 행이 선택되었습니다.

8). 사용자가 컬럼의 표제로 한 단어 이상을 사용하거나 대소문자를 반드시 구분하고자 한다면,
컬럼의 표제를 " "로 묶어야 한다. 이와 같은 경우에, Annual 과 Salary라는 단어 사이에 _를 사용하지 않아도 된다.

SQL> select empno,ename,
2 sal*12 "Annual Salary"
3 from emp;

EMPNO ENAME Annual Salary
---------- ---------- -------------
7369 SMITH 9600
7499 ALLEN 19200
7521 WARD 15000
7566 JONES 35700
7654 MARTIN 15000
7698 BLAKE 34200
7782 CLARK 29400
7788 SCOTT 36000
7839 KING 60000
7844 TURNER 18000
7876 ADAMS 13200

EMPNO ENAME Annual Salary
---------- ---------- -------------
7900 JAMES 11400
7902 FORD 36000
7934 MILLER 15600

14 개의 행이 선택되었습니다.


9). format 명령어로 컬럼의 표제를 변경하기 위해서 HEADING 옵션을 사용하는 방법이다.

SQL> col dname format a15 heading "Department Name"
SQL> select * from dept;

DEPTNO Department Name LOC
---------- --------------- -------
10 ACCOUNTING NEW YOR
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

※ format 명령어로 컬럼 헤딩을 변경할 때 변경하려는 헤딩의 길이를 충분히 포함할 정도의 폭 넓이를 지정해 줘야 한다.
지정 폭이 충분치 않으면 변경이 제대로 되지 않고, 자릿수에 맞춰 짤리게 된다.
즉, 아래의 예에서는 "Department Name"이라는 컬럼 헤딩이 a10 자릿수 때문에 "Department"까지만 나타난다.

SQL> col dname format a10 heading "Department Name"
SQL> select * from dept;

DEPTNO Department LOC
---------- ---------- -------
10 ACCOUNTING NEW YOR
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

★★★
10). 총계와 소계
오라클 자체내에서도 총계를 계산하기 위하여 sum함수를 내장하고 있지만,
SQL*Plus도 소계, 평균과 총계를 포함하는 요약 줄을 출력하기 위한 break 와 compute 명령어를 제공하고 있다.

comp[ute] 함수(avg,count,max,min,std,sum,var) [lab[el] 텍스트]...
of 계산을 수행할 대상 컬럼명
on 구분이 되는 (break에 사용되는) 컬럼명, 식, 별칭
report

compute 명령에 사용되는 함수
----------------------------------------------
함수 설명
----------------------------------------------
avg 평균값
cou[ut] Null이 아닌 값의 갯수
max[imum] 최대값
min[imum] 최소값
std 표준편차
sum 값의 합계
var[iance] 분산값
----------------------------------------------

emp 테이블의 부서별로 급여 합계를 구하고, 보고서 끝에는 전체 합계를 구하는 보고서를 작성하고 싶다.
부서번호와 사원번호 순서로 정렬을 한다. 부서별 합계를 구한 후에 한줄을 건너뛰게 하고,
부서번호가 중복해서 인쇄되는 것을 막고자 한다.

10-1. 먼저 deptno별로 한 줄을 건너 뛰게 하기 위해서 다음과 같이 한다.
SQL> break on deptno skip 1 on report
10-2. 부서별 급여 합계를 구하고 라벨을 'Subtotal'로 하기 위해선 다음과 같이 한다.
SQL> compute sum label 'Subtotal' of sal on deptno
10-3. 보고서 끝 부분에 한 번 전체 합계를 구해서 라벨을 "Grand Total"로 하기 위해선 다음과 같이 한다.
SQL> compute sum label 'Grand Total' of sal on report
10-4. 그리고, 앞에서 지정한 급여 sal의 포맷 '$9,999'는 합계액에는 부족하므로 늘리도록 한다.
SQL> col sal format $999,999
10-5. 보고서 형식 준비가 끝났으므로, 적당한 질의를 실행시켜 본다.
SQL> select deptno, empno, ename, sal
2 from emp
3 order by deptno, empno;

DEPTNO EMPNO ENAME SAL
---------- ---------- ---------- ---------
10 7782 CLARK $2,450
7839 KING $5,000
7934 MILLER $1,300
********** ---------
Subtotal $8,750

20 7369 SMITH $800
7566 JONES $2,975
7788 SCOTT $3,000
7876 ADAMS $1,100
7902 FORD $3,000

DEPTNO EMPNO ENAME SAL
---------- ---------- ---------- ---------
********** ---------
Subtotal $10,875

30 7499 ALLEN $1,600
7521 WARD $1,250
7654 MARTIN $1,250
7698 BLAKE $2,850
7844 TURNER $1,500
7900 JAMES $950
********** ---------
Subtotal $9,400

DEPTNO EMPNO ENAME SAL
---------- ---------- ---------- ---------

---------
Grand Tota $29,025

14 개의 행이 선택되었습니다.


11). SQL*Plus 출력에 제목달기
---- 다른 포맷팅 명령어와 관련되어, SQL*Plus는 제목을 만들기 위해 두개의 명령어를 제공한다.
ttitle은 각 페이지의 상위에 제목을 명시하기 위한 것이며, btitle은 각 페이지의 하단 부분에
제목을 명시하기 위한 명령어이다.
다음의 예에서, ttitle과 btitle은 제목, 날짜와 현재의 페이지 번호를 나타낸다.

11-1. 우선 보기 좋은 출력을 위해서 적당한 페이지 사이즈와 라인 사이즈를 지정한다.

SQL> set pages 35 ==> pagesize(축약어 pages)는 한 페이지에서의 줄의 수
SQL> set line 50 ==> linesize(축약어 line)는 출력의 한줄에 나타나는 문자의 최대수
SQL> ttitle left '2001-12-17' center 'EMP table'|'Salary Report' - 공백-(하이픈) : SQL*Plus에서 긴 명령을 다음 줄에 쓰기 위해서
> right 'Page' format 99 sql.pno ==> sql.pno는 현재의 페이지번호를 나타내는 SQL*Plus 변수
SQL> btitle '예제' ==> ttile과 btitle에서 위치를 따로 지정하지 않으면 기본적으로 가운데(center)에 위치하게 된다.
SQL> select deptno,empno,ename,sal
2 from emp
3 order by deptno,empno;


2001-12-17 EMP table|Salary Report> Page 1
DEPTNO EMPNO ENAME SAL
---------- ---------- ---------- ---------
10 7782 CLARK $2,450
7839 KING $5,000
7934 MILLER $1,300
********** ---------
Subtotal $8,750

20 7369 SMITH $800
7566 JONES $2,975
7788 SCOTT $3,000
7876 ADAMS $1,100
7902 FORD $3,000
********** ---------
Subtotal $10,875

30 7499 ALLEN $1,600
7521 WARD $1,250
7654 MARTIN $1,250
7698 BLAKE $2,850
7844 TURNER $1,500
7900 JAMES $950
********** ---------
Subtotal $9,400

---------
Grand Tota $29,025





예제

14 개의 행이 선택되었습니다.


★★★ SQL*Plus 시스템 변수 ★★★

SQL*Plus는 각각의 SQL*Plus 세션의 특성을 통제하는 많은 시스템 변수를 채택하고 있다.
예를 들어, SET명령어는 특정 값으로 시스템 변수를 설정하며, SHOW명령어는 시스템 변수의
현재 설정을 볼 수 있다. 또한 사용자는 모든 시스템 변수 설정을 보기 위하여 SHOW ALL명령어를 사용한다.

SQL> show all

▶ autocommit
autocommit(축약어 auto)은 SQL*Plus의 트랜잭션을 실행완료(commit)하는 방법을 통제한다.
autocommit이 on으로 설정되어 있으면, SLQ*Plus는 각각의 SQL문이 처리된 후에 실행완료된다.
즉, autocommit이 on으로 설정된 상태에서, 사용자가 실수로 테이블에서 일부 레코드들을 삭제했다면
사용자는 트랜잭션을 rollback 할 수 없다.
사용자는 일반적으로 autocommit을 off로 설정하는 것이 좋다.

SQL> show autocommit
autocommit OFF

▶ echo
SQL*Plus가 처리하는 SQL문을 반복하지 않으려면, echo를 off로 설정한다. 일반적으로 결과물을 만들어낸 SQL문 없이,
원하는 결과문만을 보고싶은 보고서를 준비하는 경우에 off로 설정한다.

SQL> show echo
echo OFF

▶ feedback
시스템 변수 feedback(축약어 feed)은 질의가 반환하는 레코드 수를 SQL*Plus가 나타내는 시기를 통제한다.
feedback의 기본적인 설정은 6이다. 즉, 질의가 6개 이상의 레코드를 조회하면, SQL*Plus는 레코드의 수를 보여준다.
질의가 6개 미만을 반환하면, SQL*Plus는 이 feedback 기능을 제공하지 않는다.
사용자는 feedback을 유발하는 레코드의 수를 설정할 수 있다.

SQL> show feedback
6 또는 그 이상의 행에 대한 FEEDBACK ON
SQL> select * from emp where deptno=10;

EMPNO ENAME JOB MGR HIREDATE SAL COMM
---------- ---------- --------- ---------- -------- ---------- ----------
DEPTNO
----------
7782 CLARK MANAGER 7839 2572.5
10

7839 KING PRESIDENT 5500
10

7934 MILLER CLERK 7782 920
10


SQL> set feedback 2
SQL> select * from emp where deptno=10;

EMPNO ENAME JOB MGR HIREDATE SAL COMM
---------- ---------- --------- ---------- -------- ---------- ----------
DEPTNO
----------
7782 CLARK MANAGER 7839 2572.5
10

7839 KING PRESIDENT 5500
10

7934 MILLER CLERK 7782 920
10


3 개의 행이 선택되었습니다. <--- feedback이 나타나는 것을 볼 수 있다.

▶ heading
--- heading(축약어 head)은 기본적으로 SQL*Plus는 컬럼 표제를 나타낸다.
표제를 보지 않으려면, heading을 off로 설정하면 된다.

SQL> show heading
heading ON
SQL> set heading off
SQL> select * from dept;

10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

▶ linesize
--- linesize(축약어 line)는 출력의 한 줄에 나타나는 문자의 최대수를 통제한다.

SQL> show line
linesize 80
SQL> set line 150

그러나 사용자가 linesize를 증가시키면, 메뉴바에서 '옵션--환경'을 선택한 후
윈도우 스크린 버퍼의 너비도 늘려야 한다.

SQL> select * from emp where deptno=10;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 2572.5 10
7839 KING PRESIDENT 5500 10
7934 MILLER CLERK 7782 920 10

▶ long
사용자가 한 컬럼에 2,000자 이상을 반드시 저장해야 한다면, 사용자는 오라클의 long 데이터형을 사용하여
컬럼을 정의해야 할 것이다. SQL*Plus는 사용자가 long 시스템 변수를 늘리지 않는 한,
long 컬럼의 80자 이상은 나타내지 않을 것이다. 사용자가 예를 들어 5,000자 까지 나타내야 한다면,
long을 5,000으로 설정해야 한다. 이밖에도 사용자는 arraysize(축약어 array)를 1로 줄여야 한다.
arraysize는 데이트베이스의 데이터 인출 크기를 가리키는 환경 변수이다.

SQL> show long
long 80
SQL> show arraysize
arraysize 15

▶ pagesize
pagesize(축약어 pages)는 한 페이지에서의 줄의 수를 정의하며, 컬럼의 표제와 페이지 제목이 표현되어야
할 시기를 결정한다. 사용자가 모든 제목과 컬럼 표제를 없애려면, pagesize를 0으로 설정한다.

SQL> show pagesize
pagesize 14
SQL> set pagesize 0
SQL> select * from dept;
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SQL> set pages 24

▶ pause
사용자가 많은 레코드를 조회하는 질의를 실행하면, SQL*Plus의 기본적인 행동은 스크린에 그 결과를 쉴새 없이 보낸다.
사용자가 pause(축약어 pau)를 on 또는 문자열로 설정하면, SQL*Plus는 사용자가 리턴키를 누른 후에 다음 결과를 스크린에
계속 보내게 된다.

SQL> select * from user_tables;

SQL> show pause
PAUSE는 OFF
SQL> set pause on
SQL> select * from user_tables;

▶ time
사용자는 time(축약어 ti)을 on으로 설정하여, SQL*Plus 프롬프트에 현재 시각을 포함시킬 수 있다.
사용자는 출력을 파일로 spooling 할 때, 이 설정이 유용하다는 것을 알게 될 것이다.

SQL> show time
time OFF
SQL> set time on
12:08:37 SQL> set time off
SQL>

▶ timing
timing(축약어 timi)은 각각의 SQL명령어에 대한 게시(timing) 통계의 표현을 on 또는 off로 설정한다.
SQL> show timing
timing OFF
SQL> set timing on
SQL> select * from dept;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

경 과: 00:00:00.10

SQL> set timing off


▶ 대입변수를 사용한 질의 작성하기

-- SQL*Plus 내에서, 사용자는 SQL문에서 대입 변수를 참조할 수 있다.
대입 변수로 사용자는 다른 값으로 동일한 SQL문을 재실행할 수 있다.
한 개 또는 두개의 &로 사용자 변수명 앞에 두어 대입 변수를 표시한다.

SQL> select empno,ename,job,sal
2 from emp
3 where sal > &sal_value;
sal_value의 값을 입력하십시오: 3000
구 3: where sal > &sal_value
신 3: where sal > 3000

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7839 KING PRESIDENT 5500
7566 JONES MANAGER 3123.75
7658 CHAN ANALYST 3450

그런데, sal이 4000 보다 큰 사원들도 결과로 얻고 싶다. 이 때에는 질의문을 두 번 작성하지 않고,
대입변수를 사용하면 간단히 해결할 수 있다.

SQL> /
sal_value의 값을 입력하십시오: 4000
구 3: where sal > &sal_value
신 3: where sal > 4000

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7839 KING PRESIDENT 5500

<예제2>
SQL> select empno,ename,job,sal
2 from emp
3 where sal > &sal_value
4 and lower(job) like '%&job_value%'; -- 문자열 변수에는 반드시 ' '를 한다.
sal_value의 값을 입력하십시오: 3000
구 3: where sal > &sal_value
신 3: where sal > 3000
job_value의 값을 입력하십시오: manager
구 4: and lower(job) like '%&job_value%'
신 4: and lower(job) like '%manager%'

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7566 JONES MANAGER 3123.75


▶ 사용자 변수를 설정하는 다른 방법
SQL*Plus는 사용자 변수를 설정하는 define과 accept 명령어가 있다.
define 명령어로 사용자는 사용자 변수를 만들고 문자 값을 여기에 부여할 수 있다.
특히, define명령어는 char 데이터형을 정의하고 싶을 때 많이 사용한다.

SQL> define job_value = 'MANAGER'
SQL> select empno,ename,job,sal
2 from emp
3 where upper(job) like '%&job_value%';
구 3: where upper(job) like '%&job_value%'
신 3: where upper(job) like '%MANAGER%'

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7782 CLARK MANAGER 2572.5
7566 JONES MANAGER 3123.75

define으로 정의된 변수는 undefine 명령을 사용할 때까지 그 상태를 유지하게 된다.

SQL> undefine job_value

=============================================================
d:\g\db\oracle\new_mine\대입변수.sql의 내용

accept job_value prompt '직업명을 입력하세요: '

select empno,ename,job,sal
from emp
where lower(job) = '&job_value'
/
=============================================================

SQL> @ d:\g\db\oracle\new_mine\대입변수.sql
직업명을 입력하세요: clerk
구 3: where lower(job) = '&job_value'
신 3: where lower(job) = 'clerk'

EMPNO ENAME JOB SAL
---------- ---------- --------- ----------
7934 MILLER CLERK 920


원문: http://blog.naver.com/lyjiny/60002865980
반응형

'ORACLE > SQL' 카테고리의 다른 글

NOT IN과 NOT EXISTS의 차이점  (0) 2010.04.02
EXECUTE IMMEDIATE를 이용한 Dynamic SQL  (0) 2010.01.04
DB 최적화를 고려한 다건조회 페이징처리  (0) 2010.01.03
SQL TIP  (0) 2010.01.03
nvl2  (0) 2010.01.03
Posted by [PineTree]
ORACLE/SQL2010. 1. 3. 14:10
반응형

오라클(Oracle)을 사용하여 다건조회(페이징) 처리를 해야하는 경우가 종종 있습니다.

물론 SQL 쿼리는 여러가지 방식으로 만들수 있고
다양한 방식이 존재하기에 어느하나가 정답이라고 할 수는 없습니다.


다만 실제 업무에서 개발중인 노하우를 공유하는 일환으로
다건조회(페이징) 처리시 DB의 성능 (대부분은 검색 속도와 관련된 부분이겠지요..)과 관련한 최적화된 쿼리 방식을 알려드리도록 하겠습니다.

이는 실제 DBA에게서 권고 받은 것이기 때문에 검증을 거쳤다고 할 수 있습니다.

자 그럼 아래를 참고하시어 최적화된 다건조회 쿼리 작성에 도움이 되시길 바랍니다.

## 1개 컬럼으로 페이징처리

SELECT *
FROM (
 SELECT ...
 WHERE ...
 AND A >= : io_nx_a
 ORDER BY A
)
WHERE ROWNUM <= 51

## 2개 컬럼으로 페이징처리

SELECT *
FROM (
SELECT ...
WHERE ///
AND A >= :io_nx_a
AND ( A > :io_nx_a
    OR ( A = :io_nx_a AND B >= :io_nx_b)
)
ORDER BY A, B)
WHERE ROWNUM <= 51

## 3개 이상의 다수개 컬럼으로 페이징처리

예) 5개 컬럼일 경우

SELECT *
FROM (
SELECT ...
WHERE ///
AND A >= :io_nx_a
AND (  A > :io_nx_a
     OR ( A = :io_nx_a AND B > :io_nx_b) )
     OR ( A = :io_nx_a AND B = :io_nx_b AND C > :io_nx_c)
     OR ( A = :io_nx_a AND B = :io_nx_b AND C = :io_nx_c AND D > :io_nx_d)
     OR ( A = :io_nx_a AND B = :io_nx_b AND C = :io_nx_c AND D = :io_nx_d AND E >= :io_nx_e)
)
ORDER BY A, B, C, D, E)
WHERE ROWNUM <= 51

(*) 제일 마지막의 OR에서만 '>='이고 나머지 OR에서는 '>'입니다.
반드시 ORDER BY에 기술된 컬럼들이 UNIQUE여야 하고 UNIQUE가 아닐 경우 이미 가이드 했던 것처럼 ROWID를 이용하셔야 합니다. SQL 가이드 참조

DBA의 말에 따르면 위와같은 방식으로
페이징 처리를 해주는 것이 DB(데이타베이스)의 성능향상에 도움이 된다더군요.

실제 예제는 아래처럼 사용됩니다.

SELECT /*+TB_CS_JH_CH_MCHTGRP_VS0001*/ *
 FROM
(
 SELECT
         a.mcht_grp_no,
         b.mcht_grpnm,
         a.mcht_no,
         c.mcht_mtalnm,
         a.apl_st_dt,
         a.apl_ed_dt
 FROM
       tb_cs_jh_ch_mchtgrp  a,
       tb_cs_jh_cm_mchtgrp  b,
       tb_cs_mc_cm_bsc      c
 WHERE a.mcht_no >= :mcht_no
   AND ( a.mcht_no > :mcht_no
          OR ( a.mcht_no = :mcht_no AND a.mcht_grp_no > :mcht_grp_no )
          OR ( a.mcht_no = :mcht_no AND a.mcht_grp_no = :mcht_grp_no  AND a.apl_st_dt >= :apl_st_dt )
           )

  AND  b.mcht_grp_no  =  a.mcht_grp_no 
     AND  b.apl_st_dt    <=  a.apl_st_dt
      AND  b.apl_ed_dt    >=  a.apl_ed_dt
     AND  c.mcht_no      =  a.mcht_no
 ORDER BY
       a.mcht_no, a.mcht_grp_no, a.apl_st_dt
)
WHERE ROWNUM <= 16

설명을 덧붙이자면
페이징시  메인 키가 되는 A >= :io_nx_a 의 인덱스서칭 시간만큼
OR을 동반한 올 시퀀스 서치시간을 줄여줄 수 있기 때문에 실제로 DB 검색시 속도향상 효과를 기대할 수 있습니다.

유용하게 사용하시기 바랍니다. ^^
반응형

'ORACLE > SQL' 카테고리의 다른 글

EXECUTE IMMEDIATE를 이용한 Dynamic SQL  (0) 2010.01.04
SQL *Plus 명령어와 SQL문 구분하기  (0) 2010.01.03
SQL TIP  (0) 2010.01.03
nvl2  (0) 2010.01.03
UNION  (0) 2010.01.03
Posted by [PineTree]
ORACLE/SQL2010. 1. 3. 13:19
반응형
* 이 팁들은 oracleclub.com의 질문과 답변에 올라온 글을 제가 정리했습니다.
 
1. 10%를 랜덤하게 가져옵니다.(오라클 8.1.7 이상부터 지원이 됩니다.) [하얀그림자님 답변글]

SQL> SELECT *
        FROM table_name
        SAMPLE (10);

 

2. 오라클에서 CASE문 사용 예제 [하얀그림자님 답변글]

SQL>SELECT col,
           CASE
             WHEN col >= 0  AND col < 6  THEN ’A’
             WHEN col >= 6  AND col < 14 THEN ’B’
             WHEN col >= 14 AND col < 22 THEN ’C’
             WHEN col >= 22 THEN ’D’
           END
      FROM table_name;




3. 해당년도의 선택된 주의 첫번째 날자를 구하고 싶습니다.[석철희님 답변글]

[질문]
해당년도의 선택된 주의 첫번째 날자를 구하고 싶습니다.
 
예로 2002년 36번째 주의 첫번째 날자는 2002/09/02입니다.
2002년 36번째주를 가지고 ’2002/09/02’이란 해당주의 첫번째 날자를 구하고 싶습니다.
 

[답변][석철희님 답변글]

SQL> SELECT NEXT_DAY(TO_DATE(해당년도||’0101’,’RRRRMMDD’) + (선택한주 - 2) * 7, 2)
         FROM DUAL;
 

SQL> SELECT NEXT_DAY(TO_DATE(2003||’0101’,’RRRRMMDD’) + (2 - 2) * 7, 2)
         FROM DUAL;
NEXT_DAY
--------
03/01/06
 
 
==> FROM 앞에 2 는 월요일을 그 주에 첫번째로 선택한 거니깐 일요일을
    그 주의 첫번째 날로 바꾸시려면 1로 바꾸시면 됩니다.
 


4. DB 테이블 내용 복사 대해서[하얀그림자님 답변글] 

1). Table A와 Table B 가 있는데. A의 내용을 B로 복사하는 방법

SQL>INSERT INTO b SELECT * FROM a;
 
 
2). Table A가 있고 Table B를 생성하면서 복사하는 방법

SQL>CREATE TABLE b AS SELECT * FROM a;


3). Table A가 있고 Table A와 구조가 같고 내용은 복사하지 않는 Table B 생성 방법
 
SQL>CREATE TABLE b AS SELECT * FROM a WHERE 1 = 2;



5.점수별로 몇명씩 있는지 알고 싶습니다 .[배경열님 답변글]
 
[질문]
이름 점수
===============
홍길동 90
김길동 98
이길동 75
성춘향 60
이동국 30
최성국 100
김남일 85
 
일때 .....
점수별로 몇명씩 있는지 알고 싶습니다 ..
 
원하는 결과값
=============
점수대 명수
===============
90-100 3
80-89 1
0-79 3


[답변 ]
Sign Function을 쓰세요.
SELECT
        DECODE(SIGN(점수-89),1,’90-100’,
        DECODE(SIGN(점수-79),1,’80-89’,’0-79’)),
        COUNT(*)
FROM
        성적
GROUP BY
        DECODE(SIGN(점수-89),1,’90-100’,
        DECODE(SIGN(점수-79),1,’80-89’,’0-79’))
ORDER BY 1 DESC




6. 컬럼에 해당하는 테이블명 알아내기..
 
SQL>SELECT TABLE_NAME
        FROM  USER_TAB_COLS
        WHERE COLUMN_NAME =’BOARD_ID’
 
이렇게 하시면 됩니다..
컬럼관련 정보는 USER_TAB_COLS 데이터사전을 통해 확인할 수 있습니다.
COLS라는 시노님을 이용해도 됩니다.


SQL>SELECT COUNT(COLUMN_NAME) "Column Count"
    FROM COLS
    WHERE TABLE_NAME =’STORM_BOARD’



시간날때마다 틈틈히 추가하겠습니다.      

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

'ORACLE > SQL' 카테고리의 다른 글

SQL *Plus 명령어와 SQL문 구분하기  (0) 2010.01.03
DB 최적화를 고려한 다건조회 페이징처리  (0) 2010.01.03
nvl2  (0) 2010.01.03
UNION  (0) 2010.01.03
case  (0) 2010.01.03
Posted by [PineTree]