'DBMS/Oracle'에 해당되는 글 4건

  1. 2013.07.25 SQL 표준 가이드(스압)
  2. 2013.07.25 로또
  3. 2013.07.25 달력
  4. 2013.07.25 구구단
2013. 7. 25. 17:05
전용뷰어 보기

   
   
 

프로젝트

개발표준

문서 이름

SQL 표준 가이드

문서 번호

 

문서 구분

관리본

개정 번호

Ver 1.0

문서 보안

일반 / 대외비 극비

개정 일자

2009-05-01

  

중앙정보전산원

 

 

SQL 표준 가이드

(Standard SQL guide)

 

 

 

 

 

 

 

 

 

 

 

Copyright ⓒ KNU & PLAYTOGETHER Co., Ltd.

플레이투게더 및 강원대학교의 사전 승인 없이 본 내용의 전부 또는 일부에 대한 복사배포 및 사용을 금합니다.

 


개정 사항

 

날짜

Rev. No

수정 내용

비고

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


   

1. 개요

2. SQL 공통 표준

2.1. SQL 명명규칙(Naming Convention)

2.1.1. ID 길이

2.1.2. ID 구성문자

2.1.3. 대소문자 사용규칙

2.1.4. 국제 명명규 표준 준수

2.1.5. 서술적인 접두어(prefix) 사용 자제

2.1.6. 표준 접미어(postfix) 지정

2.1.7. 테이블(view) 이름

2.1.8. 별칭(alias)

2.1.9. 관계성이 함축된 이름

2.1.10. 메타데이터 성격을 가진 이름

2.1.11. 데이터 요소 명명  피해야  사항

2.1.12. 대소문자 사용

2.2. SQL 코딩규칙(Coding Convention)

2.2.1. 공백(space)사용

2.2.2.  간격

2.2.3. 들여쓰기(indentation)

2.2.4. 일반적인 마침법의 준수

2.2.5. 예약어(Reserved Word) 사용

2.2.6. SQL 수직 배치

2.2.7. 주석(comment) 사용

3. SQL 작성 표준

3.1. SQL 작성시 기본적인 지침

3.1.1. 표준기능의 사용

3.1.1.1.       OUTER JOIN 표기법 (권장)

3.1.1.2.       ISO표준 기간 표기법

3.1.2. 간결한 표기법을 사용

3.1.2.1.       필요 없는 괄호의 사용

3.1.2.2.       CASE  사용시 주의 사항

3.1.2.3.       불필요한 비교문

3.1.2.4.       수식을 간소화하여 

3.1.3. 주석 사용시 주의사항

3.1.4. 옵티마이저用 힌트(Hint) 사용자제

3.1.5. SQL Stored Procedure 사용 권장

3.1.6. UNION 사용 자제

3.1.7. 정렬과 관련된 SQL문의 남용 금지

3.1.8. WHERE 절에 긍정적 조건의 사용

3.2. SQL 작성시 기본적인 절차

3.2.1. SQL 테스트

3.2.2. SQL 수행비용 검증

3.2.3. OLAP 성격의 업무 개발시 주의사항

4. SQL 작성 지침

4.1. DDL(Data Definition Language) 작성 지침

4.1.1. Default 값은 데이터 타입과 일치하는 값을 사용

4.1.2. Data Type  문자 타입은 일관성을 유지

4.1.3. 테이블 생성시 주키(Primary Key) 가장 위에 배치

4.1.4. 컬럼을 논리적인 순서로 배열  논리적인 그룹 지정

4.1.5. 제약조건 이름은 명확하게 기술

4.1.6. 수치형 컬럼은 범위 제약사항을 두도록 고려

4.1.7. 실수형 타입(REAL, FLOAT ) 사용 자제

4.1.8. 가능하면 모든 테이블이 키를 갖도록 설계

4.1.9. 속성(Attribute) 쪼개거나 합하지  

4.2. DML(Data Manipulation Language) 작성 지침

4.2.1. NULL 사용 지침

4.2.2. IN 사용 지침

4.2.3. MIN, MAX 사용 지침

4.2.4. UNION, UNION ALL 사용 지침

4.2.5. MINU 함수의 활용

4.2.6. OR 사용시 주의사항

4.2.7. 부정형 사용 금지 원칙

4.2.8. NVL 활용 원칙

4.2.9. OUTER JOIN 활용 방안

5. SQL 사용 지침

5.1. 인덱스(Index) 사용

5.1.1. 인덱스 사용지침

5.1.2. 인덱스 적용 원칙

5.1.2.1.       인덱스 컬럼은 원형 그대로 사용할 

5.1.2.2.       인덱스 사용시 부정형을 사용 금지

5.1.2.3.       인덱스 컬럼을 NULL 비교 금지

5.2. (View) 사용

5.2.1. (View) 명명법

5.2.2. 보안성을 높이려면 (View) 사용할 

5.2.3. 데이터에 대한 검증을 위해서 (View) 사용할 

5.2.4. 사용자의 요구로 인한 복잡성을 줄이기 위해 (View) 사용

5.2.5. 2 데이터를 도출할  (View) 사용하면 도움이 된다.

5.2.6. 테이블의 컬럼명이 복잡하거나 어려울  (View) 사용할 

5.2.7. 복잡한 제약사항을 단순화하기 위해 (View) 사용할 

5.2.8. 뷰를 생성하려면 그에 합당한 이유가 있어야 한다.

5.2.9. 뷰를 남용하지  

 

 


1. 개요

 가이드는 강원대학교의 SQL 작성 표준 가이드입니다 문서에서는 개발 단계에서 개발표준과 최적화에 고려해야  사항에 초점을 맞추어 내용을 기술 하였습니다기준이 되는 데이터베이스는 오라클(Oracle) 제한하였으나 명명규칙등 일반적인 사항은 데이터베이스 시스템에 종속되지 않으므로  가이드를 적용할  있습니다.

 문서는 아래와 같은 구조로 되어 있습니다.

·         SQL 공통 표준

o    SQL 명명규칙(Naming Convention)

o    SQL 코딩규칙(Coding Convention)

·         SQL 작성 표준

o    SQL 작성시 기본 지침

o    SQL 작성시 기본 절차

·         SQL 작성 지침

o    SQL 작성지침 - DDL(Data Definition Language)

o    SQL 작성지침 - DML(Data Manipulation Language)

·         SQL 사용 지침

o    인덱스(Index) 사용하기

o    (View) 사용하기


2. SQL 공통 표준

2.1. SQL 명명규칙(Naming Convention)

2.1.1. ID 길이

·         원칙

    • ID 길이는 18바이트를 넘지 않도록 작성한다.
    • 지나치게 짧은 ID 원래 의미를 상실하기 쉬우며 가독성을 떨어뜨린다.

·         설명

    •  DBMS별로 최대허용길이가 다르지만 공통으로 사용할  있는 길이는 18바이트이다.
    • 길이가  경우 DBMS간의 이식성을 떨어뜨리게 된다.

2.1.2. ID 구성문자

·         원칙

    • 알파벳과 숫자밑줄(underscore)외의 특수문자는 사용하지 않는다.
    • 밑줄(underscore) 연속으로 사용하지 않는다.
    • ID 명명할  모음을 지나치게 생략하지 않는다.

·         설명

    • 특수문자가 들어간 ID 가독성이 떨어진다.
    • 밑줄문자(underscore) 연속으로 사용하면 해당 코드를 읽을  밑줄문자가   사용되었는지 인식하기 힘들다.

2.1.3. 대소문자 사용규칙

·         원칙

    • 대소문자 사용원칙을 정했으면 일관성 있게 고수한다. (대문자 권장)

·         설명

    • 대소문자 구분여부는 DBMS마다 다르다.

2.1.4. 국제 명명규칙 표준 준수

·         원칙

    • 국제 명명규칙 표준(ISO-11179) 준수할 
    • 국가명이나 국가코드에 대한 명명은 ISO-3166 표준을 따른다.
    • 날짜 표기에 대한 형식은 ISO-8601 표준을 따른다.
    • 아무리 우수한 국제 표준이라도 레거시 시스템에서 관습적으로 사용하는 것을 우선하여 적용한다.

·         설명

    • SQL 연관된 ISO-11179
      • SQL 연관된 ISO-11179 표준 도메인은 11179-4으로데이터 요소  스칼라(Scalar) 타입은 아래와 같은 원칙을 준수한다.
      • 국가명이나 국가코드 표준에 대한 자료는 아래를 참고한다.
      • 아무리 우수한 국제표준 명명규칙이라도 관행으로 굳어졌거나 관습적으로 사용하는  보다 우선하여 사용하지 못한다.

2.1.5. 서술적인 접두어(prefix) 사용 자제

서술적인 접두어(prefix) SQL문을 읽거나 분석할 때 도움이 되지 않는 경우가 많으며 오히려 그 반대의 경우가 더 많다.

·         원칙

    • 테이블 ID “tbl_” 등으로 시작하지 않는다.
    • 컬럼ID 해당 컬럼의 소속을 나타내기 위해 테이블ID 접두어를 붙이지 않는다.
    • (view) ID “vw_” 등으로 시작하지 않는다.
    • 특정컬럼이 primary key 또는 foreign key임을 나타내기 위해 해당 컬럼의 ID “pk_” 또는 “pf_” 등으로 시작하지 않도록 한다.
    • 특정 ID 제약사항(constraint)임을 나타내기 위해 다음과 같은 형식의 명명규칙을 사용하지 않도록 한다.
      • <table_id>_CK_<column_id>
    • 트리거(trigger) ID “trig_”  시작하지 않도록 한다.
    • 저장프로시저 ID user-defined-procedure임을 나타내기 위해 “usp_”  시작하지 않는다.
    • 트리거 또는 저장프로시저의 ID <동사><목적어형태로 명명한다.

·         설명

      •  ID 명명할  해당 ID 소속형식을 표현하기 위해 접두어를 붙일 경우 해당 ID 소속 또는 형식이 바뀌면 ID자체를 변경해야  경우가 있는데이렇게 되면 일관성을 잃어버리게 된다.

2.1.6. 표준 접미어(postfix) 지정

ID의 주체가 되는 오브젝트의 형식을 나타내는 접두어(prefix) 대신 해당 오브젝트의 속성을 나타내는 접미어(postfix)을 지정하여 사용하는 것이 낫다.

(데이터베이스 명명규칙 참조)

2.1.7. 테이블(view) 이름

·         원칙

    • 집합적이면서도 대표적인 이름 또는 복수형을 사용할 
      • , 1개의 row만을 유지해야 하는 테이블의 경우는 예외로 한다.
    • 산업표준을 따른다.

2.1.8. 별칭(alias)

  • 원칙
    • 별칭(alias) 사용할  근본이 되는 원래의 이름과 동떨어진 이름은 사용하지 않는다.
  • 설명
    • 별칭(alias, 상관관계에 의해 파생되는 이름) 하나의 이름이며 그것의 존재 원인이 되는 근원 테이블컬럼 또는 수식 등이 있게 마련이다별칭을 사용할  원래의 이름과 동떨어진 이름은 유지보수가 매우 어렵게 만들게 되므로 배제하는 것이 좋으나 지엽적으로 사용할 경우는 간략한 형태로 축약하여 사용하는 것을 허용한다.

 

2.1.9. 관계성이 함축된 이름

  • 원칙
    • 테이블 또는 뷰간의 관계가 서로 엮일 이로 인해 파생되는 엔터티에 대해 가능하면관계성을 표현할  있는 이름을 사용한다.
  • 설명
    • 아래와 같이   엔터티가 관계가 함축된 엔터티의 이름은 관계성을 함축하는 이름을 사용한다.
      • 남자 ‘여자’ 엔터티가 결합된 경우
        • 나쁜  : ManWoman 또는 HusbandsWives
        • 좋은  : Marriage
      • 학생 ‘과목’ 엔터티가 결합된 경우
        • 나쁜  : StudentsCourses
        • 좋은  : Enrollments

 

2.1.10. 메타데이터 성격을 가진 이름

  • 원칙
    • 스키마 등에서 메타데이터 성격을 가진 오브젝트에 한해서 구조체를 나타내는 접미사를사용할  있다예를 들면 인덱스ID 경우 “_ix”  접미사를 사용한다.

 

2.1.11. 데이터 요소 명명  피해야  사항

  • 원칙
    • 애매한 이름은 사용하지  
    • 상반적인 개념의 수식어가 결합된 ID 사용하지  
    • 상황에 따라 변동이   있는 ID 사용하지  
    • 물리모델에서 사용하는 용어(대부분 DBMS 종속적인 용어) 논리모델에서 사용하지 
  • 설명
    • 너무 일반적인 이름은 포괄적이어서 아무런 정보를 전달하지 못하는 경우가 많다.
      •  : amountdateid
    • 객체지향 프로그래밍이 몸에  개발자의 경우 모든 필드에 “_id” 라는 접미사를 붙이려는 경향이 있는데실제 상황에서 의미가 없는 경우가 많다.
    • 논리모델에서 다음과 같은 용어는 물리모델로 전환하는 단계에서 예약어로 사용되는 경우가 많으므로 피해야 한다.
      •  : IDENTITYGUIDROWID 

 

2.1.12. 대소문자 사용

  • 원칙
    • 컬럼ID, 파라미터변수는 소문자로 작성한다.
    • 위의 경우를 제외하고스키마(schema)에서 나오는 오브젝트의  글자는 대문자로 작성한다.
    • 예약어(reserved word) 모두 대문자로 작성한다.
    • 낙타등 표기법(camel-case) 사용하지 않는다.
  • 설명
    • 예약어를 대문자로 작성하는 이유는 특별히 유의해서 보게 하려는 의도를 담고 있기 때문이다.
    • 낙타등 표기법(camel-case) 기존의 Hungarian notation 익숙한 개발자를 위한 것인데(ID 구성하는 단어의  글자만 대문자로 사용하는 표기법), 실제로는 가독성(readability) 떨어뜨리는 요인이 된다.

 

2.2. SQL 코딩규칙(Coding Convention)

여기서는 SQL 코딩 시 가독성 향상을 위해 지켜야 할 문자문장의 배치 등 외형을 중심으로 기술하였습니다.

2.2.1. 공백(space)사용

  • 원칙
    • SQL코딩  가급적 탭을 사용하지 말고 공백문자(space) 사용할 
    • SQL코드의 토큰 좌우에 공백을 사용할 
  • 설명
    • 개발자마다 선호하는 TAB-SIZE 다르기 때문에, SQL 코드 작성시 (TAB) 사용하면 실제 코드가 가독성이 떨어질  있다.
    • 실제 예는 아래와 같다.
      • 나쁜 
        • foobar=21
      • 좋은 
        • foobar = 21

 

2.2.2.  간격

  • 원칙
    •  문장 내에서는  줄씩만 띄어쓰기를  
    • 하나의 프로세스 내에서의  문장은  줄씩 띄어쓰기를  

 

2.2.3. 들여쓰기(indentation)

  • 원칙
    • SQL 사용할   그룹 내에서는 ‘3-space rule’ 사용할   있다. (들여쓰기는 공백 3개로 통일한다.)
    • 서브쿼리(sub-query)에서는 괄호를 시작과 끝의 위치를 일치시킨다.
  • 설명
    • SQL에서의 수직 맞춤 배치는 기존의 3GL 프로그래밍과 달리 공백을 이용한 인덴테이션보다 우선 순위가 높다.
    • 서브쿼리(sub-query)에서는 괄호를 시작과 끝의 위치를 일치시키면 서브쿼리의 영역을쉽게 파악할  있는 이점이 있다.

 

2.2.4. 일반적인 마침법의 준수

  • 원칙
    • 콤마 뒤에 공백을 집어 넣을 
    • 콤마로 분리된 ID 여러 줄에 걸쳐 나올 콤마를 라인 끝이 아닌 라인의 처음에 위치시킬 
    • 세미콜론으로 끝나는 SQL문의 마지막은 New-Line 이나 최소한 공백을 집어 넣을 
  • 설명
    • SQL 문을 읽을  콤마와 마침표를 구분하기 힘들 경우가 많으므로 다음의 예와 같이콤마 뒤에는 공백을 집어 넣는다.
    • 나쁜 
      • SELECT flobs.a,flobs.b,flobs.c,fleq.d
      •   FROM Flobs,Foobar,Fleq;
    • 좋은 
      • SELECT flobs.a, flobs.b, flobs.c, fleq.d
      •   FROM Flobs, Foobar, Fleq;
    • 콤마로 분리된 ID 여러 줄에 걸쳐 쓰여지면다음 예와 같이 콤마를 라인의 처음에 위치시키는 것이 보기에도 좋고 추후 SQL 수정하기에도 수월하다.
      • SELECT flobs.a
      •       ,flobs.b
      •       ,flobs.c,
      •       ,fleq.d
      •   FROM Flobs
      •       ,Fleq
      •  

 

2.2.5. 예약어(Reserved Word) 사용

  • 원칙
    • 예약어는 단축형이 아닌 Full-Name 사용할 
    • 특정 DBMS 종속적인 예약어 대신 표준 예약어를 사용할 
  • 설명
    • 데이터 타입을 제외하고는 되도록이면 예약어는 생략하지 말고 Full-Name 사용하는 것이 좋다예를 들면 “FROM”절에 “Personnel P1” 대신 “Personnel AS P1” 으로 사용하면 좋다.
    • 특정 DBMS 종속적인 예약어를 사용하면 이식성이 떨어진다.

 

2.2.6. SQL 수직 배치

SQL문장이 여러 줄에 걸쳐 기술되어 있을 경우좌우로 지그재그형태로 생긴 모양은 최대한 배제하고다음을 원칙으로 한다.

  • 원칙
    • SELECT(T), UPDATE(E), FROM(M), WHERE(E), AND(D), OR(R), ORDER BY(R), GROUP BY(P)  문자를 다음 SQL문의  문자(SELECT(T), UPDATE(E), INSERT(T), DELETE(E)) 맞춘다.
    • INSERT  VALUES 동일한 위치에서 시작한다.
    • 모든 컬럼은 동일한 위치에서 시작한다. (컬럼 앞에 함수가 나오면 함수명의  글자를 기준으로 맞춤)
    • SELECT(T), UPDATE(E), INSERT(T), DELETE(E뒤로 바로 컬럼명이 나올 경우 다음줄에서  줄의  단어의 (INSERT(T), UPDATGE(E), INSERT(T), DELETE(E))으로 부터  칸을 띄고 작성한다.
    • SELECT, UPDATE, INSERT, DELETE 문의 컬럼 목록은  컬럼만 제외하고 앞에 콤마(,) 시작한다.
    • INSERT 문의 경우 VALUE 절의 값들도  번째 값을 제외하고 모두 콤마로 시작하되 동일한 위치로 정렬한다.
    • FROM 절의 -라인 뷰를 제외한 일반 테이블들은 콤마(,) 구분하되  줄에 연속하여기술하고  줄을 초과하는 경우줄을 바꾸어 윗줄의  테이블 이름에 맞추어 시작한다.
    • -라인 뷰의 내부의 SQL문은 시작괄호 ‘(‘ 바로 다음부터 시작하되위의 내용과 동일한 규칙을 적용하며 -라인 뷰가 끝나면 괄호를 닫은  줄을 바꾸도록 한다.
    • SQL 문의 마지막에 “;”  기술하여 해당 문의 끝을 표시한다.
    • UPDATE 문에서 SET절의 컬럼들은  컬럼만 제외하고 콤마(,) 시작한다.
  • 설명
    • 일반적인 SQL  배치 예시
    • 일반적인 수직배치  (1)
      • SELECT DISTINCT pilot
      •   FROM PilotSkills AS PS1
      •  WHERE NOT EXISTS
      •        (SELECT *
      •           FROM Hangar
      •          WHERE NOT EXISTS
      •                (SELECT *
      •                   FROM PilotSkills AS PS2
      •                  WHERE PS1.pilot = PS2.pilot
      •                    AND P2.plane = Hangar.plane));
    • 일반적인 수직배치  (2): 위의 예에서 괄호의 위치를 수직으로 맞춘 경우이다.
      • SELECT DISTINCT pilot
      •   FROM PilotSkills AS PS1
      •  WHERE NOT EXISTS
      •        (SELECT *
      •           FROM Hangar
      •          WHERE NOT EXISTS
      •                (SELECT *
      •                   FROM PilotSkills AS PS2
      •                  WHERE PS1.pilot = PS2.pilot
      •                    AND P2.plane = Hangar.plane
      •                )
      •        );
      •  
    • SELECT 문의 작성 예시
      • 예시 (1) : SELECT 예약어의 ‘T’ 기준으로 수직배치를  
        • SELECT /*+ 프로그램ID INDEX(a, 인덱스명) */
        •        col1
        •       ,col2 /* Comment */
        •       ,col3
        •       ,DECODE(col4, 1, col4,col4/100)
        •       ,col5 /* Comment */
        •  FROM TB_SAMPLE a
        • WHERE col1 = 123
        •   AND col2 like ‘A%’
        •   AND col3 in (‘A’, ‘B’, ‘C’);
      • 예시 (2) : 주석(comment) SELECT 예약어 바로 다음에 배치한 
        •  SELECT /* 프로그램ID */
        •         col1
        •        ,col2 /* Comment */
        •        ,col3
        •   FROM TB_SAMPLE
        •  WHERE col1 = 123
        •  GROUP BY col2
        • HAVING SUM(col3) > 1000
        •  ORDER BY SUM(col3);
      • 예시 (3): 중첩된 SQL문장의 수직배치 
        • SELECT /* 프로그램ID */
        •        col1
        •       ,col2 /* Comment */
        •       ,col3
        •       ,col4
        •       ,col5 /* Comment */
        •   FROM (SELECT
        •                col1
        •               ,col2
        •               ,col3
        •           FROM TB_SAMPLE1
        •          WHERE col1 BETWEEN 100 AND 200) a
        •       ,TB_SAMPLE2 b
        •  WHERE a.col1 = b.col1
        •    AND b.col2 IN (SELECT
        •                          col1
        •                     FROM TB_SAMPLE3
        •                    WHERE col2 = ‘123’)
        •    AND b.col3 LIKE ‘A%’;
      • 예시 (4) CASE문을 동반한 수직배치의 
        • SELECT /* 프로그램ID */
        •        col1
        •       ,col2
        •       ,col3
        •       ,CASE WHEN col4 = 'AAA' THEN col5 * 1.05
        •             WHEN col4 LIKE '%BB' THEN col5 * 1.1
        •             WHEN col4 IN ('CCC', 'DDD') THEN col5 * 1.2
        •             ELSE col5 * 1.3
        •        END AS 인상급여
        •   FROM TB_SAMPLE;
      • 예시 (5): 왼쪽 괄호가 동반된 수직배치의 
        • SELECT deptno
        •   FROM BIG_DEPT d
        •  WHERE NOT EXISTS
        •        (SELECT deptno
        •           FROM BIG_EMP e
        •          WHERE e.deptno = d.deptno);
      • 예시 (6): UNION 동반한 수직배치의 
        • SELECT deptno
        •   FROM BIG_DEPT d
        •  WHERE NOT EXISTS
        •        (SELECT deptno
        •           FROM BIG_EMP e
        •          WHERE e.deptno = d.deptno);
      •  
    • UPDATE 문의 작성 예시
      • 예시 (1): UPDATE 예약어의 ‘E’ 기준으로 수직배치를  
        •  UPDATE /* 프로그램 ID */ TB_SAMPLE
        •     SET col1 = 123
        •       , col2 = ‘ABC’
        •       , col3 = TO_CHAR(9936)
        •  WHERE col4 = 123
        •    AND col5 LIKE ‘A%’
        •    AND col6 IN (‘A’, ‘B’, ‘C’);
      • 예시 (2): UPDATE 예약어 다음에 주석(comment) 사용한 
        • UPDATE /* 프로그램ID */ TB_SAMPLE1
        •    SET (col1, col2) = (SELECT col1
        •                              ,col2
        •                          FROM TB_SAMPLE2
        •                         WHERE col1 = '111')
        •  WHERE col3 IN (SELECT col1
        •   FROM TB_SAMPLE3
        •  WHERE col2 = '123')
        •    AND col4 LIKE 'A%'
        •    AND col5 IN ('A', 'B', 'C');
      •  
    • INSERT  작성예문
      • 예시 (1): INSERT 예약어의 ‘T’ 기준으로 수직배치를  
        • INSERT /* 프로그램ID */ INTO TB_SAMPLE
        •      (col1
        •      ,col2
        •      ,col3
        •      ,col4)
        • VALUES ('111'
        •        ,'222'
        •        ,'333'
        •        ,'444');
      • 예시 (2): INSERT VALUE 내용을 SELECT 사용하여 처리한 
        • INSERT INTO TB_SAMPLE1
        •      (col1
        •      ,col2)
        • SELECT col3 /* col1 */
        •       ,col4 /* col2 */
        •   FROM TB_SAMPLE2;
    • DELETE  작성예문
      • 예시 (1) : DELETE 예약어의  문자(‘E’) 기준으로 수직배치를  
        • DELETE /* 프로그램ID */ FROM TB_SAMPLE
        •  WHERE col1 = 123
        •    AND col2 LIKE 'A%'
        •    AND col3 IN ('A', 'B', 'C');

 

2.2.7. 주석(comment) 사용

  • 원칙
    • SELECT, UPDATE, INSERT, DELETE 문에서 컬럼목록 다음에 반드시 주석(/* */) 사용하여 프로그램ID 기술한다.
    • 원칙적으로 힌트(HINT) 사용하는 것은 금지하지만불가피하게 힌트(HINT) 사용할경우에는 SQL문의  번째 SELECT, UPDATE, INSERT, DELETE 다음에 반드시 동일한 줄에 프로그램 ID  /* */  이용하여 기술하며, /*+ */  이용하고 프로그램ID 먼저 기술하고 힌트를 기술한다.

3. SQL 작성 표준

3.1. SQL 작성시 기본적인 지침

3.1.1. 표준기능의 사용

  • 제품특성과 연관된 기능보다 표준 기능을 사용  .

3.1.1.1.   OUTER JOIN 표기법 (권장)

  • 조회  특정 DBMS 종속된 SQL 사용하는 예는 바람직하지 않으며 이식에 문제를 발생시키게 된다. ( 사항은 권장 사항임)

 

3.1.1.2.  ISO표준 기간 표기법

  • ISO-8601 표준 표기법인 “YYYY-MM-DD hh:mm:ss.sssss”  사용할 

3.1.2. 간결한 표기법을 사용

3.1.2.1.  필요 없는 괄호의 사용

다음과 같이 불필요한 괄호는 사용하지 않는 것이 좋다.

  • SELECT a, b, c
  •   FROM Foobar
  •  WHERE (a = b)
  •    AND (c < 42);

3.1.2.2.  CASE  사용시 주의 사항

  • CASE문은 엄밀하게 말하면 문장(statement) 아니라 수식(expression)이기 때문에 반드시하나의 값을 반환한다는 것에 유의할 (만약 조건  만족하는 것이 없으면 묵시적으로 “ELSE NULL”  추가된다.
  • 명시적으로 NULL 반환할 때는 “CAST (NULL AS <datatype>)” 형태를 사용할 
  • CASE문을   “<CASE operand>” 대신에 Searched CASE 수식을 사용할 
    • 바람직하지 않은 
      • CASE iso_sex_code
      • WHEN 0 THEN ‘Unknown’
      • WHEN 1 THEN ‘Male’
      • WHEN 2 THEN ‘Female’
      • WHEN 9 THEN ‘N/A’
      • ELSE NULL END
    • 바람직한 
      • CASE
      • WHEN iso_sex_code = 0 THEN ‘Unknown’
      • WHEN iso_sex_code = 1 THEN ‘Male’
      • WHEN iso_sex_code = 2 THEN ‘Female’
      • WHEN iso_sex_code = 9 THEN ‘N/A’
      • ELSE NULL END
    • 예외상황
      • NULL 여부와 비교하는 경우는 다음과 같이 SQL 작성하면 에러가 발생하므로 주의해야 한다.
      • CASE
      • WHEN foo = 0 THEN ‘bar’
      • WHEN foo = NULL THEN ‘no_bar’ — error!!
      • ELSE NULL END
  • 가능하다면 COALESCE 또는 NULLIF  사용하여 SQL 깔끔하게 작성한다.
    • (COALESCE, NULLIF 모두 SQL-92 표준이다)

 

3.1.2.3.  불필요한 비교문

다음과 같이 불필요한 비교문은 사용하지 않는다.

  • SELECT a, b, c
  •   FROM Foobar
  •  WHERE a = b
  •    AND b = c
  •    AND c = a;

3.1.2.4.  수식을 간소화하여 사용

  • 간소한 수식 (1)
    • 나쁜 
      • 아래와 같이 작성하면 읽기에도 어려울  아니라, a 컬럼이 인덱스로 구성되어 있어도 인덱스를 활용할  없게 되는 경우가 있다.
      • SELECT a, b, c
      •   FROM Foobar
      •  WHERE a + 2 = b – 4;
    • 좋은 
      • SELECT a, b, c
      •   FROM Foobar
      •  WHERE a = b – 6;
  • 간소한 수식 (2)
    • 구간에 대한 조건을 AND 사용하여 표현하는 것보다 BETWEEN 활용하는 것이 좋다.
      • (인덱스를 활용할  있는지 여부를 먼저 고려해서 사용할 )
  • 간소한 수식 (3)
    • 여러 개의 값과 비교할  OR 사용하여 표현하는 것보다 IN 활용하는 것이 좋다.
  • 중첩되어 복잡한 조건절은 CASE 수식을 사용하여 간략하게 한다.

 

3.1.3. 주석 사용시 주의사항

  • 가능하면 “--“ 보다는 /* */  활용하는 것이 좋다. (경우에 따라 Unary Operator - 혼동이 되는 경우가 있기 때문이다)
  • Stored-Procedure 에서의 주석
    • 항상 Stored-Procedure  줄에 최소한 다음의 사항을 주석으로 표현한다프로시저 이름은 “<동사><목적어>” 형태로 기술하는 것이 좋다.
      • 작성자
      • 날짜
      • 수정 기록
      • 해당 프로시저의 목적/기능
      • 복잡한 제어문에는 항상 주석을 사용할 

 

3.1.4. 옵티마이저用 힌트(Hint) 사용자제

  • 옵티마이저用 힌트는 DBMS 따라 표기법이 달라서 호환이 되지 않는 경우가 많으므로 사용하지 않는 것이 좋다.
  • DBMS 옵티마이저는 대부분의 개발자보다  적은 비용의 전략을  찾아낸다.
  • 힌트를 사용할 일이 없어지거나 인덱스가 변경되면 성능이  떨어지는 경우가 많다.

 

3.1.5. SQL Stored Procedure 사용 권장

  • Stored Procedure 사용하면 다음과 같은 장점이 있다.
    • 보안성 강화
      • Stored Procedure 사용하면 해당 프로시저 내부에서 허용되는 작업만 진행하게 되므로 동적SQL(Dynamic SQL) 사용할 때보다 훨씬 안전하다. (동적 SQL사용하면 SQL내용을 통제할  있는 방법이 없다)
    • 유지보수 용이
      • Stored Procedure 손쉽게 수정하여 업그레이드할  있다. (새로 DBMS 수정하는 순간 re-compile된다)
    • 네트워크 트래픽 감소
      • 네트워크상에서 파라미터 값만 전송되므로 네트워크 전송 효율이 좋아진다.
    • 일관성
      • SQL 모두 Stored-Procedure로만 작성하게 되면 일관성이 생기므로 추후 작업에도 생산성이 높아진다.
    • 모듈성
      • 다른 Stored-Procedure에서도 해당 프로시저를 호출하여 사용할  있으므로 모듈화에 적합하다.

3.1.6. UNION 사용 자제

아직도 대부분 옵티마이저는 UNION을 최적화하는데 어려움을 겪고 있다따라서 가능하다면 UNION ALL 만을 사용하고 나머지는 사용하지 않는 것이 좋다.

 

3.1.7. 정렬과 관련된 SQL문의 남용 금지

다음과 같이 Sort 가 발생하는 SQL 문은 최대한 자제한다.

  • order by
  • group by
  • distinct

 

3.1.8. WHERE 절에 긍정적 조건의 사용

  • 비교하고자 하는 컬럼이 숫자 타입이 확실한 경우를 제외하고 비교 하고자 하는 상수 값을 숫자 타입으로 하지 않는다.
  • OR” 사용을 자제하고 가급적 IN, DECODE 함수를 활용한다.
  • NVL 함수는 불필요하게 사용하지 않는다.
  • WHERE 절의 인덱스 스캔 컬럼에 인위적인 변형을 가하지 말고 반드시 상수(변수쪽에 변형을 가한다.
  • 데이터를 검색할  불필요한 부분은 액세스하지 말고 읽어야 하는 부분만 처리하여 효율을 높인다. ( SELECT 문에서 ‘*’ 사용하지 말고 Named Column 사용한다. )
  • 불필요한 Network 접근을 줄이기 위해 가능하면 SQL 최대한 묶어서 사용한다.

 

3.2. SQL 작성시 기본적인 절차

3.2.1. SQL 테스트

  • 가능한 NULL 관련된 모든 경우의 수를 테스트할 
  • CHECK() 제약사항을 모두 검사하고 테스트할 
  • 테이블의 크기가 커질 경우를 테스트할 

3.2.2. SQL 수행비용 검증

  • 개발자는 작성된 SQL 문에 대한 실행계획을 검증하는 절차를 거친다.

3.2.3. OLAP 성격의 업무 개발시 주의사항

OLTP 성격의 업무에서 아래와 같은 SQL 문에 대해서는 반드시 해당 SQL문의 개선 작업을 수행한다.

  • Full Table Scan
  • Index Fast Full Scan
  • Sort Merge Join

 


4. SQL 작성 지침

4.1. DDL(Data Definition Language) 작성 지침

4.1.1. Default 값은 데이터 타입과 일치하는 값을 사용

당연한 말이지만의외로 많은 개발자가 이 원칙을 지키지 않는다예를 들면

  • Decimal 데이터 타입에 정수 0(zero) default 값으로 사용하는 경우
  • (CHAR(n) 데이터 타입에 길이가 n 보다 적은 문자 스트링을 default 값으로 사용하는 경우
  • TIMESTAMPE 데이터 타입에 DATE 값을 default  사용하는 경우


위의 경우 같은 경우 DBMS에서 원래 데이터 타입에 맞게 묵시적인 변환작업이 일어나는데, DBMS성능에 영향을 미치는 요인이 될 수 있다.

4.1.2. Data Type  문자 타입은 일관성을 유지

  • 오라클 사용자(개발자) 경우 char 대신 varchar2  사용할 
  • 인덱스로 지정될 가능성이 높은 컬럼은 varchar2 지정하여 사용할 

4.1.3. 테이블 생성시 주키(Primary Key) 가장 위에 배치

가독성을 높이기 위해 키에 해당되는 속성은 가장 위에 위치시키는 것이 좋다왜냐하면 키라는 의미 자체가 해당 엔터티의 대표값을 나타내기 때문이다.

4.1.4. 컬럼을 논리적인 순서로 배열  논리적인 그룹 지정

스키마가 완성된 이후에 컬럼을 추가할 때 성능에 영향을 미치는지 고려해야 하는데,다음 순서대로 컬럼을 배치하면 성능에 도움이 된다.

  • 업데이트가 적게 일어나는 고정길이 컬럼
  • 업데이트가 적게 일어나는 가변길이 컬럼
  • 업데이트가 자주 일어나는 컬럼()
    • 업데이트가 동시에 일어나는 성격의 컬럼이 연속되게 배치하면 좋음

4.1.5. 제약조건 이름은 명확하게 기술

제약조건은 ”CONSTRAINT <name>” 형태로 기술하는데제약조건 명을 기술하지 않으면 에러 상황이 발생하였을 때 시스템에서 정한 임의의 이름으로 에러메시지가 발생하므로 오류를 찾기 어렵게 되므로 제약조건의 이름은 명확하게 기술한다PRIMARY KEYSUNIQUEFOREIGN KEY 제약 조건에 대한 이름은 생략한다.

 

4.1.6. 수치형 컬럼은 범위 제약사항을 두도록 고려

데이터베이스는 기업에서 유일하게 신뢰할 수 있는 “저장소이므로비즈니스 룰을 강제할 수 있는 방편으로 제약사항을 두게 된다대개는 테이블의 필드가 0(zero)보다 크도록 제약사항을 두는 경우가 많다.

 

4.1.7. 실수형 타입(REAL, FLOAT ) 사용 자제

하드웨어나 OS, DBMS등에 따라 실수가 표현할 수 있는 정확도의미 등이 달라질 수 있으므로 과학적 수치 또는 통계 값 외에는 REAL, FLOAT 대신 DECIMAL 타입을 사용하는 것이 좋다
 

4.1.8. 가능하면 모든 테이블이 키를 갖도록 설계

키와 관련하여 주의할 사항은 아래와 같다.

  • 자동 채번 컬럼은 관계성 키가 아니다.
  • 파일은 테이블이 아니다.
  • 좋은  속성을 살펴  
    • 유일성(Uniqueness)
    • 안정성(Stability)
      • 쉽게 변하지 않는 값이어야 한다.
    • 친밀성(Familiarity)
    • 검증성(Validation)
      • 사용자 입장에서 검증하기 용이해야 한다.
    • 확인성(Verifiability)
      • 개발자 입장에서 확인하기 용이해야 한다.
    • 단순성(Simplicity)

 

4.1.9. 속성(Attribute) 쪼개거나 합하지  

속성을 쪼개거나 뭉치는 나쁜 사례로 아래와 같은 것이 대표적이다.

  • 데이터를 속성에 따라 다른 테이블로 쪼개는 행위
    • 예를 들면 남자에 대한 정보는 MalePersonnel, 여자에 대한 정보는 FemalePersonnel  분류하는 행위
  • 여러 속성을 하나의 컬럼으로 뭉치는 행위
    • 하나의 속성을 단독 컬럼으로 사용하는 것이 아니라 여러 개의 속성을 하나의 컬럼에 수용하는 행위
    •   개발자는 해당 속성을 분류(설명)하기 위한 메타데이터 성격의 컬럼을 별도로 두는 경향이 있다예를 들면 다음과 같다.
      • 여러 개의 속성을 하나의 컬럼에 저장하는 
        • CREATE TABLE Player_Stats
        • (league_id INTEGER NOT NULL,
        •  player_id INTEGER NOT NULL, -- proprietary auto-number on Players
        •  game_id INTEGER NOT NULL,
        •  stat_field_id CHAR(20) NOT NULL, -- the domain of the number_value
        •  number_value INTEGER NULL,
        • ... );
      • 위의 예를 개선한 
        • CREATE TABLE Player_Stats
        • (league_id INTEGER NOT NULL,
        •  player_nbr INTEGER NOT NULL
        •    FOREIGN KEY (league_id, player_nbr)
        •    REFERENCES Players (league_id, player_nbr)
        •    ON UPDATE CASCADE,
        •  game_id INTEGER NOT NULL
        •    REFERENCES Games (game_id)
        •    ON UPDATE CASCADE,
        •  completions INTEGER DEFAULT 0 NOT NULL CHECK (completions >= 0),
        •  yeards INTEGER 0 NOT NULL CHECK (yards >= 0),
        •  ... -- put other statistics here
        •  ...
        •  Primary key (league_id, player_nbr, game_id);
  • 하나의 속성을 여러 개의 Row 쪼개는 행위
    • 대표적인 예를 들면 시작과 종료 시점을 가진 하나의 데이터를 시간 별로 별도의 ROW 분류하는 행위로 아래의 예를 참고할 
      • 하나의 속성을 여러 개의 Row 분류하는 나쁜 
        • CREATE TABLE Events
        • (event_name CHAR(15) NOT NULL,
        •  event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
        •  ...);
        •       
        • INSERT INTO Events
        • VALUES ((‘start running’, ‘2008-08-12 12:00:00’),
        •         (‘stop running’, ‘2008-08-12 12:34:56’));
      • 위의 예를 개선한 
        • CREATE TABLE Events
        • (event_name CHAR(15) NOT NULL,
        •  event_start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
        •  event_finish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
        •  CHECK (event_start_time < event_finish_time),
        • ...);
        •  
        • INSERT INTO Events
        • VALUES ('running', '2008-08-12 12:00:00', '2008-08-1212:34:56', ...);

 

4.2. DML(Data Manipulation Language) 작성 지침

4.2.1. NULL 사용 지침

  • NULL  사용해야  경우 비교연산자가 아닌 “IS” 또는 “IS NOT” 사용한다.
    • 좋은 
      • IF (@var IS NOT NULL)
      • IF (@var IS NULL)
    • 나쁜 
      • IF (@var = NULL)
      • IF (@var <> NULL)
      • IF (@var != NULL)
      • IF (@var > NULL )
  • 인덱스 비교 부분에서 NULL 사용하지 않는다.
    • 좋은 
      • SELECT
      •        ord_no
      •       ,ord_date
      •       ,item
      •       ,ord_qty
      •   FROM ORDER1T
      •  WHERE ord_date > ' ';
    • 나쁜 
      • SELECT
      •        ord_no
      •       ,ord_date
      •       ,item
      •       ,ord_qty
      •  FROM ORDER1T
      • WHERE ord_date IS NOT NULL
      • ORDER BY ord_date;

4.2.2. IN 사용 지침

  • WHERE 조건에서 ‘OR’ 최대한 배제하고 IN  사용한다.
    • 좋은 
      • SELECT emp_name
      •   FROM Employees
      •  WHERE emp_id IN (1, 2, 5);
    • 나쁜 
      • SELECT
      •        emp_name
      •   FROM Employees
      •  WHERE ((emp_id = 1)
      •     OR (empidn = 2)
      •     OR (empidn = 5));
  • 'BETWEEN' 사용하면 Range Scan 수행하고, 'IN' 사용하면 Point SCAN 수행하므로IN 사용하는 것이  효율적이다.
    • 좋은 
      • SELECT col3
      •       ,col4
      •       ,col5
      •   FROM TAB1
      •  WHERE col1 = ‘A’
      •    AND col2 IN (‘112’,‘111’);
    • 나쁜 
      • SELECT col3
      •       ,col4
      •       ,col5
      •   FROM TAB1
      •  WHERE col1 = ‘A’
      •    AND col2 BETWEEN ‘111’AND ‘112’;
      • SELECT col3
      •       ,col4
      •       ,col5
      •   FROM TAB1
      •  WHERE col1 = ‘A’
      •    AND col2 BETWEEN ‘111’AND ‘112’;
  • UNION 가능하면 IN으로 대체한다.
    • 좋은 
      • SELECT
      •        DISTINCT useid
      •       ,usetypid
      •   FROM JOIN_USER_USERTYPS
      •  WHERE usetypid IN (16, 17);
    • 나쁜 
      • SELECT
      •        DISTINCT useid
      •       ,usetypid
      •   FROM JOIN_USER_USERTYPES
      •  WHERE (usetypid = 16)
      •  UNION
      • SELECT
      •        DISTINCT useid
      •       ,usetypid
      •   FROM JOIN_USER_USERTYPES
      •  WHERE (usetypid = 17);

4.2.3. MIN, MAX 사용 지침

  • 최대값(또는 최소값) 필요한 경우 ORDER BY 대신 MAX(또는 MIN) 함수를 사용한다.
    • 좋은 
      • SELECT
      •        MAX (emp_id)
      •   FROM Employees;
    • 나쁜 
      • SELECT
      •        Emp_id
      •   FROM Employees
      •  ORDER BY empi_d DESC;

4.2.4. UNION, UNION ALL 사용 지침

  • 아래와 같이 UNION ALL 구문을 활용한다.
    • 좋은 
      • SELECT fname
      •       ,lname
      •       ,empidn
      •   FROM Employees
      •  WHERE (empidn < 10)
      •  UNION ALL
      • SELECT fname
      •       ,lname
      •       ,empidn
      •   FROM Employees
      •  WHERE (empidn >= 100);
    • 나쁜 
      • SELECT fname
      •       ,lname
      •       ,empidn
      •   FROM Employees
      •  WHERE (empidn < 10)
      •  UNION
      • SELECT fname
      •       ,lname
      •       ,empidn
      •   FROM Employees
      •  WHERE (empidn >= 100);
  • OR 대신 아래와 같이 UNION ALL  활용한다.
    • 좋은 
      • SELECT COUNT(*)
      •   FROM Chujgo
      •  WHERE :sw = 1 AND chuldate = '20020628'
      •  UNION ALL
      • SELECT COUNT(*)
      •   FROM Chulgo
      •  WHERE :sw = 2
      •    AND RTRIM(chuldate) LIKE '200206%';
    • 나쁜 
      • SELECT COUNT(*)
      •   FROM Chulgo
      •  WHERE (:sw = 1 AND chuldate = ‘20020628’)
      •     OR (:sw = 2 AND RTRIM(chuldate) LIKE ‘200206%’);

 

4.2.5. MINU 함수의 활용

  • 차집합 개념의 ROW 검색하려면 MINUS 함수를 활용한다.
    • 좋은 
      • SELECT dept_nbr
      •   FROM BigDept
      •  MINUS
      • SELECT dept_nbr
      •   FROM BigDept;
    • 나쁜 
      • SELECT dept_nbr
      •   FROM BIG_DEPT
      •  WHERE dept_nbr NOT IN (SELECT dept_nbr
      •                           FROM BigEmp);

 

4.2.6. OR 사용시 주의사항

  • 조건문 안에 OR 사용하면 TABLE FULL SCAN 하게 되므로 주의해야 한다.
    • 좋은 
      • SELECT chulno
      •       ,custno
      •       ,chuldate
      •       ,uncost
      •   FROM Chulgo
      •  WHERE (:sw = 1 AND (status LIKE ‘1%’)
      •     OR (:sw = 1 AND (status LIKE ‘2%’)
      •     OR (:sw = 2 AND (status LIKE ‘3%’)
      •  ORDER BY status;
    • 나쁜 
      • SELECT chulno
      •       ,custno
      •       ,chuldate
      •       ,uncost
      •   FROM Chulgo
      •  WHERE (:sw = 1 AND (status LIKE ‘1%’
      •     OR status LIKE ‘2%’))
      •     OR (:sw = 2 AND (status LIKE ‘3%’))
      •  ORDER BY status;

 

4.2.7. 부정형 사용 금지 원칙

  • WHERE절에 부정형을 사용하면 인덱스 스캔이 불가능하므로 긍정형으로 변형하여 사용한다.
    • 좋은 
      • SELECT 'Not found' INTO :col1
      •   FROM DUAL
      •  WHERE NOT EXISTS
      •        (SELECT 'x'
      •           FROM EMP
      •          WHERE empno = ‘1234’);
    • 나쁜 
      • SELECT 'Not found' INTO :COL1
      •   FROM EMP
      •  WHERE empno <> '1234';

 

4.2.8. NVL 활용 원칙

  • 총계함수 사용  NULL 무시되므로 총계함수 내에서의 NVL함수는 필요하지 않음
    • 좋은 
      • NVL(SUM(trn_amount),0)
    • 나쁜 
      • NVL(SUM(NVL(trn_amount,0)),0)

4.2.9. OUTER JOIN 활용 방안

  •  개의 테이블   쪽에만 값이 있는 경우를 추출할 경우 OUTER JOIN 활용한다.
    • 좋은 
      • SELECT d.deptno
      •   FROM BIG_DEPT d, BIG_EMP e
      •  WHERE d.deptno = e.deptno(+)
      •    AND e.deptno is NULL;
      • 또는
      • SELECT d.deptno
      •   FROM BIG_DEPT d, BIG_EMP e
      •  WHERE d.deptno
      •        LEFT OUTER JOIN
      •        e.deptno
      •    AND e.deptno is NULL;
    • 나쁜 
      • SELECT deptno
      •   FROM BIG_DEPT d
      •  WHERE NOT EXISTS
      •        (SELECT deptno
      •           FROM BIG_EMP e
      •          WHERE e.deptno = d.deptno);

 


5. SQL 사용 지침

5.1. 인덱스(Index) 사용

5.1.1. 인덱스 사용지침

  • 필요한 경우에만 인덱스를 생성하고사용되지 않는 인덱스는 모니터링  삭제한다.
  • 실제 조사된 액세스 종류에 따라서 인덱스를 선정  검증한다.
  • 특정 명령문을 튜닝하기 위해 인덱스를 추가로 생성할 경우 다른 SQL 액세스 경로가 바뀔수도 있으므로 충분한 사전 분석 작업이 필요하다.
  • 각종 액세스 분포도가 자주 조합되어 사용되는 경우는 결합 인덱스로 생성한다.
  • 자주 조합되어 사용되는 경우의 수를 만족할  있도록 인덱스간의 역할을 분담한다.(되도록 많은 access path 수용하도록 한다)
  • 가능한 수정이 빈번하지 않는 칼럼으로 인덱스를 선정한다.
  • 결합 인덱스의 칼럼 순서 선정에 주의 한다 번째 칼럼이 Where 조건에 존재해야 인덱스 scan 가능하다.
  • 반복수행(loop 되는 조건은 가장 빠른 수행속도를 내게 하여야 하므로 인덱스 구성의 대상으로 최우선 고려한다.
  • 넓은 범위(5% 이상) 인덱스로 처리  random access 인한 많은 오버헤드가 발생할 가능성이 있으므로, Table Full Scan 고려해봐야 한다.
  • 인덱스의 개수는 테이블의 사용 형태에 따라 적절히 생성한다왜냐하면 DML 작업이 많은 경우 성능저하의 원인이   있기 때문이다.
  • 조인(join) 시에는 잘못된 인덱스 사용이  부하를 가져올  있으므로인덱스 사용여부에 주의하여야 한다.

 

5.1.2. 인덱스 적용 원칙

5.1.2.1.  인덱스 컬럼은 원형 그대로 사용할 

인덱스 컬럼은 비교되기 전에 변형이 일어나면 인덱스가 사용되지 않기 때문에 되도록이면 WHERE절에서 인덱스 컬럼을 원형 그대로 사용하는 것이 바람직하다.

  • 예시(1)
    • 개선 
      • SELECT dept
      •       ,ename
      •       ,sal
      •   FROM EMP
      •  WHERE SUBSTR(job, 1,4) = '<st1:city w:st="on">SALE</st1:city>';
      •  
    • 개선 
      • SELECT dept
      •       ,ename
      •       ,sal
      •   FROM EMP
      •  WHERE job LIKE '<st1:city w:st="on">SALE</st1:city>%';
  • 예시(2)
    • 개선 
      • SELECT empno
      •       ,ename
      •       ,job
      •   FROM EMP
      •  WHERE (sal * 12) = 35000000;
    • 개선 
      • SELECT empno
      •       ,ename
      •       ,job
      •   FROM EMP
      •  WHERE sal = (35000000 / 12);
  • 예시(3)
    • 개선 
      • SELECT empno,
      •       ,ename
      •       ,job
      •   FROM EMP
      •  WHERE job||dept = 'CLERK10';
    • 개선 
      • SELECT empno,
      •       ,ename
      •       ,job
      •   FROM EMP
      •  WHERE job =‘'CLERK'
      •    AND dept = '10';
  • 예시(4)
    • 개선 
      • SELECT chr
      •       ,num
      •       ,var
      •       ,dat
      •   FROM SAMPLET
      •  WHERE TO_NUMBER(chr) = 10;
    • 개선 
      • SELECT chr
      •       ,num
      •       ,var
      •       ,dat
      •   FROM SAMPLET
      •  WHERE chr =‘'10';
  • 위의 예를 이용하여 다음과 같이 강제로 인덱스를 타지 않게    있다.
    • SELECT SUM(col1)
    •   FROM TAB1
    •  WHERE RTRIM(status) = '90';

 

5.1.2.2.  인덱스 사용시 부정형을 사용 금지

인덱스 컬럼을 부정형(NOT<>)으로 비교할 때도 인덱스가 사용되지 않는다.

  • 예시(1)
    • 개선 
      • SELECT 'Not found' INTO :col1
      •   FROM EMP
      •  WHERE empno <> '1234';
    • 개선 
      • SELECT 'Not found' INTO :col1
      •   FROM DUAL
      •  WHERE NOT EXISTS
      •        (SELECT ‘'X'
      •           FROM EMP
      •          WHERE empno =‘'1234');

 

5.1.2.3.  인덱스 컬럼을 NULL 비교 금지

인덱스 컬럼을 NULL과 비교하여도 해당 인덱스가 사용되지 않는다.

  • 예시(1)
    • 개선 
      • SELECT ord_no
      •       ,ord_date
      •       ,item
      •       ,ord_qty
      •   FROM ORDER1T
      •  WHERE ord_date IS NOT NULL
      •  ORDER BY ord_date;
    • 개선 
      • SELECT ord_no
      •       ,ord_date
      •       ,item
      •       ,ord_qty
      •   FROM ORDER1T
      •  WHERE ord_date > ' ';
      • ord_date 숫자 타입이면
      • SELECT ord_no
      •       ,ord_date
      •       ,item
      •       ,ord_qty
      •   FROM ORDER1T
      •  WHERE ord_date > 0;

 

5.2. (View) 사용

5.2.1. (View) 명명법

뷰의 명명법은 기본적으로 테이블에 대한 명명법과 동일하다다만 뷰의 이름을 'vw’ 또는 'v로 시작하는 것은 피하는 것이 좋다이유는 다음과 같다.

  • 뷰를 나중에 테이블로 전환하는 경우 'vw’  시작하는 이름을 모두 'tbl 바꾸어야 하는 병폐가 생길  있다.

5.2.2. 보안성을 높이려면 (View) 사용할 

5.2.3. 데이터에 대한 검증을 위해서 (View) 사용할 

5.2.4. 사용자의 요구로 인한 복잡성을 줄이기 위해 (View) 사용

사용자 또는 SQL 초보프로그래머를 위해 복잡한 SQL조회 결과를 뷰(View)로 미리 만들어 놓으면 추후 작업할 때 일을 대폭 줄여줄 수 있다

5.2.5. 2 데이터를 도출할  (View) 사용하면 도움이 된다.

기존 테이블의 데이터를 근간으로 2차 데이터를 도출하여 사용할 때 뷰를 정의하여 사용하면 프로그래머의 부담이 줄어든다.

5.2.6. 테이블의 컬럼명이 복잡하거나 어려울  (View) 사용할 

테이블의 컬럼명이 복잡하고 애매할 경우 간결한 컬럼명을 가지는 뷰를 생성하면 기존 컬럼명을 수정하지 않고도 동일한 효과를 얻을 수 있다.

5.2.7. 복잡한 제약사항을 단순화하기 위해 (View) 사용할 

DBMS 마다 테이블에 대한 복잡한 제약사항을 지원하는데 한계가 있으며이 한계는 DBMS마다 다르다이를 극복하기 위하여 뷰(View)을 사용하면 큰 도움이 된다.

5.2.8. 뷰를 생성하려면 그에 합당한 이유가 있어야 한다.

5.2.9. 뷰를 남용하지  

 
   
 


'DBMS > Oracle' 카테고리의 다른 글

로또  (0) 2013.07.25
달력  (0) 2013.07.25
구구단  (0) 2013.07.25
Posted by 1+1은?
2013. 7. 25. 17:01
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
32
SELECT CHR(64+P) P
         , MIN (DECODE (rnum, 1, lottono)) AS N1
         , MIN (DECODE (rnum, 2, lottono)) AS N2
         , MIN (DECODE (rnum, 3, lottono)) AS N3
         , MIN (DECODE (rnum, 4, lottono)) AS N4
         , MIN (DECODE (rnum, 5, lottono)) AS N5
         , MIN (DECODE (rnum, 6, lottono)) AS N6
  FROM (SELECT P, lottono
                       , ROW_NUMBER() OVER(PARTITION BY P ORDER BY DBMS_RANDOM.VALUE) rnum
               FROM (SELECT LEVEL AS P FROM dual CONNECT BY LEVEL <= 5)
                      , (SELECT LEVEL AS lottono FROM dual CONNECT BY LEVEL <= 45))
  WHERE rnum <= 7
  GROUP BY P
  ORDER BY P;
 
 
 P N1 N2 N3 N4 N5 N6
 - -- -- -- -- -- --
 A 28  1 36 37 24 17
 B 26 19  3 41 45 13
 C 34 21 37 24 41 38
 D 20 15 39  3 32 25
 E 15 36 38 45 10 40
 
 
 P N1 N2 N3 N4 N5 N6
 - -- -- -- -- -- --
 A 41 20 33 11 13  7
 B  3  9 14 32  2 26
 C 37 24 13 12 15 40
 D 15 35 12 32 41 40
 E 24  3 11 35 42 22


'DBMS > Oracle' 카테고리의 다른 글

SQL 표준 가이드(스압)  (0) 2013.07.25
달력  (0) 2013.07.25
구구단  (0) 2013.07.25
Posted by 1+1은?
2013. 7. 25. 17:00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT *
 FROM (SELECT MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS SUN
            ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS MON
                           ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS TUE
                           ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS WED
                           ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS THU
                           ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS FRI
                           ,MIN(DECODE(TO_CHAR(YM + LEVEL - 1, 'd'), '1', LEVEL)) AS SAT
         FROM (SELECT TO_DATE(TO_CHAR(SYSDATE, 'YYYYMM'), 'YYYYMM') YM FROM DUAL
              CONNECT BY LEVEL <= LAST_DAY(YM) - YM + 1
              GROUP BY TRUNC(YM + LEVEL, 'iw')
              ORDER BY 7)
 
 
 SUN  MON TUE WED THU  FRI  SAT
 ---- --- --- --- ---- ---- ----
 NULL   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 NULL NULL NULL


'DBMS > Oracle' 카테고리의 다른 글

SQL 표준 가이드(스압)  (0) 2013.07.25
로또  (0) 2013.07.25
구구단  (0) 2013.07.25
Posted by 1+1은?
2013. 7. 25. 17:00


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
SELECT MAX(DECODE(L1, 2, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "2단",
       MAX(DECODE(L1, 3, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "3단",
       MAX(DECODE(L1, 4, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "4단",
       MAX(DECODE(L1, 5, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "5단",
       MAX(DECODE(L1, 6, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "6단",
       MAX(DECODE(L1, 7, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "7단",
       MAX(DECODE(L1, 8, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "8단",
       MAX(DECODE(L1, 9, L1||' * '||L2||' = '||(L1*L2), NULL)) AS "9단"
 FROM (SELECT LEVEL AS L1 FROM DUAL CONNECT BY LEVEL < 10) A,
      (SELECT LEVEL AS L2 FROM DUAL CONNECT BY LEVEL < 10) B
 GROUP BY L2
 ORDER BY L2;
 
 
 2단         3단         4단         5단         6단         7단         8단         9단
 ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
 2 * 1 = 2  3 * 1 = 3  4 * 1 = 4  5 * 1 = 5  6 * 1 = 6  7 * 1 = 7  8 * 1 = 8  9 * 1 = 9
 2 * 2 = 4  3 * 2 = 6  4 * 2 = 8  5 * 2 = 10 6 * 2 = 12 7 * 2 = 14 8 * 2 = 16 9 * 2 = 18
 2 * 3 = 6  3 * 3 = 9  4 * 3 = 12 5 * 3 = 15 6 * 3 = 18 7 * 3 = 21 8 * 3 = 24 9 * 3 = 27
 2 * 4 = 8  3 * 4 = 12 4 * 4 = 16 5 * 4 = 20 6 * 4 = 24 7 * 4 = 28 8 * 4 = 32 9 * 4 = 36
 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25 6 * 5 = 30 7 * 5 = 35 8 * 5 = 40 9 * 5 = 45
 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36 7 * 6 = 42 8 * 6 = 48 9 * 6 = 54
 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49 8 * 7 = 56 9 * 7 = 63
 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64 9 * 8 = 72
 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81

 

 

혹은

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT MIN (DECODE (A, 2, gugu)) AS "2단"
          , MIN (DECODE (A, 3, gugu)) AS "3단"
          , MIN (DECODE (A, 4, gugu)) AS "4단"
          , MIN (DECODE (A, 5, gugu)) AS "5단"
          , MIN (DECODE (A, 6, gugu)) AS "6단"
          , MIN (DECODE (A, 7, gugu)) AS "7단"
          , MIN (DECODE (A, 8, gugu)) AS "8단"
          , MIN (DECODE (A, 9, gugu)) AS "9단"
 FROM (SELECT A, B, A || ' * ' || B  || ' = ' ||  A * B AS gugu
        FROM (SELECT mod(LEVEL -1 ,9) + 1 AS A, trunc((LEVEL - 1)/9) + 1 AS B
               FROM dual CONNECT BY LEVEL <= 81
              )
       )
 GROUP BY B
 ORDER BY B;

 

'DBMS > Oracle' 카테고리의 다른 글

SQL 표준 가이드(스압)  (0) 2013.07.25
로또  (0) 2013.07.25
달력  (0) 2013.07.25
Posted by 1+1은?