Download presentation
Presentation is loading. Please wait.
1
DataBase 기본 교육 신입사원용 최지철
2
데이터베이스 모델링 01 정보모델링 DataBase 1. 데이터베이스 모델링이란
데이터 모델링이라고도 하며, 다른 말로는 개체-관계 모델링이라고도 합니다. 현실의 개념들을 체계적으로 수집하여 정보모델링을 통해 사용자의 정보요구사항을 조사하고, 이를 개체, 관계, 속성을 중심으로 명확하게 체계적으로 표현하고 문서화 하는 기법입니다. 현실세계 데이터 모델링 정보모델링 개념 1 개념 2 개체 Entiy name 개체 Entiy name 개념 3 개념 n 일치 컴퓨터세계 데이터구조화 물리적으로 저장된 DataBase id name tel 개체 Entiy name 개체 Entiy name 1234 김승희 1235 김희석 1236 김미나 1237 김향화 - 개체 : 데이터베이스 내에 표현하고자 하는 유형/무형의 파일 시스템의 레코드에 해당되면 정보를 표현하는 논리적인 단위 - 관계 : 두 개 이상의 개체들 간의 연관성을 결정짓는 의미 있는 연결. - 속성 : 개체의 성질, 분류, 식별, 수량, 상태 등을 나타내는 세부의 관리 요소로써 관계형 데이터베이스에 사용되는 데이터의 최소단위
3
데이터베이스 모델링 01 2. 데이터 모델링의 필요성(1/2) ◈ 데이터 증가에 따른 문제 발생
▷ 데이터가 증가하면서 시스템에는 많은 변화가 생기게 된다. 그 중에서 데이터에 대해서만 확인해 본다면 데이터의 증가와 함께 발생하는 문제는 두 가지로 요약될 수 있습니다. - 데이터의 증가 → 데이터의 중복발생 → 데이터 정합성에 문제 발생 - 데이터의 증가 → SQL 응답 속도 저하 → 성능 저하 ▷ 성능 저하 → SQL의 튜닝 데이터의 정합성 문제 → 애플리케이션에서 해결 단, 근본적인 문제를 해결이 아님. ▷ 데이터의 증가에 따라 더욱 중요해지는 이 두 가지 문제는 최적화된 데이터 모델링을 통해 해결할 수 있으며 이 방법이야말로 근본적인 문제를 해결하는 방법입니다. ▷ 하지만 데이터 모델링은 언제나 할 수 있는 것은 아닙니다. 그러므로 데이터 모델링을 재수행하는 단계에서 최적의 데이터 모델링이 되도록 노력해야 합니다. [그림1] 데이터 증가가 유발하는 문제
4
데이터베이스 모델링 01 2. 데이터 모델링의 필요성(2/2) ◈ 인식의 변화
▷ 우리 주변의 많은 시스템들에서 데이터가 증가하며 그에 따른 문제들이 계속 발견되고 있기 때문에 많은 사람들이 데이터 모델링의 중요성을 인식하게 되었습니다. [그림2] 데이터에 대한 인식의 변화
5
데이터베이스 모델링 01 3. 데이터 모델의 기본 개념의 이해(1/2) ◈ 데이터 모델링의 정의 ▷ 모델링에 대한 다양한 정의
- 정보시스템을 구축하기 위해, 해당 업무에 어떤 데이터가 존재하는지 또는 업무가 필요로 하는 정보는 무엇인지를 분석하는 방법 기업 업무에 대한 종합적인 이해를 바탕으로 데이터에 존재하는 업무 규칙(Business Rule)에 대하여 참(True) 또는 거짓(False)을 판별할 수 있는 사실(사실명제)을 데이터에 접근하는 방법(How), 사람(Who), 전산화는 별개(독립적인)의 관점에서 이를 명확하게 표현하는 추상화 기법 ▷ 실무적 관점(정보시스템 구축)에서의 데이터 모델링을 하는 주요 이유 - 정보시스템 구축 대상이 되는 업무 내용을 정확하게 분석하는 것 - 분석된 모델을 가지고 실제 데이터베이스를 생성하여 개발 및 데이터관리에 사용하기 위한 것 단지 데이터베이스 구축만이 목적이 아니라 데이터 모델링 자체로서 업무를 설명하고 분석하는 부분에도 중요한 의미를 가지고 있습니다. ▷ 데이터 모델링이란 - 정보시스템을 구축하기 위한 데이터 관점의 업무분석 기법 - 현실세계의 데이터(What)에 대해 약속된 표기법에 의해 표현하는 과정 - 데이터베이스를 구축하기 위한 분석/설계의 과정
6
데이터베이스 모델링 01 3. 데이터 모델의 기본 개념의 이해(2/2) ◈ 데이터 모델링이 제공하는 기능
▷ 업무를 분석하는 관점에서 데이터 모델이 제공하는 기능 - 시스템을 현재 또는 원하는 모습으로 가시화하도록 도와줍니다. - 시스템의 구조와 행동을 명세화 할 수 있게 합니다. - 시스템을 구축하는 구조화된 틀을 제공합니다. - 시스템을 구축하는 과정에서 결정한 것을 문서화합니다. - 다양한 영역에 집중하기 위해 다른 영역의 세부사항은 숨기는 다양한 관점을 제공합니다. - 특정 목표에 따라 구체화된 상세 수준의 표현방법을 제공합니다.
7
데이터베이스 모델링 01 4. 모델링의 특징 ◈ 데이터 모델링의 3대 특징
▷ 모델링의 재정의 : 현실세계를 추상화, 단순화, 명확화하기 위해 일정한 표기법에 의해 표현하는 기법 ▷ 정보시스템 구축에서의 모델링 활용 ▷ 계획/분석/설계 단계 : 업무를 분석하고 설계하는데 이용 ▷ 구축/운영 단계 : 변경과 관리의 목적으로 이용 3대 특징 설명 추상화 (모형화, 가설적) 현실세계를 일정한 형식에 맞추어 표현을 한다는 의미로 정리할 수 있습니다. 즉, 다양한 현상을 일정한 양식인 표기법에 의해 표기한다는 것입니다. 단순화 복잡한 현실세계를 약속된 규약에 의해 제한된 표기법이나 언어로 표현하여 쉽게 이해할 수 있도록 하는 개념을 의미합니다. 명확화 누구나 이해하기 쉽게 하기 위해 대상에 대한 애매모호함을 제거하고 정확하게 현상을 기술하는 것을 의미합니다.
8
데이터베이스 모델링 01 5. 모델링의 세가지 관점(1/2) ◈ 모델링의 세가지 관점
▷ 시스템의 대상이 되는 업무를 분석하여 정보시스템으로 구성하는 과정에서 업무의 내용과 정보시스템의 모습을 적절한 표기법(Notation)으로 표현하는 것을 모델링이라고 한다면, 모델링은 크게 세 가지 관점인 데이터관점, 프로세스관점, 데이터와 프로세스의 상관관점으로 구분하여 설명할 수 있다. [그림3] 모델링의 관점 관점 설명 키워드 데이터관점 업무가 어떤 데이터와 관련이 있는지? 데이터간의 관계는 무엇인지? Data What 프로세스관점 업무가 실제하고 있는 일이 무엇인지? 무엇을 모델링 해야 하는지? Process How 데이터와 프로세스의 상관관점 업무가 처리하는 일의 방법에 따라 데이터는 어떻게 영향을 받고 있는지? Interaction (상호작용)
9
데이터베이스 모델링 01 5. 모델링의 세가지 관점(2/2) ◈ 데이터와 프로세스 관점의 데이터 모델링
▷ 데이터와 프로세스 관점에서 데이터 모델링은 프로젝트를 수행할 때 커뮤니케이션의 도구 - 프로젝트 수행시 개발자들은 데이터 모델링의 산출물인 ERD를 통해 의사 소통하는 경우가 많습니다. - ERD에는 기본적으로 데이터에 대한 요소가 포함됩니다. - 업무 프로세스는 ERD에 포함되지는 않지만 데이터와 업무를 완전히 분리할 수 없습니다. [그림4] 데이터와 프로세스, 그리고 데이터 모델링
10
데이터베이스 모델링 01 6. 데이터 모델링의 주체 ◈ 데이터 모델링의 주체
▷ 모델링은 모델러 (Modeler)의 역할(Role)을 가지고 있는 한 사람만을 주체로 하는 것이 아니다. 프로젝트에 관련된 사람 중 데이터와 업무에 관련이 있는 담당자들이 함께 참여해야 성공할 수 있습니다. ▷ 업무를 잘 아는 현업 담당자만 데이터 모델링을 수행하게 되면 데이터 정합성은 보장되더라도 성능이 보장되기는 어렵습니다. ▷ 프로젝트를 리드하는 모든 사람, 데이터 및 업무와 관련된 사람들이 함께 데이터 모델링에 참여해야만 데이터 정합성 및 성능을 고려 할 수 있습니다. [그림5] 데이터 모델링의 주체
11
데이터베이스 모델링 01 7. 데이터 모델링의 최적화(1/2) ◈ 최적화된 데이터 모델링의 특징
▷ 현재 업무에 대한 내용 포함 - 현재 구축하고자 하는 시스템이 관리해야 될 데이터를 체계적으로 관리해야 하며 해당 데이터에 의해 현재 업무가 모두 최적으로 적용돼야 합니다. ▷ AS-IS에 대한 최적화 - 현재 업무에 대해 또한 현재의 데이터 정합성 및 성능을 보장할 수 있는 데이터의 관리를 위한 데이터 모델링이 수행돼야 합니다. ▷ 일관성 있는 데이터 모델링 - 각 Entity, Attribute의 Naming Rule 및 도메인 설정, 용어 사전의 사용 등을 통해 하나의 데이터 모델링에서 동일한 Attribute의 데이터 형식 및 동일한 이름이 지정돼야 합니다. ▷ TO-BE 업무에 대한 전략/계획 도출 - 데이터 모델링은 현재 의 업무를 최적으로 수행되게 하는 것은 물론이고 추후에 발생 할 업무에 대한 전략 및 계획도 고려돼야 합니다. - 데이터 모델링 을 수행함에 있어 가장 어려운 부분이면 잘 수행되지 않는 것이 현실이다. 하지만, 데이터와 업무는 정지돼 있는 것이 아니라 계속 유기적으로 변하기 때문에 TOBE를 고려해야만 합니다.
12
데이터베이스 모델링 01 7. 데이터 모델링의 최적화(2/2) ◈ 최적화된 데이터 모델링의 특징
▷ Physical Modeling에 대한 고려 - 데이터 모델링은 시스템 구축 시 데이터베이스에 구축되므로 최적화된 Physical Modeling이 수행될 수 있도록 데이터 모델링 시부터 고려돼야 할 것이다. ▷ 안정적인 성능 - 데이터 모델링의 주요 목적은 데이터 정합성과 성능이다. 이와 같이 성능은 데이터 모델링에 의해 좌우되는 경 우도 많다. 물론, SQL 튜닝 (Tuning)을 통해 성능을 향상시킬 수 있지만 성능을 고려한 데이터 모델링을 통해 기본적인 성능 을 보장받을 수 있게 데이터 모델링이 구현돼야 한다. [그림6] 최적화된 데이터 모델링의 특징
13
데이터베이스 모델링 01 8. 데이터 모델링 설계과정(1/3) ◈ 프로젝트 진행 과정
계획 : ISP(정보전략계획)과 유사하며, 외적 환경과 요구사항, 그리고 최상위 수준의 시스템 구분과 모델링을 통해 향후 데이터 베이스 구축방향제시 분석 : 각종문서들을 수집하거나 분석하고 인터뷰, 관찰, 브래인 스토밍 등을 통해 데이터를 찾는 과정 - 사용자와 어플리케이션 범위 검증(대상범위,DB사용자 ) - 운영환경과 처리사항의 분석(트랜잭션 처리형태,발생빈도 등) - 질의서와 인터뷰(각 정보에 대한 가치평가와 정보등급평가) 개념적 데이터 모델링 : 데이터베이스 구현을 위한 사전단계로 업무관점의 개략적인 데이터 모델링에 해당됩니다 주제영역 파악, ERD(Entity Relationship Diagram) 논리적 데이터 모델링 : 개념적 설계에서 추출된 실체와 속성들의 관계를 구조적으로 설계하는 단계(스키마 설계) - Mapping Rule, 완벽한 정규화 물리적 데이터 모델링 : 논리적 데이터모델링에서 정의된 정규화된 모델을 개발 DBMS의 특성 및 효율적 DBMS가 되기 위한 데이터분산 등을 고려해 데이터 베이스 스키마를 구축하는 단계 - 개발 DMBS선정, 컬럼의 데이터타입과 사이즈선정. 데이터 사용량 분석과 사용자들의 업무 프로세스 분석, 역정규화, 인덱스설정 및 데이터 분산정의, 각종 데이터베이스 개체정의, 데이터베이스 선정 구현 테스트 유지보수 계획 분석 설계
14
데이터베이스 모델링 01 8. 데이터 모델링 설계과정(2/3) ◈ 데이터베이스 설계
▷ 요구사항 분석:현업의 요구사항에 대한 내용을 수집 분석해 개념 설 계에 필요한 정보를 정리한다. ▷ 개념 설계:Entity, Relationship 및 Attribute를 도출한다. ▷ Logical 설계:Normalization 및 Entity 통합을 수행한다. ▷ Physical 설계:데이터베이스로 구현하기 위해 Entity는 테이블로 Attribute 는 컬럼으로 구현한다. 요구 조건 분석 요구 조건 명세 개념적 설계 정보 구조 논리적 설계 논리적 데이터베이스 구조 물리적 설계 물리적 데이터베이스 구조 데이터베이스 구현 정보요구 조건 처리요구 조건 DBMS, 하드웨어 및 운영체제 특성 개념적 데이터 모델 논리적 데이터 모델 물리적 데이터 모델
15
데이터베이스 모델링 01 8. 데이터 모델링 설계과정(3/3) ◈ 모델링의 단계 1. 요구사항 분석 2. 개념 모텔
3. 논리 모텔 4. 물리 모텔 설계자 [그림7] 데이터 모델링의 4단계
16
데이터베이스 모델링 01 9. 데이터 모델링의 고려사항(1/2)
▷ 데이터 모델링 시 고려사항은 바로 데이터 모델링을 하는 목적에 해당될 것입니다.. 그렇기 때문에 항상 데이터의 정합성과 성능 을 고려해야 합니다. [그림8] 논리 모델과 물리 모델
17
데이터베이스 모델링 01 9. 데이터 모델링의 고려사항(2/2) ▷ 데이터 정합성
- PC에 동일한 파일을 여러 곳에 보관하게 되면 시간이 지나면서 각각의 파일들은 버전이 달라지게 되며 최신 파일을 찾기 어렵게 됩니다. 이와 같이 중복된 데이터가 존재한다면 시간이 지남에 따라 테이터 정합성이 위험해지며 정확한 최신의 테이터를 확인할 수 없게 됩니다. ▷ 성능 - 테이터 모델링 시 성능을 고려한 Entity, Attribute 및 Relationship 도출이 필요합니다. 예를 들어. 거래내역 Entity에 제조사 Attribute가 존재한다고 가정합니다. 해당 Attribute에는 제조사 이름이 입력되어 있는 경우 제조사가 변경된다면 거래내역 Entity에서 제조사 이름을 변경해야 하며 대용량 테이블일 경우 많은 데이터에 대한 Update 작업으로 큰 성능 저하가 발생할 수 있게 됩니다. 이와 같은 현상을 해결하기 위해서는 제조사 이름의 값을 별도의 Entity 로 분리해 제조사 번호와 제조사 이름 값으로 구성하도록 하며 거래내역 Entity의 제조사 Attribute에는 제조사 번호로 데이터를 관리 합니다. 별도의 Entity로 구성했을 경우 거래내역 데이터를 제조사 이름과 함께 보고자 할 경우에는 Join을 이용해야 합니다. 또한, Join 수행 시 성능 저하가 발생할 가능성이 있습니다. 결국 데이터 모델링 시 데이터 정합성과 성능을 어떻게 배분하는가에 따라 최적의 데이터 모델링이 될 수 있습니다.
18
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 개체-관계 모델(E-R Model)
▷ 데이터베이스 구현을 위한 사전단계로 업무관점의 개략적인 데이터 모델링에 해당됩니다. 개념 모델 단계에서는 달성해야 할 목적에 맞게 무엇(WHAT)을 해야 하는지에 초점을 두고 해야 함 (DBMS고려해서 설계하지 않아도 됨) 업무 분석 시 발견되는 업무처리 내용 중 명사 또는 개념적 명사 중심으로 용어를 정리하고 반드시 의미 설명하여 개념설계가 이루어야 함 ERD는 확인 및 Review의 효율성을 위해 현업에서 사용되는 용어를 선택하도록 노력해야 합니다. 개념모델 단계의 산출물은 논리모델의 입력물로 추적성이 용이한 문서가 되고 무결성 규칙이 유지되도록 산출물이 정리 되어야 합니다. 학생과 교육과정 관계를 표현한 E-R Diagram 식별자 학생 학번 학생이름 등록 교육과정 과정 내용 과정코드 과정 명 전화번호 개체 속성 관계
19
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Subject Area를 이용한 ERD 표기 방식
▷ Entity가 많은 시스템의 경우 하나로 ERD를 작성한다면 매우 복잡해질 수 있어서 업무별 또는 시간별로 구분하고 Subject Area를 분리해 ERD를 작성할 수 있습니다. ▷ 실제 프로젝트에 Entity의 개수가 많은 경우에는 Subject Area를 다수 활용하게 됩니다. 오른쪽 그림의 예에서 카드 업무에 대해 데이터 모델링을 수행하는 과정에서 해당 데이터 모델링의 Entity가 많을 경우 카드 승인 업무와 카드 정산 업무를 분리해 Subject Area를 이용함으로써 각각 데이터 모델링을 수행할 수 있습니다. [그림9] Subject Area 이용
20
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Subject Area를 이용한 ERD 표기 방식
▷ Subject Area를 구분하는 경우 서로 다른 Subject Area 사이에 많은 Relationship이 존재한다면 매우 불리할 수 있습니다. 따라서 서로 Relationship이 적은 경우를 Subject Area로 구성해야 합니다. ▷ 업무별 또는 시간별로 Subject Area를 분리하기 때문에 각각의 Subject Area는 적은 Entity를 가지게 됩니다. 따라서 ERD의 읽기 편의성이 높아집니다. ▷ 업무를 분리해 데이터 모델링을 수행하게 되므로 하나의 Subject Area에서 관리해야 하는 Entity의 개수 감소로 명시적인 데이터 모델링이 가능해집니다. ▷ 업무에서 가장 많이 사용하는 명사 또는 업무에서 가장 중심에 있는 Entity의 이름으로 Subject Area의 이름을 선정합니다.
21
UNIQUE IDENTIFIER에 의해 식별 가능
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity의 개념 ▷ 저장되고 관리되어야 할 정보(명사)로서 물리적은 DMBS의 테이블에 해당합니다. ▷ 아래 그림과 같이 일곱 가지 조건을 만족해야만 Entity 자격이 되며, 데이터 모델링에서 Entity로 구현될 수 있습니다. Entity로 선정된 후 Entity는 Physical Modeling에서 테이블로 변경됩니다. Entity 정의 - 회사의 중요한 Data라 할지라도 해당 시스템에서 반드시 필요한 정보만을 Entity로 표현 과금 시스템 통화내역 HR 시스템 통화내역 HR : 인사관리시스템 업무에 필요한 정보 영속적으로 존재 - 임시로 사용하는 Entity는 Entity로 표현하지 않음 객관적인 집합 Temp Entity UNIQUE IDENTIFIER에 의해 식별 가능 업무에서 반드시 사용 - 행렬의 정의에 의해 행과 열이 존재하는(2개이상의 행) 집합적인 개념을 가져야 함 - 어느 누구나 이해할 수 있는 객관적인 Entity의 정의 필요 1개 이상의 Attribute 존재 Entity Data Insert 1개 이상의 Relationship 존재
22
UNIQUE IDENTIFIER에 의해 식별 가능
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity의 개념 Entity 정의 - Unique Identifier에 의해 유일한 Data가 존재해야 함 만약 Unique Identifier에 대해 2개의 Data가 존재한다면 정규화 필요 업무에 필요한 정보 Unique Identifier (Card Number) Card Table Unique Identifier (Card Number) Card Table 영속적으로 존재 - 업무에서 반듯이 사용, 업무에서 사용되지 않는 Entity는 해당 Entity 삭제 또는 업무 분석 재시도 필요 객관적인 집합 Process Process Entity Entity UNIQUE IDENTIFIER에 의해 식별 가능 - Entity는 적어도 1개 이상의 Attribute(Column)가 존재해야 함 업무에서 반드시 사용 - 다른 Entity와 관계가 없는 Entity는 Entity가 아니며 다른Entity의 Attribute로 표현 - 어느 누구나 이해할 수 있는 객관적인 Entity의 정의 필요 1개 이상의 Attribute 존재 Card Table 거래내역 Table A Table Card Table 거래내역 Table 1개 이상의 Relationship 존재
23
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 정보 수집
▷ 데이터 모델링은 업무 프로세스를 고려하되 업무에 절대적으로 의존적 이어서는 안 됩니다. 업무는 언제든 변경될 수 있으므로 업무에 의존적이면 애플리케이션 변경이 어려워집니다. ▷ 데이터 모델링의 중심이 되는 Entity는 결국 업무에서 추출해야 합니다. 그렇기 때문에 기존 문서, 업무 프로세스, DFD, 업무 설명, Interview 및 경험/성능 등을 고려해 도출하게 됩니다. 개념 요구사항 명세서 및 추가 요구사항을 먼저 숙지하여 해당 자료로부터 Entity 후보 도출 업무기술서/장표 문서 업무Process를 분석하여 필요한 Entity 도출 업무Process를 통해 Entity를 도출하는 과정에서 업무 Process에 완전 의족적이지 않도록 주의 업무 기술서 이용 업무Process DFD Data Flow Diagram을 통해 필요한 Entity 도출 업무설명 업무담당자로부터 업무에 대한 설명을 통해 Entity 확인 및 추가 Entity 도출 Interview 현업과의 Interview를 통해 필요한 정보 수집 기존의 Entity 확인 및 추가적인 결정 사항을 확정 질문 목록 미리 작성 및 준비 경험/성능 논리적 모델링 경험 및 성능을 고려하여 논리적으로 필요한 Entity 도출
24
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 도출 Entiry 도출 방법
2. 중복된 명사 제거 – 단어의 중복 3. 객관적인 집합 – 도출된 명사 중 개념이 불분명한 명사 제외 4. Attribute에 해당하는 명사 제거(종속 여부 파악) 5. 업무 Process에 해당하는 명사 제외-업무 프로세스에 대한 명사는 보통의 경우 Relationship을 의미(거래 등) 6. 중복되는 명사 제거 – 단어의 중복이 아닌 의미의 중복을 확인 7. 누락된 Entity 도출 – 행위를 발생시키는 허위 Entity에 대해 고려/성능을 고려한 Entity 도출 8. Unique Identifier 존재 확인 - Unique Identifier가 존재해야만 Entity로 선정 가능
25
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 도출 예제 업무 기술서 인터넷경매를 하는 IAuctionCo 이라는 회사는 경매할 물품에 대한 내용을 온라인으로접수 받고 각 물품이 팔릴 수 있는 날짜를 정하여(이 날짜를 경매공고일이라고 함) 인터넷에 경매공고한다. 경매공고일에는 역시 온라인을 통해 입찰인이 입찰된 물품에 대해 매수신청을 하고 매수 신청한 입찰인중 최고가를 신청한 매수신청인에게 물품이낙찰된다. 물품 낙찰일로부터 1주일 이내에 낙찰대금을 은행계좌나 카드 또는 직접 IAuctionCo에 납부하지 않으면 낙찰은 자동으로 취소되고 차 순위 금액을 신청한 매수신청인에게 물품이 낙찰 된다. 낙찰인은 1주일 이내에 대금을 납부하면 경매가 성사되었다고 하고 매수신청인에게 낙찰대금을 입금하여 경매절차가 완료된다. 경매가 성사되는 경우 물품가격의 2%를 IAuctionCo에 수수료로 납부해야 한다. 각경매일에 경매가 진행된 결과는 자세하게 알 수 있어야 한다.
26
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 도출 예제 ▷ 시나리오에서 명사를 구분 합니다. 인터넷경매를 하는 IAuctionCo 이라는 회사는 경매할 물품에 대한 내용을 온라인으로접수 받고 각 물품이 팔릴 수 있는 날짜를 정하여(이 날짜를 경매공고일이라고 함) 인터넷에 경매공고한다. 경매공고일에는 역시 온라인을 통해 입찰인이 입찰된 물품에 대해 매수신청을 하고 매수 신청한 입찰인중 최고가를 신청한 매수신청인에게 물품이낙찰된다. 물품 낙찰일로부터 1주일 이내에 낙찰대금을 은행계좌나 카드 또는 직접 IAuctionCo에 납부하지 않으면 낙찰은 자동으로 취소되고 차 순위 금액을 신청한 매수신청인에게 물품이 낙찰 된다. 낙찰인은 1주일 이내에 대금을 납부하면 경매가 성사되었다고 하고 매수신청인에게 낙찰대금을 입금하여 경매절차가 완료된다. 경매가 성사되는 경우 물품가격의 2%를 IAuctionCo에 수수료로 납부해야 한다. 각경매일에 경매가 진행된 결과는 자세하게 알 수 있어야 한다.
27
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 도출 예제 ▷ 개념이 불분명한것, 광범위한 것은 제거합니다. ▷ 엔티티타입의 특성이거나 속성의 값은 제거합니다. 인터넷경매, IAuctionCo, 회사, 경매, 물품, 내용, 온라인, 입찰, 접수, 날짜, 경매공고일, 인터넷, 경매공고, 입찰인, 매수신청, 최고가, 신청, 매수신청인, 낙찰, 낙찰일, 1주일, 낙찰대금, 은행계좌, 카드,직접납부, 자동, 취소, 차순위금액, 낙찰인, 대금납부, 경매성사, 입금, 물품가격, 수수료, 경매일, 진행, 결과 물품, 온라인, 입찰, 접수, 날짜, 경매공고일, 경매공고, 입찰인, 매수신청, 최고가, 신청, 매수신청인, 낙찰, 낙찰일, 1주일, 낙찰대금, 은행계좌, 카드, 직접납부, 자동, 취소, 차순위금액, 낙찰인, 대금납부, 경매성사, 입금, 물품가격, 수수료, 경매일, 진행, 결과
28
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 도출 예제 ▷ 포괄적인 업무 프로세스에 해당되는 명사는 제거합니다. ▷ 중복되는 명사는 제거합니다. - 매수신청인 입찰인과 동일한 의미를 가지므로 업무에서 자주 사용하는 입찰인을 남기고 매수신청인은 제거한다. - 매수신청과 신청은 같은 의미를 가지고 있으므로 매수신청을 남기고 신청을 제거한다. ▷ 최종 엔티티타입 후보 물품, 온라인, 입찰, 접수, 경매공고, 입찰인, 매수신청, 신청, 매수신청인, 낙찰, 자동, 취소, 낙찰인, 대금납부, 경매성사, 입금, 진행, 결과 물품, 온라인, 입찰, 접수, 경매공고, 입찰인, 매수신청, 신청, 매수신청인, 낙찰, 낙찰인, 진행 물품, 온라인, 입찰, 접수, 경매공고, 입찰인, 매수신청, 낙찰, 낙찰인, 진행
29
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ Entity 이름
▷ Entity는 데이터 모델링을 수행한 사람만 보는 것이 아니다. 그러므로 Entity에는 표준화된 이름의 사용이 권장된다. 용어사전, Domain(Data Type 지정)을 이용해 누가 보더라도 이해할 수 있고 커뮤니케이션(Communication)이 가능하도록 Naming Rule을 정하도록 한다 Entity Naming Rule Entity 이름에 업무를 적용하여 누가 보아도 이해할 수 있도록 함 AAA DEAL_TRAN 업무를 표현 모든 것에 대한 약어 사용 자제 - 누구나 이해할 수 있는 부분은 약어 사용 가능 약어 사용 자제 DE_TR DEAL_TRAN 명사 사용 명사로만 Entity 표현 - 동사는 사용하지 않음 DO_DEAL DEAL_TRAN 유일한 이름 사용 중복된 Entity 이름 사용 금지 - Entity 이름은 유일한 이름만 사용 정확한 의미 부여 정확한 의미 부여 - 모호한 Entity 이름은 개발을 힘들게 함 통화 통화내역
30
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 속성(Attribute)
▷ Entity내에서 관리되는 정보들의 항목으로서 Entity를 설명하는데 사용되는 명사로 컬럼명을 의미합니다. ▷ Entity를 구성하는 요소가 되며, 하나의 Entity에는 고유 식별자를 포함한 하나 이상의 속성이 포함됩니다. 의미가 명확하고 길지 않으며 내용을 함축성 있게 표현. Entity명을 사용해서는 안됨. 단 하나의 Entity에만 속하도록 함. 가능한 한 최소단위까지 분할. 여러 값을 가지거나 반복되는 속성은 Entity로 분할. 추출 값, 즉 Count 값이거나 Total값, 최대, 최소, 평균 등의 계산 값 등은 포함시키는 것은 낭비. 속성이 자신의 속성을 가질 수 있으면 Entity로 분류. * 속성은 물리적인 단계에 앞서 각 속성의 값의 범위, 크기, 형식,NULL여부 등의 특성들을 기술해 주어야 합니다. Attribute 선정 주의사항 의미가 명확한 Attribute만을 선정 순번/상태/서버번호/연락처/학력 의미 명확 하나의 단어가 아닌 여러 단어의 조합으로 생성해야 의미 전달이 수월 용어사전 이용 복합명사 사용 동일한 용어를 사용 용어사전 이용 이름 표준화 일관성 있는 Data Type 동일 Attribute에 동일한 Data Type 설정 Domain 이용
31
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 속성(Attribute) 도출
Entity 도출 과정에서 Attribute 도출 프로세스 Modeling 중에 도출 Data Modeling과 프로세스 Modeling을 검증하는 단계에서 도출 시스템 구축 단계에서 도출 ▷ 업무자료에서는 속성에 대한 도출뿐만 아니라 엔티티 및 관계에 관련된 사항도 도출이 가능합니다. 그렇기 때문에 이와 같은 분류를 정확히 해서 속성을 도출해야 합니다. ▷ 엔티티 도출 과정에서 속성을 도출할 수 있다. 엔티티 도출 과정에서 속성에 해당하는 명사를 제거하는 단계에서 속성을 도출할 수 있습니다. ▷ 프로세스 모델링 시 엔티티에 필요한 속성의 일부가 표현되며 이를 통해 속성을 도출할 수 있습니다. ▷ 시스템의 서비스를 개시하는 그 순간까지 속성은 도출될 수 있으며 이와 같은 단계에서의 속성 도출은 기존 엔티티와 속성을 검토하고 데이터 정합성 및 애플리케이션을 고려해 속성을 추가 도출해야 합니다.
32
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 속성(Attribute) 도출
▷ 속성을 도출함에 있어 가장 중요한 것은 업무의 최소 단위로 속성을 분리하는 것이다. 이와 같이 속성은 업무의 최소 단위로 분리하는 것이 매우 중요하며 그렇게 해야만 애플리케이션을 좀더 수월하게 작성할 수 있고 성능을 보장받을 수 있게 된다 YYYY MM DD YYYYMM만으로 의미 있는 경우 공과금 조회 조건은 분리하지 않는 경우가 유리 YYYY||MM Between ‘ ’ AND ‘ ’ MM만으로 의미 있는 경우 요금단가 DD만으로 의미 있는 경우 카드결제일, 이체일 MMDD만으로 의미 있는 경우 생일, 성수기
33
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 속성(Attribute) 도출
YYYYMMDD / YYYY, MM, DD / YYYYMM, DD / YYYY, MMDD / YYYYDD, MM ▷ 어떤 형태로 속성을 구현할지는 해당 속성을 액세스하는 업무의 성격에 달려 있습니다. 경우에 따라 DD만으로 업무에서 의미가 있다면 DD는 별도의 속성으로 구성해야 하며, MM만으로 업무에서 의미가 있다면 MM은 별도의 속성으로 구성해야 할 것입니다. YYYY MM DD YYYYMMDD 속성 하나로 구성한 경우 BIRTH_DAY 속성을 DDMM으로만 구성하고 YYYY는 다른 속성으로 독립한 경우 SELECT 고객이름, 이메일 FROM 고객_정보 WHERE SUBSTR(BIRTH_DAY,5,4) = SUBSTR(TO_CHAR(SYSDATE,'YYYYMMDD'),5,4); Where 조건의 컬럼이 함수에 의해 가공되어 인덱스 사용 불가, 따라서 FULL SCAN으로 성능 저하 SELECT 고객이름, 이메일 FROM 고객_정보 WHERE BIRTH_DAY = SUBSTR(TO_CHAR(SYSDATE,'YYYYMMDD'),5,4); Where 조건의 컬럼이 함수에 의해 가공되어 있지 않기 때문에 BIRTH_DAY속성에 인덱스가 존재하면 해당 인덱스 이용 가능
34
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 속성(Attribute) 도출
▷ 거래내역 엔티티에 데이터가 저장되는 순간 고객 엔티티에는 Update가 발생하게 되므로 거래내역 엔티티에 대한 Insert 작업은 부하를 발생시키게 될 것입니다. 또한 거래건수 엔티티는 자주 변하는 값이기 때문에 데이터 정합성에도 문제를 발생시킬 수 있습니다. 그리고 애플리케이션은 복잡해질 것입니다. COUNT/SUM/MAX/MIN/AVG 등에 의한 값(계산값) 추출 값은 데이터 정합성을 저해 추출 값에 대한 정의 필요 낭비 발생 고객 거래내역 단점 데이터 정합성 저해 INSERT 성능저하 애플리케이션 복잡 장점 계약건수에 대한 조회 성능 향상 고객번호 거래건수 고객번호 거래일자 금액 추출 값을 속성으로 도출하지 않는 경우 SELECT COUNT(고객번호) 거래건수 FROM 거래내역 WHERE 고객번호 = '111'
35
여러 개의 Data에서 각각의 Data를 구분할 수 있는 논리적인 이름을 Identifier라고 함
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) ▷ 식별자는 엔티티의 성격을 좌우하는 속성입니다. 하나의 속성으로 해당 엔티티의 식별자를 선정할 수 있습니다. 여러 개의 속성으로 해당 엔티티의 식별자를 선정하는 것도 가능합니다. 엔티티의 식별자는 물리 모델링을 할 때 인덱스로 구현되며 그 중 유니크 식별자(Unique Identifier)는 프라이머리 키(Primary Key)로 구현됩니다. 이처럼 식별자는 해당 엔티티의 키 값이 되며, 해당 테이블의 속성을 좌우합니다. 여러 개의 Data에서 각각의 Data를 구분할 수 있는 논리적인 이름을 Identifier라고 함 Identifier Identifier에 의해 Entity의 모든 Data는 각각 구분 가능해야 함 Identifier는 변하지 않아야 함 각각의 Identifier에 의해 Data가 존재해야 함 Identifier를 이용하여 원하는 Data를 Access 모든 Entity는 1개 이상의 Identifier를 가짐
36
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) Unique
주 식별자 Primary Identifier 해당 엔티티의 성격을 좌우하는 식별자 회원 정보를 저장하는 회원 정보 엔티티의 주민번호 속성이 바로 유니크 식별자 보조 식별자 Alternate Identifier 유니크 식별자는 아니지만 유일한 값을 가지는 식별자 회원 정보 엔티티에서 주민번호 속성을 보조 식별자로 지정하고 가공해 생성한 회원번호 속성을 유니크 식별자로 지정 내부 식별자 Internal Identifier 다른 엔티티로부터 식별자를 상속받는 것이 아니라 자신의 엔티티에서 식별자를 생성해 사용하는 식별자 사원 정보를 저장하는 사원 엔티티의 사원번호 속성은 누구한테 상속받은 번호가 아닌 자체 엔티티에서 만들어낸 것이므로 내부 식별자에 해당 외부 식별자 Foreign Identifer 다른 엔티티로부터 식별자를 상속받은 경우 교육센터의 수강 엔티티는 강의 엔티티의 강의번호 속성과 학생 엔티티의 학생번호 속성을 각각 상속받아 유니크 식별자로 사용된다. 인조 식별자 Artificial Identifier 복합키가 여러 개의 컬럼으로 구성된 경우 이를 대체하기 위해 인위적으로 정의한 컬럼 Unique Identifier Entity를 대표하는 유일한 Identifier Primary Key Index로 생성 보조 Identifier Unique Identifier를 대신하여 Data를 식별하는 Identifier Unique Index를 생성 Unique Identifier를 구성하는 Attribute가 많을 경우 Artificial Identifier를 생성하고 실제 Identifier는 보조 Identifier로 정의
37
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준
▷ 하나의 엔티티에 유니크한 값을 가지는 속성이 여러 개 있을 경우 자주 사용하는 속성을 유니크 속성으로 선정 직원 엔티티에는 유니크한 값을 저장하는 속성이 주민번호와 사원번호가 있다고 가정 했을때 업무에 자주 사용하는 속성을 유니크 식별자로 선정해야 합니다. 직원 엔티티는 사원번호 속성이므로 조회 등의 업무를 자주 수행한다면 사원번호 속성을 유니크 식별자로, 업무에 적게 사용되는 주민등록 속성은 보조 식별자로 선정 자주 이용하는 Attribute를 Unique Identifier로 선정 Unique Identifier는 Primary Key Index를 자동 생성하게 되므로 자주 사용하는 Attribute를 Unique Identifier로 선언하여 자동으로 인덱스를 생성하여 성능을 보장하게 함 직원 직원 사원번호 주민번호 주소 전화번호 ……. 주민번호 사원번호 주소 전화번호 ……. 주민번호 등의 개인정보는 보안에 주의해야 하므로 유니크 식별자로 선정하지 않아도 된다. 주민번호 속성을 유니크 식별자로 선정하는 순간 자식 엔티티들은 주민번호 속성을 상속받을 가능성이 많아짐,이로 인해 보안에 중요한 속성이 여러 엔티티에 있게 되고, 이것이 보안 취약점이 될 수 있다. 직원 주민번호 사원번호 주소 전화번호 …….
38
Unique Identifier를 선정하는 기준
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준 ▷ 일반적으로 유니크 식별자로는 이름처럼 한글이 저장되는 속성이 아닌 CODE 값이나 Artificial 값이 저장되는 속성을 선정합니다. Unique Identifier를 선정하는 기준 CODE 값이나 Artificial 값을 보통 Unique Identifier로 선정 부서 이름보다는 부서번호를 Unique Identifier로 선정(사용이 편함) 명칭 또는 내역등은 Unique Identifier로 선정하지 않음 부서 부서 부서번호 부서이름 주소 팀장 ……. 부서번호 부서이름 주소 팀장 ……. 부서 엔티티를 살펴보자. 부서번호 속성과 부서 이름 속성 모두에 유크한 데이터가 저장된다고 가정하자. 이 경우 한글로 저장되는 부서 이름 속성이 아니라 CODE 값으로 데이터가 저장되는 부서번호 속성을 유니크 식별자로 선정하고, 부서 이름 속성을 보조 식별자로 선정한다. 부서 부서이름 부서번호 주소 팀장 …….
39
수많은 속성을 유니크 식별자로 선정할 경우 발생할 수 있는 문제점
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준 ▷ 여러 개의 속성으로 해당 엔티티의 유니크 식별자를 생성하는 것보다 임의의 유니크 생성자 하나를 생성하는 것이 바람직합니다. 이를 인조 유니크 식별자(Artificial Unique Identifier)라고 합니다. 이처럼 인조 유니크 식별자를 생성한 경우 기존 유니크 식별자는 보조 식별자로 정의합니다. 수많은 속성을 유니크 식별자로 선정할 경우 발생할 수 있는 문제점 Unique Identifier를 구성하는 Attribute가 많은 경우는 Artificial Identifier를 생성하여 Unique Identifier를 대신함 Unique Identifier를 구성하는 Attribute가 많은 경우에는 SQL 작성이 어려움 유니크 식별자를 이용해 한 건의 데이터를 추출할 경우 유니크 식별자가 여러 속성으로 구성돼 있으므로 Where 조건이 증가하고, SQL이 길어져 관리가 어려워질 수 있다. 자식 엔티티가 부모 엔티티의 유니크 식별자를 상속받은 상황에서 자신의 속성을 추가하면 계속해서 유니크 식별자가 증가한다. 유니크 식별자는 물리 모델링 시 기본 키(Primary Key)로 구현되므로 인덱스 속성이 증가하게 되며, 인덱스의 크기도 불필요하게 커질 수 있다. 접수등록 접수등록 접수일자 관할부서 담당자사번 구분코드 ……. 접수번호 접수일자 관할부서 담당자사번 구분코드 …….
40
유니크한 데이터를 저장하는 속성이 여러 개인 경우
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준 ▷ 하나의 엔티티에 유니크한 데이터를 저장하는 속성이 여러 개인 경우 변하는 값은 유니크 식별자로 선정하지 않습니다. 유니크한 데이터를 저장하는 속성이 여러 개인 경우 변하지 않는 값으로 선정 학생 엔티티에는 유니크한 데이터를 저장하는 속성으로 전화번호 속성과 학번 속성이 있다. 두 속성 모두 유니크한 데이터가 저장된다. 그러나 전화번호 속성은 언제든 값이 바뀔 수 있다. 그렇기 때문에 변치 않는 학번 속성을 유니크 식별자로 선정하고, 값이 변할 수 있는 전화번호 속성은 보조 식별자로 지정한다. 학생 학생 전화번호 학번 이름 ……. 학번 이름 전화번호 …….
41
속성에 NULL 값을 허용하면 다음과 같은 문제가 발생
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준 ▷ 유니크 식별자는 NULL 값을 허용해서는 안 됨에 주의합니다. 해당 엔티티에서 유일한 값을 찾을 수 있는 KEY 값에 NULL이 저장되는 것은 문제 발생의 소지가 커집니다. 속성에 NULL 값을 허용하면 다음과 같은 문제가 발생 Null 값 허용 안됨 NULL을 허용하는 속성이 NULL 값을 조회할 경우 IS NLL 또는 IS NOT NULL 연산자를 사용해야 하는데, 인덱스에서는 이를 이용할 수 없다. NULL로 인해 NVL 함수를 많이 사용하게 되는데, 이로 인해 CPU 사용률이 높아진다. 유니크 식별자뿐 아니라 일반 속성에도 적용되는 주의점인데, 유니크 식별자는 각각의 속성이 NOT NULL을 만족해야만 물리 모델링 시 기본 키(Primary Key)로 생성 가능하다. 학생 학생 메일ID 학번 이름 ……. 학번 이름 메일ID …….
42
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 식별자(Identifier) 선정 기준
▷ 상속 식별자 : 단어 그대로 외부 엔티티로부터 식별자 전체를 상속받거나 일부를 상속받는 특별한 식별자입니다. 상속 식별자 구분 ① 상속 식별자만이 유니크 식별자가 되는 경우 다른 엔티티로부터 상속받은 속성만이 해당 엔티티의 유니크 식별자가 되는 경우다. 사원 엔티티의 사원번호 속성이 계약직 엔티티로 상속된 경우를 가정했을때, 계약직 엔티티에서의 유니크 식별자로는 상속 식별자만이 가능하다. 이러한 경우는 1:1 관계에서 자주 발생한다 ② 상속 식별자와 다른 속성에 의해 유니크 식별자가 되는 경우 다른 엔티티로부터 상속받은 속성들로만 유니크 식별자를 선정하기 어려운 경우가 있다. 이 때에는 해당 엔티티의 다른 속성을 합해 유니크 식별자를 선정해야 한다. 사원이동 엔티티는 사원 엔티티로부터 상속받은 사원번호 속성과 해당 엔티티가 가지고 있는 이동일자 속성을 합해 두 속성 모두를 유니크 식별자로 선정한다. 이와 같은 현상은 1:M 과계에서 자주 발생한다. ③ 상속 식별자로 유니크 식별자를 선정하지 않는 경우 부모 엔티티로부터 상속받은 모든 속성이 자식 엔티티의 유니크 식별자로 선정되는 것은 아니다. 경우에 따라 부모로부터 상속받은 속성을 유니크 식별자로 선정하지 않고 일반 속성으로 선정하기도 한다. 이런 경우 부모로부터 상속받은 속성은 외부키(Foreign Key)로 설정된다. 이는 물리 모델에서 외부키로 설정돼야 한다. 하지만 실제 물리 모델링에서는 외부키를 설정하지 않는 경우가 대부분이다. 결국 논리 모델에서만 이렇게 표현하는 경우가 많다.
43
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 관계(Relational)
▷ 관계는 엔티티 속성을 연결해주는 역할을 합니다. 관계에 의해서 엔티티와 속성이 의미를 가지게 되므로 관계는 데이터 모델링에서 가장 중요한 요소중 하나입니다. Cardinality Cardinality는 분포도를 의미한다. 카드 엔티티의 Unique Identifier인 1개의 카드번호 데이터에 대한 여러 개의 데이터가 거래내역 엔티티에 있다고 가정했을때 카드 엔티티의 데이터에 대한 거래내역 엔티티의 데이터는 여러 건인데, 1:M의 관계를 가지며 그 표현은 그림처럼 여러 개의 선으로 표현할 수 있다. 거래내역 엔티티에서 Unique Identifier인 1개의 데이터에 대한 카드 엔티티의 데이터가 1개인 경우 하나의 선으로 표현될 것이다. Cardinality를 통해서는 어느 엔티티가 부모 엔티티인지를 확인할 수 있다
44
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 관계(Relational) Selectivity
그림에서 카드 엔티티의 Unique Identifier인 1개의 카드번호 값에 대한 거래내역 엔티티에는 해당 카드번호 값을 가진 데이터가 있을 수도 없을 수도 있다. 이는 거래내역 엔티티에 동그라미로 관계가 표현돼 있기 때문이다. 거래내역 엔티티의 Unique Identifier인 1개의 데이터에 대한 해당 카드번호 값은 항상 카드 엔티티에 있어야 한다. 이는 관계에서 카드 엔티티에 동그라미 표시가 없기 때문이다. 방향 관계의 방향에는 두 가지 종류가 있다. 그림처럼 카드 엔티티에서 거래내역 엔티티의 관계를 바라보는 방향과 거래내역 엔티티에서 카드 엔티티를 보는 2개의 관계가 그것이다. 즉 어떤 방향으로 둘의 관계를 해석하는가에 따라 그 의미가 달라진다. 예컨대 카드 엔티티에서 거래내역 엔티티를 보는 방향의 경우 1개의 카드번호 값은 여러 개의 거래내역 엔티티에 데이터를 생성하는 관계다. 이와 반대로 거래내역 엔티티 관점에서 카드 엔티티를 보면 하나의 거래내역 엔티티의 데이터는 1개의 카드번호에 의해 발생하는 관계라고 할 수 있다.
45
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 관계(Relational)의 특징 관계도 집합이다
관계는 두 엔티티 사이의 교집합을 의미한다. 관계는 두 엔티티의 Unique Identifier에 대한 교집함을 의미하므로, 즉 집합이라고 할 수 있다. 관계는 엔티티 정의에 따라 다양해진다 보통 사원 엔티티와 부서 엔티티는 M:1의 관계에 놓인다. 이는 사원 한명이 1개의 부서에 소속되고, 1개의 부서에는 여러 명의 사원이 포함되기 때문이다. 사원 엔티티의 Unique Identifier에 사원번호 속성뿐 아니라 이동일자 속성까지 포함돼 있다면 사원 엔티티는 해당 사원들의 이력까지 관리하는 것이다. 이력을 관리하면 사원 한 명이 두 번 부서를 이동해도 부서의 엔티티와의 관계는 여러 건의 데이터가 될 것이다. 그러므로 사원 엔티티와 부서 엔티티는 M:M 관계가 된다. 이처럼 엔티티는 어떻게 정의하느가에 따라 관계가 변하게 된다. 관계는 정의하기에 따라 다양해진다 엔티티 정의에 의해 관계가 바뀌듯 어떤 속성으로 두 엔티티를 보는가에 따라 관계가 변함에 유의하자. 그림에서 보험 계약 엔티티와 고객 엔티티를 살펴보자. 계약의 속성으로 두 엔티티를 보는 것과 피보험자 속성으로 보는 것은 분명 다르다. 계약의 속성으로 보는 것과 피보험자의 관계로 보는 것 또한 관계의 Selectivity가 달라질 것이다.
46
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 관계(Relational)의 Selectivity 카드 거래내역
Mandatory Must를 의미(필수) 하나의 거래내역 데이터는 반드시 하나의 카드 데이터를 가진다. Optional Maybe를 의미(선택) 하나의 카드는 여러 개의 거래내역을 생성할 수도 있으며 아닐 수도 있다 Mandatory 관계에 있는 Entity가 서브쿼리로 수행 SELECT …. FROM 카드 WHERE 카드번호 IN (SELECT … FROM 거래내역) SELECT …. FROM 거래내역 WHERE 카드번호 IN (SELECT … FROM 카드)
47
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 차수성의 정의 1) 일대일 1:1 2) 일대다 1:M
고객 주문 상품 관계를 맺고 있는 두 실체의 레코드가 서로 하나씩 대응되는 관계 2) 일대다 1:M 부서 소속 사원 관계를 맺고 있는 두 에서 부모실체의 하나의 레코드가 자식 실체의 여러 레코드에 대응되는 관계(가장일반적) 3) 다대다 M:M 사원 관리한다 부서 관계를 맺고 있는 두 실체에서 부모실체의 하나의 레코드가 자식 실체의 여러 레코드에 대응되며 반대로 자식레코드가 부모 실체의 여러 레코드에 관계를 맺음.
48
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 1:1 관계 Relationship 정의
신청한다 민원요청 민원인 작성한다 Relationship 정의 하나의 민원 요청은 한명의 민원인이 신청한다. 한명의 민원인은 하나의 민원 요청을 작성한다. 1:1 Relationship의 개념 한 건의 민원 요청 데이터에 대해 반드시 한 건의 민원인 데이터 존재 한 건의 민원인 데이터에 대해 반드시 한 건의 민원 요청 데이터 존재 1:1 Relationship의 속성 수직 분할 하나의 Entity로 구성해도 무방 해당 시스템에 1:1 관계가 많다면 1:1 관계에 대해 재점검 필요 빈번한 조인이 발생한다면 성능 저하 예상 Data 정합성의 위험
49
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ 1:M 관계 자식은 부모 없이 생성 안됨
부모는 자식을 가지지 않을 수 있음 가장 일반적(타당한 형태) 카드 거래내역 가장 이상적인 관계다. 자식 엔티티인 거래내역 엔티티의 데이터는 부모 엔티티인 카드 엔티티의 데이터에 의해서만 생성되는 형태를 띄고 있다. 자식은 부모가 없을 수 있음 부모는 자식을 가지지 않을 수 있음 가장 일반적(타당한 형태) 취미 회원 부모 데이터 없이 자식 데이터가 생성될 수 있는 형태다. 이러한 형태는 참조 테이블에서 발생하는 관계인데, 흔치 않은 관계라고 볼 수 있다. 부모가 반드시 하나이상의 자식이 있어야 하는 경우 자식에 의해 부모가 발생하는 상태 ? ? 자식 엔티티의 데이터에 의해 부모 데이터가 생성되는 형태로 이 또한 흔하지 않다.
50
데이터베이스 모델링 01 10. 개념적 데이터베이스 모델링 ◈ M:M 관계 하나의 고객 데이터는 여러 개의 상품을 구매한다.
판매된다 하나의 고객 데이터는 여러 개의 상품을 구매한다. 하나의 상품 데이터는 여러 명의 고객에게 판매된다. M:M Relationship의 개념 한 건의 고객 데이터에 대해 여러 건의 상품 데이터 존재 한 건의 상품 데이터에 대해 여러 건의 고객 데이터 존재 M:M Relationship의 속성 조인 발생시 Group By 사용(M:M 조인에 의해 증가된 데이터를 감소 시키기 위해) 조인 횟수의 증가로 성능 저하 예상 고객 Entity와 상품 Entity의 자식 Entity의 Join시 성능 저하 예상 교차(Intersect) Entity 도출 필요
51
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 관계형 모델의 개념 ▷ 부모테이블과 자식테이블 :
- 관계를 맺고 있는 두 테이블 중 반드시 부모테이블이고 반드시 하나는 자식테이블입니다. ▷ 기본키(Primary Key)와 포린키(Foreign Key) : - 부모테이블의 기본키가 자식테이블의 포린키로 전이 되어집니다. - 부모 혹은 자식테이블의 식별은 [주체관계파악] [부모테이블 테이터의 선정여부]로 합니다. ▷ 식별관계와 비 식별관계 : - 식별관계 : 부모테이블의 기본키가 자식테이블의 기본키(그룹)와 연결(전이) - 비식별관계 : 부모테이블의 기본키가 자식테이블의 일반속성과 연결(전이) * 식별관계 –교차실체 추가처리 – 데이터를 껀껀히 처리 * 비식별관계 – 몇단계거처 처리 – 데이터를 묶어서 처리 상 품 상품코드 상품명(AK) 규격 측정단위 회 원 회원코드 이름 주민번호(AK) 전화번호 주문 상세 주문코드(FK) 상품코드(FK) 수량 단가 금액 주문 주문코드 회원코드(FK) 주문일자 주문총금액 식별관계 비식별관계
52
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ Mapping Rule
▷ E-R Diagram을 관계형 데이터베이스 이론에 의해 데이터 베이스 스키마로 변환 메핑 룰의 4단계 1. 단순 엔티티 테이블로 2. 속성 칼럼으로 3. 식별자 기본키로 4. 관계 포린키로 E-R Diagram 관계 스키마 개체 테이블 명 : 학생 속성 1.엔티티 → 테이블 식별자 학생 학번 학생이름 전화번호 2.속성- 칼럼 컬럼명 학번 학생이름 전화번호 식별자 PK 3.식별자- 기본키
53
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 정규화 ▷ 데이터의 중복방지, 효율적으로 저장, 무결성 유지.
▷ 1차 정규화 : 반복되는 그룹 속성이 존재할 경우 그 그룹을 분리하여 새로운 실체를 추가한 후 기존 실체와 1:n의 관계를 형성함으로써 속성들의 원래 제자리를 찾아주는 것. 컬럼명 B_id Title c_name price name 키코드 PK Data A-1 데이터베이스 서울 4000 저팔개 b-1 운영체제 부산 3500 허청 C-1 워드 인천 5000 이한나 A-2 경기 손오공 * Book 테이블 컬럼명 B_id Title c_name name 키코드 PK Data A-1 데이터베이스 서울 저팔개 b-1 운영체제 부산 허청 C-1 워드 인천 이한나 A-2 경기 손오공 Id B_id Price PK FK 101 A-1 4000 102 b-1 3500 103 C-1 5000 104 A-2 * Book 테이블 * danga 테이블
54
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 정규화 ▷ 2차 정규화
복합식별자로 구성된 경우 해당 엔티티 안의 속성들은 복합식별자 전체에 의존적이어야 한다 만일 복합식별자 일부에 의존적인 속성이 존재한다면 이를 제거해야 한다.(부분종속속성 제거) 2차 정규화가 끝나면 각각의 속성들은 자신이 속한 테이블의 주식별자에 의해 완전함수종속(Full Functional Dependency) 관계를 이루게 됨 구분 이상현상 입력이상 강좌개설이 되지 않은 새로운 강좌 등록 시 수강자 학번을 임의로 넣지 않으면 입력 할 수 없음 수정이상 한 학생이 여러 강좌를 수강 할 경우 강좌에 대한 정보가 중복 생성됨, 수강 정보 생성 시 한 개라도 누락하면 데이터 일관성이 유지 안됨 삭제이상 강좌 정보 삭제 시 수강자에 대한 평가코드 및 평가 점수도 함께 삭제 됨
55
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 정규화
▷ 3차 정규화 : 한 테이블 안의 키가 아닌 모든 컬럼들은 기본키에 의존합니다. 만일 키가 아닌 컬럼에 종속되는 속성이 있다면 이를 제거 해야 합니다. 학과등록 엔티티 타입에 평가에 대한 정보가 포함되어 있는 모습. 평가코드가 결정자 역할을 하고 있고 평가내역이 의존자 역할을 하는 속성 간의 종속적인 속성이 발견되었으므로 3차 정규화의 대상이 되는 모델. 따라서 평가항목에 대한 내용에 대해 별도의 엔티티 타입을 도출한 아래쪽 모델로 만듦으로써 3차 정규화를 완성 단, 조인 속도 등을 고려하여 반정규화 하기도 함
56
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 정규화 ▷ 4차 정규화 : 다가 종속을 제거합니다.
다가 종속(MVD: Multivalued Dependency) : 한 릴레이션에 다가 속성이 두 개 이상 존재할 때, 하나의 다가 속성 값이 다른 다가 속성의 모든 값마다 중복되는 것입니다.
57
데이터베이스 모델링 01 11. 논리적 데이터베이스 모델링 ◈ 정규화
‘한 명의 사원은 여러 개의 프로젝트를 지원할 수 있다’ 그리고 ‘한 명의 사원은 여러 개의 기술을 보유할 수 있다’ 즉 사원과 프로젝트, 사원과 기술 간의 업무적인 관계의 규칙이 있는 경우이다. 이 업무 규칙은 보유하는 기술이 있다는 사실을 관리하고 보유한 기술은 지원한 프로젝트와는 아무런 상관이 없다는 것이 특징이다. 따라서 필요하지 않은 조인 관계를 해소하기 위해 오른쪽 모델과 같이 업무 규칙에 적합하게 관계를 분리하는 방법이 4차 정규화이다.
58
데이터베이스 모델링 01 12. 물리적 데이터베이스 모델링 물리적 데이터베이스 모델링 단계 개발 DBMS 선정.
◈ 물리적 데이터 베이스 모델링 논리적인 데이터베이스 구조로부터 효율적이고 구현 가능한 물리적 구조로 설계하는 것입니다. 물리적 데이터베이스 모델링 단계 개발 DBMS 선정. 컬럼의 데이터 타입과 사이즈 정의 데이터 사용량 분석과 사용자들의 업무 프로세스 분석 역 정규화 각종 제약조건 정의 인덱스, View, Stored Procedure, Trigger등 각종 Object 정의 데이터베이스 생성
59
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 문제
▷ 아래 고객에게 받은 엑셀파일을 기준으로 테이블을 생성 하고자 합니다. 정규화된 논리 모델을 구성 하시오. ※ 비 정규형 제품 주문품목 제품코드 제품명 제고수량 주문번호 수출내수구분 고객코드 사업자등록번호 고객우선순위 주문수량 110 TV 12,505 94002 X A031 5,000 94073 N C010 3 20 165 VTR 16,606 94028 C238 2 55 94101 7,700 94007 Y211 1 500 850 Aircon 795 94036 350 반복그룹
60
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 해설 - 01 ※ 1차 정규형 제품 주문품목 제품코드 제품명
제고수량 110 TV 12,505 165 VTR 16,606 850 Aircon 795 주문품목 제품코드 주문번호 수출내수구분 고객코드 사업자등록번호 고객우선순위 주문수량 110 94002 X A031 5,000 94073 N C010 3 20 165 94028 C238 2 55 94101 7,700 94007 Y211 1 500 850 94036 350
61
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 해설 - 02 ※ 2차 정규형 주문품목 제품 제품코드 주문번호
주문수량 110 94002 5,000 94073 20 165 94028 55 94101 7,700 94007 500 850 94036 350 제품코드 제품명 제고수량 110 TV 12,505 165 VTR 16,606 850 Aircon 795 주문번호 수출내수구분 고객코드 사업자등록번호 고객우선순위 94002 X A031 94073 N C010 3 94028 C238 2 94101 94007 Y211 1 94036
62
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 해설 - 03 ※ 3차 정규형 주문품목 제품 주문 고객 제품코드
주문번호 주문수량 110 94002 5,000 94073 20 165 94028 55 94101 7,700 94007 500 850 94036 350 제품코드 제품명 제고수량 110 TV 12,505 165 VTR 16,606 850 Aircon 795 주문 고객 주문번호 고객코드 94002 A031 94073 C010 94028 C238 94101 94007 Y211 94036 고객코드 수출내수구분 사업자등록번호 고객우선순위 A031 X C010 N 3 C238 2 Y211 1
63
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 해설 - 04 ※ 4차 정규형 제품 주문품목 주문 고객 국내고객
제품코드 제품명 제고수량 110 TV 12,505 165 VTR 16,606 850 Aircon 795 제품코드 주문번호 주문수량 110 94002 5,000 94073 20 165 94028 55 94101 7,700 94007 500 850 94036 350 주문 고객 주문번호 고객코드 94002 A031 94073 C010 94028 C238 94101 94007 Y211 94036 국내고객 고객코드 수출내수구분 고객우선순위 A031 X C010 N 3 C238 2 Y211 1 고객코드 사업자등록번호 C010 C238
64
데이터베이스 모델링 01 13. 모델링 실습 ◈ 정규화 실습 해설 - 05 ※ 데이터 모델 수정(Entity 통합) 제품 주문
제품코드 제품명 제고수량 110 TV 12,505 165 VTR 16,606 850 Aircon 795 제품코드 주문번호 고객코드 주문수량 110 94002 A031 5,000 94073 C010 20 165 94028 C238 55 94101 7,700 94007 Y211 500 850 94036 350 고객 국내고객 고객코드 수출내수구분 고객우선순위 A031 X C010 N 3 C238 2 Y211 1 고객코드 사업자등록번호 C010 C238
65
데이터베이스 모델링 01 14. 모델링 실습 – 거래명세표 논리 ERD 문) 아래 거래명세표를 보고 논리 ERD를 그리시오.
거 래 명 세 표 일련번호 199 년 월 일 귀하 아래와 같이 계산합니다. 합 계 금 액 (공급가액+세액) 품 목 규 격 수 량 단 가 공 급 가 액 세 액 비 고 공 급 자 등록번호 상 호 사업장 소재지 업 태 전화번호 성 명 종 목
66
데이터베이스 모델링 01 14. 모델링 실습 – 거래명세표 논리 ERD ※ 속성 추출 거 래 명 세 표
거 래 명 세 표 일련번호 199 년 월 일 귀하 아래와 같이 계산합니다. 합 계 금 액 (공급가액+세액) 품 목 규 격 수 량 단 가 공 급 가 액 세 액 비 고 공 급 자 등록번호 상 호 사업장 소재지 업 태 전화번호 성 명 종 목 데이터의 특성별 분류(속성유형기준) ● 기초속성 : 실제적(자연적)으로 존재하는 데이터 => 거래명세, 년월일, 공급받는자, 공급자, 상호, 성명, 사업장소재지, 업태, 품목, 규격, 수량, 단가, 비고 ● 설계속성 : 원래 존재하지 않지만 필요에 따라 설계자가 만든 데이터 => 일련번호, 등록번호, 전화번호 ● 추출속성 : 다른 자료로부터 계산 등의 가공처리를 통해 만들어진 데이터 => 공급가액, 세액, 합계금액
67
데이터베이스 모델링 01 14. 모델링 실습 – 거래명세표 논리 ERD ※ 실체 발견 거 래 명 세 표
거 래 명 세 표 일련번호 199 년 월 일 귀하 아래와 같이 계산합니다. 합 계 금 액 (공급가액+세액) 품 목 규 격 수 량 단 가 공 급 가 액 세 액 비 고 공 급 자 등록번호 상 호 사업장 소재지 업 태 전화번호 성 명 종 목 데이터의 특성별 분류(실체자격기준) ● 실체의 자격 – 대표 값을 가질 것 (Uniqueness), 대표 값외의 속성을 가질 것. 사용자가 DB에 저장 관리하려고 할 것. 다른 실체와 관계가 있을 것. ● 실체 - 거래명세, 공급자, 사업장, 품목, 거래명세내역 ● 실체별 속성 - 거래명세) 거래명세, 일련번호, 년월일, 공급받는자 - 공급자) 등록번호, 상호, 성명, 업태,종목 사업장소재지, 전화번호 - 사업장) 사업장번호, 사업장명, 소재지 - 품목) 품목번호, 품목명 - 거래명세내역) 품목번호, 규격, 수량, 단가,비고
68
데이터베이스 모델링 01 14. 모델링 실습 – 거래명세표 논리 ERD ※ 개념모델 도출
공급자 등록번호 상 호 성 명 소 재 지 업 태 종 목 전화번호 사업장 품 목 사업장번호 사업장명 소재지 품목번호 품 목 명 거래명세 거래명세내역 거래명세일련번호 년월일 공급받는자 규격 수량 단가 비고 표 시 엔티티(파일, 테이블) 명 식별자(키) 영역 비식별자 영역 거 래 명 세 표 일련번호 199 년 월 일 귀하 아래와 같이 계산합니다. 합 계 금 액 (공급가액+세액) 품 목 규 격 수 량 단 가 공 급 가 액 세 액 비 고 공 급 자 등록번호 상 호 사업장 소재지 업 태 전화번호 성 명 종 목
69
데이터베이스 모델링 01 14. 모델링 실습 – 거래명세표 논리 ERD ※ 업무규칙과 데이터무결성 ● 입력규칙(자식실체기준)
공급자 사업장 품 목 부모실체 관계 자식실체 참조무결성규칙 입력 삭제 공급자 거래명세 Dependent Restrict 거래명세내역 Cascade ● 입력규칙(자식실체기준) Dependent: 대응되는 부모실체가 있는 경우에만, 자식실체의 입력/수정을 허용 ● 삭제규칙(부모실체기준) Restrict: 대응되는 자식실체가 없는 경우에만, 부모실체의 삭제를 허용 Cascade: 부모실체의 삭제를 항상 허용하고 동시에 대응되는 자식실체의 모든 건을 자동 삭제 PK등록번호 PK사업장번호 PK품목번호 상 호 성 명 소 재 지 업 태 종 목 전화번호 사업장명 소 재 지 품 목 명 거래명세 거래명세내역 PK 거래명세일련번호 FK PK 품목번호 FK PK 거래명세일련번호 년월일 공급받는자 공급자등록번호FK 공급자사업장번호FK 규격 수량 단가 비고
70
SQL 기초 02 1. SQL문의 종류 DDL (Data Definition Language) : 데이터와 그 구조를 정의 합니다. SQL문 내 용 CREATE 데이터베이스 객체를 생성 합니다. DROP 데이터베이스 객체를 삭제 합니다. ALTER 기존에 존재하는 데이터베이스 객체를 다시 정의하는 역할을 합니다. DML (Data Manipulation Language) : 데이터의 검색과 수정 등의 처리 – commit/rollback SQL문 내 용 INSERT 데이터베이스 객체에 데이터를 입력 DELETE 데이터베이스 객체에 데이터를 삭제 UPDATE 기존에 존재하는 데이터베이스 객체안의 데이터 수정 SELECT 데이터베이스 객체로부터 데이터를 검색 DCL (Data Control Language) : 데이터베이스 사용자의 권한을 제어 – PGM보단 DBA업무 SQL문 내 용 GRANT 데이터베이스 객체에 권한을 부여 합니다. REVOKE 이미 부여된 데이터베이스객체의 권한을 취소합니다.
71
SQL 기초 02 2. 테이블 ◈ 테이블이란? 1. 테이블은 DataBase의 기본적인 데이타 저장 단위 입니다.
3. 테이블은 시스템내에서 독립적으로 사용되길 원하는 엔티티를 표현할 수 있습니다. 예를 들면, 회사에서의 고용자나 제품에 대한 주문은 테이블로 표현 가능합니다. 4. 테이블은 두 엔티티간의 관계를 표현할 수 있습니다. 즉 테이블은 고용자와 그들의 작업 숙련도 혹은 제품과 주문과의 관계를 표현하는데 사용될 수 있습니다. 테이블내에 있는 외래 키(ForeIgn Key)는 두 엔티티 사이의 관계를 표현하는데 사용됩니다. 5. 비록 "테이블" 이라는 말이 더 많이 사용되지만 테이블의 형식어는 "릴레이션" 입니다. 컬럼 : 테이블의 각 컬럼은 엔티티의 한 속성을 표현한다 행(ROW, 레코드) : 테이블의 데이타는 행에 저장됩니다 ◈ 테이블 생성시 제한사항과 고려 할 점 - 테이블 이름과 컬럼은 항상 알파벳 문자로 시작해야 하며 A~Z까지의 문자, 0~9까지의 숫자, 그리고 $,#,_(Under Bar)를 사용할 수 있습니다. (공백 사용 불가능) - 테이블의 컬럼 이름은 30자를 초과 할 수 없고, 예약어를 사용 할 수 없습니다. - 오라클 테이블 한 계정 안에서 테이블 이름은 다른 테이블 이름과 달리 유사해야 합니다. - 한 테이블 안에서 컬럼 이름은 같을 수 없으며 다른 테이블에서의 컬럼 이름과는 같을 수 있습니다.
72
SQL 기초 02 3. 테이블의 생성 문법 CREATE TABLE [schema.]table_name
- Column : 컬럼의 이름 - Datatype : 컬럼의 데이터 유형 - TABLESPACE : 테이블이 데이터를 저장 할 테이블스페이스를 지정 합니다. - PCTFREE : 블록 내에 이미 존재하고 있는 Row에 Update가 가능하도록 예약시켜 놓는 블럭의 퍼센트 값을 지정 합니다. - PCTUSED : 테이블 데이터가 저장될 블록의 행 데이터 부분의 크기를 퍼센트로 지정 합니다. PCTFREE에 의해 지정된 크기만큼 Block이 차면 PCTUSED 값보다 작아져야 새로운 행 삽입이 가능 합니다. CREATE TABLE [schema.]table_name ( column datatype [, column datatype ] ) [TABLESPACE tablespace ] [ PCTFREE integer ] [ PCTUSED integer ] [ INITRANS integer ] [ MAXTRANS integer ] [ STORAGE storage-clause ] [ LOGGING | NOLOGGING ] [ CACHE | NOCACHE ] ; - INITRANS : 하나의 데이터 블록에 지정될 초기 트랜잭션의 값을 지정합니다. (기본값은 1) - MAXTRANS: 하나의 데이터 블록에 지정될 수 있는 트랜잭션 최대 수를 지정 합니다. (기본값은 255) - STORAGE: 익스텐트 스토리지에 대한 값을 지정 합니다. - LOGGING: 테이블에 대해 이후의 모든 작업이 리두 로그 파일 내에 기록 되도록 지정합니다. (default) - NOLOGGING: 리두 로그 파일에 테이블의 생성과 특정 유형의 데이터 로드를 기록하지 않도록 지정 합니다. - CACHE : 전체 테이블 스캔(full table scan)이 수행될 때 읽어 들인 블록이 버퍼 캐쉬 내의 LRU 리스트의 가장 최근에 사용된 것의 자리에 위치 하도록 지정 합니다. - NOCACHE : 전체 테이블 스캔(full table scan)이 수행될때 읽어 들인 블록이 버퍼 캐쉬 내의 LRU 리스트의 가장 최근에 사용 되지 않은 것의 자리에 위치하도록 지정 합니다. PCTFREE 블럭내에 이미 존재하고 있는 Row에 Update가 가능하도록 예약시켜 놓는 블럭의 퍼센트 값을 지정 합니다. 예로 "PCTFREE 20" 으로 설정을 하면, 데이터 블록의 20%를 사용 가능한 빈 영역으로 유지하여 각 블록에 있는 행을 갱신하는데 사용한다는 의미입니다. PCTFREE의 기본값은 10% 입니다. PCTFREE와 PCTUSED의 합이 100을 초과하지 않는 범위 내에서 0에서 99까지의 값을 PCTFREE 값으로 사용할 수 있습니다. INDEX값은 수정이 자주 발생하지 않으므로 PCTFREE는 5%정도가 적당합니다. PCTFREE가 적을 경우 - 기존 테이블 행 갱신에 의한 확장을 위해 적은 공간을 확보 합니다. - 많은 로우가 한 블럭에 입력 가능합니다. - 수정이 적은 세그먼트에 적합 합니다. PCTFREE가 클 경우 - 블럭당 적은 row가 입력됩니다. 즉 같은 row를 입력하기 위해서 많은 블럭이 소요 됩니다. - 행 조각을 자주 체인화할 필요가 없으므로 수정 수행 속도가 증가 합니다. - 자주 수정되는 세그먼트에 적합 합니다. PCTUSED 오라클 서버가 테이블의 각 데이터 블록에 대해 유지하려는 사용 공간의 최소 백분율로써 데이터 세그먼트에 대해 지정합니다 예로 "PCTUSED 40" 으로 설정하면, 데이터 블록의 사용영역이 39%보다 적어지지 않으면 새로운 행을 삽입할 수 없음을 의미 합니다. PCTUSED의 기본값은 40% 입니다. PCTUSED값이 적을 경우 - 블록이 재사용되는 일이 적어질 수 있으므로 처리 비용이 감소 합니다. - 데이터베이스에서 사용되지 않은 공간이 증가 합니다. PCTUSED값이 클 경우 - 블록이 재사용되는 일이 많아질 수 있으므로 처리 비용이 증가 합니다. - 공간 사용도를 향상 시킵니다.
73
SQL 기초 02 4. 테이블의 생성 예제 ◈ DEPT2 테이블 생성 예제 입니다.
CREATE TABLE DEPT2( DEPTNO NUMBER CONSTRAINT dept_pk_deptno PRIMARY KEY, - (컬럼) (데이터타입) (제약조건) DNAME VARCHAR2(40), LOC VARCHAR2(50)) PCTFREE 20 PCTUSED 50 ; ◈ 테이블 생성시 주의사항 - 테이블 이름을 지정하고 각 컬럼들은 괄호 "()" 로 묶어 지정합니다. - 컬럼뒤에 데이터 타입은 꼭 지정되어야 합니다. - 각 컬럼들은 콤마","로 구분되고, 항상 끝은 세미콜론";" 으로 끝납니다. - 한 테이블 안에서 컬럼 이름은 같을 수 없으며 다른 테이블에서의 컬럼 이름과는 같을 수 있습니다. EMP, DEPT 테이블 생성 ◈ USER_TABLES 데이터사전을 조회 하면 유저가 소유한 테이블을 확인 할 수 있습니다. SELECT table_name FROM USER_TABLES; TABLE_NAME BONUS CRETABLE
74
SQL 기초 02 5. 테이블의 제약조건 제약조건이란 테이블에 부적절한 자료가 입력되는 것을 방지하기 위해서 여러 가지 규칙을 적용해 놓는 거라 생각하면 됩니다. 간단하게 테이블 안에서 데이터의 성격을 정의하는 것이 바로 제약조건 입니다. ▷ 데이터의 무결성 유지를 위하여 사용자가 지정할 수 있는 성질 입니다. ▷ 모든 CONSTRAINT는 데이터 사전(DICTIONARY)에 저장 됩니다. ▷ 의미있는 이름을 부여했다면 CONSTRAINT를 쉽게 참조할 수 있습니다. ▷ 표준 객체 명명법을 따르는 것이 좋습니다. ▷ 제약조건은 테이블을 생성할 당시에 지정할 수도 있고, 테이블 생성 후 구조변경(ALTER)명령어를 통해서도 추가가 가능합니다. ▷ NOT NULL제약조건은 반드시 컬럼 레벨에서만 정의가 가능합니다. 제 약 조 건 설 명 PRIMARY KEY(PK) 유일하게 테이블의 각행을 식별(NOT NULL과 UNIQUE조건을 만족) FOREIGN KEY(FK) 열과 참조된 열 사이의 외래키 관계를 적용하고 설정합니다. UNIQUE key(UK) 테이블의 모든 행을 유일하게 하는 값을 가진 열(NULL을 허용) NOT NULL(NN) 열은 NULL값을 포함할 수 없습니다. CHECK(CK) 참이어야 하는 조건을 지정함(대부분 업무 규칙을 설정)
75
SQL 기초 02 5. 테이블의 제약조건 ◈ NOT NULL 조건 : 컬럼을 필수 필드화 시킬 때 사용합니다.
CREATE TABLE emp( ename VARCHAR2(20) CONSTRAINT emp_nn_ename NOT NULL ); 위와 같이 테이블을 생성하면 ename 컬럼에는 꼭 데이터를 입력해야만 합니다. - 여기서 emp_nn_ename은 (테이블이름_제약조건이름_컬럼이름) 형식으로 CONSTRAINT NAME을 정의 합니다. - CONSTRAINT NAME은 USER_CONSTRAINTS 뷰(VIEW)를 통해서 확인 할 수 있습니다. SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME ='EMP' ; CONSTRAINT_NAME emp_nn_ename 이런 식으로 제약조건의 이름을 확인할 수 있습니다. ◈ UNIQUE 조건 UNIQUE 조건 : 데이터의 유일성을 보장 합니다. (중복되는 데이터가 존재할수 없습니다.) 유니크 조건을 생성하면 자동으로 index가 생성됩니다. ALTER TABLE emp ADD CONSTRAINT emp_uk_deptno UNIQUE (deptno) ; - 위와 같이 제약조건을 생성하면 deptno 컬럼에 중복된 데이터가 들어갈 수 없습니다. -- 제약 조건의 삭제 ALTER TABLE emp DROP CONSTRAINT emp_uk_deptno ;
76
SQL 기초 02 5. 테이블의 제약조건 ◈ CHECK 조건 : 컬럼의 값을 어떤 특정 범위로 제한할 수 있습니다.
ALTER TABLE emp ADD CONSTRAINT emp_ck_comm CHECK (comm >= 10 AND comm <= ) ; : comm컬럼은 체크조건에서 제한을 하고 있으므로 1에서 100까지의 값만을 가질수 있습니다. 또 체크 조건에서는 IN 연산자를 사용할 수 있습니다. -- 제약 조건의 삭제 ALTER TABLE emp DROP CONSTRAINT emp_ck_comm ; -- IN 연산자를 이용해서 CHECK 제약 조건을 생성 ALTER TABLE emp ADD CONSTRAINT emp_ck_comm CHECK (comm IN (10000,20000,30000,40000,50000)) ; : comm 컬럼은 10000,20000,30000,40000,50000의 값만을 가질 수 있습니다. ◈ DEFAULT(컬럼 기본값) 지정 데이터 입력시에 입력을 하지 않아도 지정된 값이 디폴트로 입력이 됩니다. CREATE TABLE emp( hiredate DATE DEFAULT SYSDATE ) ; 위와 같이 디폴트 값을 설정하면 hiredate 컬럼에 INSERT를 하지 않아도 오늘 날짜가 들어갑니다.
77
SQL 기초 02 5. 테이블의 제약조건 ◈ PRIMARY KEY(기본키) 지정
▷ 기본키는 그 데이터 행을 대표하는 컬럼으로서의 역할을 수행하여 다른 테이블에서 외래키들이 참조할 수 있는 키로서의 자격을 가지고 있습니다. 이를 참조 무결성이라 합니다. ▷ UNIQUE 조건과 마찬가지로 기본키를 정의하면 자동으로 인덱스를 생성하며 그 이름은 기본 키 제약 조건의 이름과 같습니다. CREATE TABLE emp( empno NUMBER CONSTRAINT emp_pk_empno PRIMARY KEY ) ; 위와 같이 제약조건을 설정 하면 empno 컬럼에 UNIQUE 제약조건과 NOT NULL제약조건을 가지게 됩니다. ◈ FOREIGN KEY(외래 키)지정 FOREIGN KEY(외래 키)지정 : 기본키를 참조하는 컬럼 또는 컬럼들의 집합입니다. ▷ 외래키를 가지는 컬럼의 데이터 형은 외뢰키가 참조하는 기본키의 컬럼과 데이터형이 일치해야 합니다. 이를 어기면 참조무결성 제약에의해 테이블을 생성 할 수 없습니다. ▷ 외래키에 의해 참조되고 있는 기본 키는 삭제 할 수 없습니다. ▷ ON DELETE CASCADE 연산자와 함께 정의된 외래키의 데이터는 그 기본키가 삭제 될 때 같이 삭제됩니다. ALTER TABLE emp ADD CONSTRAINT emp_fk_deptno FOREIGN KEY (deptno) REFERENCES dept(deptno) 위와 같이 제약조건을 생성하면 emp 테이블의 deptno 컬럼은 dept 테이블에 deptno 컬럼을 참조하는 외래키를 가지게 됩니다.
78
SQL 기초 02 6. 데이터 타입 ◈ 데이터 타입(오라클) DATA TYPE 설 명 VARCHAR2(n)
설 명 VARCHAR2(n) 가변 길이 문자 데이터(1~4000byte) CHAR(n) 고정 길이 문자 데이터(1~2000byte) NUMBER(p,s) 전체 p자리 중 소수점 이하 s자리(p:1~38, s:-84~127) DATE 7Byte(BC 4712년 1월 1일부터 AD 9999년 12월 31일) LONG 가변 길이 문자 데이터(1~2Gbyte) CLOB 단일 바이트 가변 길이 문자 데이터(1~4Gbyte) RAW(n) n Byte의 원시 이진 데이터(1~2000) LONG RAW 가변 길이 원시 이진 데이터(1~2Gbyte) BLOB 가변 길이 이진 데이터(1~4Gbyte) BFILE 가변 길이 외부 파일에 저장된 이진 데이터(1~4Gbyte)
79
SQL 기초 02 6. 데이터 타입 ◈ 숫자 데이터(Numeric Data)
▷ 오라클 데이터베이스에서 숫자는 항상 가변 길이 데이터로 저장되며 유효 자릿수 38자리까지 저장할 수 있습니다. ◈ 문자 데이터(Character Data) ▷ 문자 데이터는 데이터베이스에 고정 길이, 또는 가변 길이 문자열로 저장될 수 있습니다. ▷ CHAR와 NCHAR같은 고정 길이 문자 데이터 유형은 고정 길이까지 공백으로 채워서 저장합니다. ▷ NCHAR는 고정 폭(fixed-width), 또는 가변 폭(variable-width) character set의 저장을 가능하게 하는 NLS 데이터 유형입니다. 최대 크기는 한 문자를 저장하는데 필요한 바이트 수에 따라 결정되며 한 행 당 2000 바이트가 상한입니다. 기본값은 charater set에 따라 1 문자, 또는 1 바이트입니다. ▷ 가변 길이 문자 데이터 유형은 실제 컬럼 값을 저장하는데 필요한 바이트 만큼만을 사용하며 각 행에 따라 그 크기가 다양합니다. VARCHAR2와 NVARCHAR2 가 있습니다. ◈ 날짜(DATE) 데이터 유형 ▷ 오라클 서버는 날짜를 7 바이트, 고정 길이 필드(field)로 저장합니다. ▷ 오라클 DATE는 항상 시간을 포함합니다.
80
SQL 기초 02 6. 데이터 타입 ◈ RAW 데이터 유형 ▷ 크기가 적은 이진 데이터의 저장에 사용 합니다.
◈ 크기가 큰 오브젝트를 저장하기 위한 데이터 유형 ▷ 크기가 큰 오브젝트를 저장하기 위한 데이터 유형에는 LONG과 LONG RAW, LOB데이터 유형이 있습니다. ▷ LONG데이터 유형은 2GB의 문자열 데이터를 저장 할 수 있습니다. ▷ 오라클은 LOB을 저장하기 위한 여섯 가지 데이터 유형을 제공합니다. - 큰 고정 폭(fixed-width) 문자 데이터를 위한 CLOB과 LONG - 큰 고정 폭 국가 character set 데이터를 위한 NCLOB - 구조화되지 않은 데이터를 저장하기 위한 BLOB과 LONG RAW - 구조화되지 않은 데이터를 운영 체제 파일에 저장하기 위한 BFILE - LOB은 TEXT, 그래픽, 이미지, 비디오, 사운드 등 구조화되지 않은 대형 데이터를 저장하는데 사용한다. - 일반적으로 테이블에 저장되는 구조화된 데이터들은 크기가 작지만, 멀티미디어 데이터는 크기가 크다. - 크기가 큰 데이터는 DB에 저장하기 힘들기 때문에 OS상 존재하는 파일을 데이터베이스가 접근하게 된다. - LONG, LONG RAW 데이터 유형은 예전에 사용던 것이고, 현재는 대부분 LOB 데이터 유형을 사용한다. - TO_LOB 함수를 이용하여 LONG 및 LONG RAW 를 LOB 으로 변경할 수 있다. 종류 - CLOB: 문자 대형 객체 (Character). Oracle Server는 CLOB과 VARCHAR2 사이에 암시적 변환을 수행한다. - BLOB: 이진 대형 객체 (Binary). 이미지, 동영상, MP3 등... - NCLOB: 내셔널 문자 대형 객체 (National). 오라클에서 정의되는 National Character Set을 따르는 문자. - BFILE: OS에 저장되는 이진 파일의 이름과 위치를 저장. 읽기 전용 모드로만 액세스 가능. LONG, LONG RAW LOB 테이블에 컬럼 하나만 생성 할 수 있음 테이블에 여러개의 컬럼 생성이 가능 2GB 4GB SELECT결과로 데이터를 리턴 SELECT결과로 위치를 리턴 데이터를 직접 저장 데이터를 직접 또는 간접 저장 오브젝트 유형을 지원하지 않음 오브젝트 유형 지원
81
SQL 기초 02 7. 테이블 관리 ◈ ADD 연산자 ALTER TABLE emp ADD (addr VARCHAR2(50));
VARCHAR2의 데이터 형을 가지는 addr 컬럼이 emp 테이블에 추가 됩니다. ◈ MODIFY 연산자 MODIFY 연산자 : 테이블의 컬럼을 수정 하거나 NOT NULL컬럼으로 변경 할 수 있습니다. ALTER TABLE emp MODIFY (ename VARCHAR2(50) NOT NULL) ; -> ename컬럼이 VARCHAR2 50자리로 수정 됩니다. ※컬럼이 이미 테이터를 가지고 있을 경우 다른 데이터형으로 변경이 불가능합니다. ◈ DROP 연산자 - 컬럼의 삭제 예제 ALTER TABLE table_name DROP COLUMN column_name - 제약 조건의 삭제 예제 ALTER TABLE emp DROP CONSTRAINT emp_pk_empno CASCADE; -- CASCADE 연산자와 함께 사용하면 외래키에 의해 참조되는 기본키도 삭제될수 있습니다.
82
SQL 기초 02 7. 테이블 관리 ◈ 기존 테이블의 복사 ▷ 기존 테이블을 부분, 또는 완전히 복사할 때에 서브쿼리를 가진 CREATE TABLE 명령어를 사용해서 쉽게 테이블을 복사 할 수 있습니다. ▷ 하지만 제약 조건, 트리거, 그리고 테이블 권한은 새로운 테이블로 복사되지 않습니다. ▷ 제약조건은 NOT NULL제약조건만 복사 됩니다. [문법] [예제] CREATE TABLE emp2 AS SELECT * FROM emp; CREATE TABLE [schema.]table_name [ LOGGING | NOLOGGING ] [ ] AS subquery ◈ 테이블의 테이블스페이스 변경 ALTER TABLE emp MOVE TABLESPACE test; emp 테이블의 테이블스페이스를 test로 변경 했습니다. ALTER TABLE table_name MOVE TABLESPACE tablespace_name;
83
SQL 기초 02 7. 테이블 관리 ◈ 테이블의 TRUNCATE
▷ 테이블을 Truncate하면 테이블의 모든 행이 삭제되고 사용된 공간이 해제 됩니다. ▷ TRUNCATE TABLE은 DDL명령이므로 롤백 데이터가 생성되지 않습니다. DELETE명령으로 데이터를 지우면 롤백명렁어로 복구 할 수 있지만 TRUNCATE로 데이터를 삭제하면 롤백을 할 수가 없습니다. ▷행의 인덱스도 같이 잘려 나갑니다. ▷외래키가 참조중인 테이블은 TRUNCATE 할 수 없습니다. ▷TRUNCATE명령을 사용하면 삭제 트리거가 실행되지 않습니다. TRUNCATE TABLE [schema.]table_name ; ◈ DROP TABLE (테이블을 삭제할 때 사용) DROP TABLE emp ; DROP TABLE emp CASCADE CONSTRAINT; CASCADE CONSTRAINT 외래키에 의해 참조되는 기본키를 포함한 테이블일 경우 기본키를 참조하던 외래 키 조건도 같이 삭제 됩니다. DROP TABLE [schema.]table_name [CASCADE CONSTRAINTS] ;
84
SQL 기초 02 8. 데이터 조작어(DML) ◈ INSERT
- 실제 데이터는 VALUES 괄호()안에 입력하고 문자열은 단일 따옴표(' ')로 둘러쌉니다. - 각각의 테이터 구분은 ","로 합니다. - 테이블 이름 옆에 ()생략 시에는 모든 컬럼을 VALUES()안에 입력 시킵니다 - 모든 데이터를 입력할 경우 INSERT INTO EMP VALUES(7369, 'SMITH', 'CLERK', 7902, TO_DATE('80/12/17'), 800, NULL, 20); - 원하는 데이터만 입력할 경우 INSERT INTO DEPT (DEPTNO, DNAME) VALUES(10, 'ACCOUNTING' ); ◈ SELECT 문장을 이용한 INSERT INSERT INTO DEPT SELECT * FROM SCOTT.DEPT ; INSERT INTO table_name VALUES (column1, column2,…); EMP, DEPT 테이블 Data Insert INSERT INTO table_name(column1, column2,…) SELECT column1, column2,… FROM table_name WHERE 조건 ;
85
SQL 기초 02 8. 데이터 조작어(DML) ◈ UPDATE UPDATE 명령어는 테이블 안의 데이터를 수정 합니다.
UPDATE EMP SET DEPTNO = 30 WHERE EMPNO = 7902 ; 사원번호가 7902번인 사람의 부서 번호가 30번으로 수정됨 UPDATE EMP SET SAL = SAL * 1.1 WHERE DEPTNO = 20 ; 20부서의 사원들의 급여가 10% 인상됨 UPDATE EMP SET HIREDATE = SYSDATE 모든 사원의 입사일이 오늘로 수정됨 UPDATE table_name SET column1 = 값(고칠내용), column2 = 값, … WHERE 조건 EMP, DEPT 테이블 Data Insert ◈ DELETE DELETE 명령어는 테이블 안의 데이터를 삭제 합니다. DELETE FROM EMP WHERE EMPNO = 7902 ; 사원번호가 7902번인 사람의 데이터가 삭제 되었습니다. DELETE FROM EMP WHERE SAL < (SELECT AVG(SAL) FROM EMP) ; 평균급여보다 적게 받는 사원 삭제 DELETE FROM EMP ; 테이블의 모든 행이 삭제 됩니다. DELETE FROM table_name WHERE 조건 ;
86
SQL 기초 02 8. 데이터 조작어(DML) ◈ SELECT 문
- DISTINCT : 중복되는 행을 제거하는 옵션입니다. - * : 테이블의 모든 column을 출력 합니다. - alias : 해당 column에 대해서 다른 이름을 부여할 때 사용합니다. - table_name : 질의 대상 테이블명 - WHERE : 조건을 만족하는 행들만 검색 - condition : column, 표현식, 상수 및 비교 연산자 - ORDER BY : 질의 결과 정렬을 위한 옵션(ASC:오름차순(Default),DESC내림차순) [ SQL문의 작성 방법 ] - SQL 문장은 대소문자를 구별하지 않습니다. - SQL 문장은 한 줄 또는 여러 줄에 입력될 수 있습니다. - 일반적으로 키워드는 대문자로 입력합니다. 다른 모든 단어, 즉 테이블 이름, 열 이름은 소문자로 입력합니다.(권장) - 가장 최근의 명령어가 1개가 SQL buffer에 저장됩니다. - SQL문 마지막 절의 끝에 ";"를 기술하여 명령의 끝을 표시 합니다. [예제] SELECT empno 사번, ename 성명 FROM emp WHERE deptno = 10 SELECT [DISTINCT] {*, column [alias], . . .} FROM table_name [WHERE condition] [ORDER BY {column, expression} [ASC | DESC]]; 실무에서 사용 x 영문 대문자로 줄 것(A,B,C…), 필요에 따라서 2글자도 사용함 EMP, DEPT 테이블 조회 사이트마다 다름. 사이트 표준대로 사용
87
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 다음 두 문장을 실행 시키고 결과를 비교해 보자
ELECT EMP_ID,EMP_NAME FROM TEMP; SELECT EMP_ID,EMP_NAME FROM TEMP WHERE EMP_ID > 0; 2) 다음을 실행해 보시오 SELECT EMP_ID, DEPT_CODE, DEPT_NAME FROM TEMP, TDEPT WHERE TDEPT.DEPT_CODE = TEMP.DEPT_CODE; 3) 위에서 문장을 정상적으로 실행되게 수정하여 결과를 확인 하세요.
88
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 4) 다음 문장을 실행 시키세요
SELECT EMP_ID,EMP_NAME FROM TEMP ORDER BY EMP_ID; 5) 위 결과값을 DESCENDING 으로 결과를 나오게 수정 하세요 6) 위 결과를 직급 명(LEV)에 ASCENDING하면서 결과 내에서 다시 사번 순으로 DESCENDING 하게하는 ORDER BY 하는 문장을 만들어 보시오. 단, ORDER BY에 컬럼 명 대신 컬럼 순서를 기술하세요.
89
SQL 기초 02 8. 데이터 조작어(DML) ◈ Arithmetic Expressions (산술 연산자)
SELECT 문을 사용하다 보면 연산할 일이 많이 발생합니다. 예를 들면, 기본급에 보너스를 포함한 금액을 보고 싶을 경우, 다음과 같이 ‘salary + comm’ 으로 표현합니다. 또한 현재일 기준으로 근무 일수를 구할 경우에도 사용할 수 있습니다. 즉, 산술 연산자는 decimal type 뿐만 아니라, date type 등 여러 목적으로 사용 가능 합니다. 산술 연산자는 FROM 절을 제외한 모든 절에 사용 가능 합니다. SELECT salary, salary + 300, salary + comm FROM employee; ◈ Concatenation Operator Concatenation Operator는 컬럼 또는 문자열을 다른 컬럼과 연관시켜 하나의 컬럼으로 보이게 합니다. 주로 ‘컬럼명||컬럼명’ 형태로 사용하게 됩니다. SELECT firstnme||' '||midinit||' '||lastname as full_name FROM employee FETCH FIRST 5 ROWS ONLY" 위의 예제는 컬럼 firstnme, midinit, lastname 등을 연관지어 하나의 컬럼으로 보이게 만들었으며, 이 세 컬럼을 full_name 라는 Alias를 주어 조회하고 있습니다. full_name Alias의 사용은 SELECT 절의 가독성을 훨씬 높이는 효과가 있습니다.
90
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 1) TEMP 테이블에서 SALARY(연봉)을 이용하여 사원별 월 급여를 알아보는 SQL을 만드세요 월 급여는 연봉을 18로 나누어 홀수 달에는 연봉의 1/18 이 지급되고, 짝수 달에는 연봉의 2/18 가 지급된다고 가정했을 때 홀수 달과 짝수 달에 받을 금액을 구하세요 - EMP_NAM: 성명, SALARY: 연봉 2) 위에서 구한 월 급여에 교통비가 10만원씩 지급됬을때 (짝수 달은20만원) 결과값을 구하시오. 3) 사원테이블(TEMP)에서 성명(직급) 형태로 출력 하세요. - EMP_NAME: 성명, LEV: 직급 예) 김길동(부장) 4) 위 결과를 성명’직급’ 형태로 출력 하세요. 예) 김길동’부장’
91
SQL 기초 02 8. 데이터 조작어(DML) ◈ Duplicate Rows
관련된 Table의 정보를 조회할 때 몇 천건의 중복된 Data가 한 번에 조회될 때, 중복되지 않은 유일한 Data 값만 보기를 원할 경우가 있습니다. 이럴 경우 사용합니다. Eliminating Duplicate Rows (distinct 처리) SELECT bonus SELECT distinct bonus FROM employee FROM employee WHERE bonus = 400; WHERE bonus = 400; ◈ Using the WHERE Clause WHERE 절은 Table에 있는 Data에 일정 조건을 추가함으로써 조건에 부합하는 Data만 검색 합니다. 예를 들어 설명하면, employee Table의 전체 Data 42건 중 WHERE bonus = 400 조건에 부하는 7의 Data만 검색합니다. SELECT count SELECT count(*) FROM employee; FROM employee WHERE bonus = 400;
92
SQL 기초 02 8. 데이터 조작어(DML) ◈ Character String and Dates
WHERE 절에는 숫자 상수를 제외한 문자열 및 Date 데이터를 검색하기 위해 작은 따옴표로 감싸야 합니다. 또한 검색어의 모든 문자열은 대, 소문자가 구분됩니다. 예를 들어 해당 Table의 Data는 ‘FIELDREP’ 인데, WHERE 조건절에서 ‘fieldrep’로 조회한다면 Data를 전혀 검색할 수 없습니다. SELECT JOB SELECT JOB FROM EMP FROM EMP WHERE JOB = ‘analyst'; WHERE JOB = ' ANALYST '; 날짜와 관련한 데이터를 조회할 때는 해당 데이터의 Date Format을 명확히 알아야 합니다. 아래의 구문과 같이 잘못된 Format인 ‘일-월-연’ 으로 검색을 하면 ‘날짜 시간 값의 문자열 표현 구문이 올바르지 않습니다.’ 라는 오류 메시지를 받게 됩니다. SELECT empno, birthdate FROM employee WHERE birthdate = ' ' 1 라인 근처 오류: SQL0180N 날짜 시간 값의 문자열 표현 구문이 올바르지 않습니다. WHERE birthdate = ' ';
93
SQL 기초 02 8. 데이터 조작어(DML) ◈ WHERE절에 올 수 있는 연산자들 ◈ IN 과 NOT IN 연산자
SELECT empno, ename FROM emp WHERE empno IN (7900, 7934) ; --> 사번이 7900, 7934번인 사원의 사번과 성명 출력 [ NOT IN 연산자 ] SELECT empno, ename FROM emp WHERE empno NOT IN (7900, 7934); --> 사번이 7900, 7934번이 아닌 사원의 사번과 성명 출력 연산자 설 명 BETWEEN a AND b a와b사이의 데이터를 출력 합니다.(a, b값 포함) IN (list) list의 값 중 어느 하나와 일치하는 데이터를 출력 합니다. LIKE 문자 형태로 일치하는 데이터를 출력 합니다.(%, _사용) IS NULL NULL값을 가진 데이터를 출력 합니다. NOT BETWEEN a AND b a와b사이에 있지않은 데이터를 출력 합니다.(a, b값 포함하지 않음) NOT IN (list) list의 값과 일치하지 않는 데이터를 출력 합니다. NOT LIKE 문자 형태와 일치하지 않는 데이터를 출력 합니다. IS NOT NULL NULL값을 갖지 않는 데이터를 출력 합니다. =or
94
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 1) TEMP(사원테이블)에서 성명(EMP_NAME)이 ‘홍길동’,’김길동’을 IN을 사용하여 조회 하시오. 2) TEMP(사원테이블)에서 성명(EMP_NAME)이 ‘홍길동’,’김길동’을 OR을 사용하여 조회 하시오.
95
SQL 기초 02 실무에서 거의 안씀 8. 데이터 조작어(DML) ▷% : 여러개의 문자열을 나타내는 와일드 카드
◈ BETWEEN 연산자 SELECT empno, ename FROM emp WHERE sal BETWEEN AND 5000 ; 급여가 3000에서 5000사이인 사원만 보여줍니다. BETWEEN 연산자(AND를 이용해 두 조건을 결합한 검색과 같은 결과값을 보여줍니다.) ◈ LIKE 연산자 ▷검색 STRING 값에 대한 와일드 카드 검색을 위해서 LIKE연산자를 사용 합니다. ▷% : 여러개의 문자열을 나타내는 와일드 카드 ▷_ : 단 하나의 문자를 나타내는 와일드 카드 ▷ESCAPE : 와일드 카드 문자를 일반문자 처럼 사용하고 싶은 경우에 사용합니다. WHERE name LIKE '%a\_y%' ESCAPE '\' ; ▷LIKE 연산자는 대소문자를 구분합니다. ▷Upper()함수를 이용해 대소문자 구분 없이 출력 할 수 있습니다. [예제] SELECT empno, ename FROM emp WHERE UPPER(ename) like '%K%'; 'K' 문자가 들어있는 사원 정보를 보여줍니다. upper()라는 함수는 k가 들어가 있는 것도 대문자 'K'로 인식하기 때문에 데이터들을 보여줍니다. ※ '_'를 이용한 LIKE검색 SELECT empno, ename FROM emp WHERE UPPER(ename) like '_I%' '_'는 한 문자를 나타냅니다. 'I' 문자가 두 번째 문자에 위치한 사원들의 정보를 보여줍니다. 실무에서 거의 안씀
96
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 1) TEMP(사원테이블)에서 사번이 1997로 시작하는 사원의 사번과 성명을 검색하시오. 2) TEMP(사원테이블)에서 성명(EMP_NAME)이 ‘ㄱ’ 으로 시작되는 사원의 사번과 성명을 검색하시오. 3) TEMP(사원테이블)에서 부서코드가 A로 시작되는 ROW를 검색한다. 4) TEMP(사원테이블)에서 부서코드 중에 A 가 들어가는 ROW를 검색한다.
97
SQL 기초 02 8. 데이터 조작어(DML) ◈ 테이블 예명(Alias)
- 테이블 alias로 column을 단순, 명확히 할 수 있습니다. - 현재의 SELECT 문장에 대해서만 유효합니다. - 테이블 alias는 길이가 30자 까지 가능하나 짧을수록 더욱 좋습니다. - 테이블 alias는 의미가 있어야 합니다 - FROM절에 테이블 alias설정시 해당 테이블 alias는 SELECT문장에서 테이블 이름 대신에 사용해야 합니다. SELECT a.dname, b.cnt FROM dept a , (SELECT deptno, COUNT(empno) cnt FROM emp GROUP BY deptno) b WHERE a.deptno = b.deptno AND b.cnt > 3 DNAME CNT RESEARCH SALES 사원수가 3명이 넘는 부서의 부서명과 사원수를 보여줍니다. 위 쿼리에선 총 3개의 Alias가 사용됐습니다. 첫 번째로 DEPT테이블을 a라는 예명으로 두 번째로 부서의 사원수인 COUNT(empno)를 cnt라는 예명으로 세 번째로 부서별 사원수를 가져오는 쿼리를 b라는 예명을 주었습니다. 위 예제와 같이 예명은 컬럼에만 주는 것이 아니라. 쿼리 문 및 테이블에도 사용할 수 있습니다.
98
SQL 기초 02 8. 데이터 조작어(DML) ◈ 조인(Join) [ 조인(Join) 이란 ]
▷둘 이상의 테이블을 연결하여 데이터를 검색하는 방법 입니다. ▷보통 둘 이상의 행들의 공통된 값 Primary Key 및 Foreign Key 값을 사용하여 조인 합니다. ▷그러므로 두 개의 테이블을 SELECT문장 안에서 조인하려면 적어도 하나의 컬럼이 그 두 테이블 사이에서 공유 되어야 합니다 [ 조인 방법 ] - Equijoin(동등 조인, 내부조인) - Non-equijoin - Outer join Self join [ Cartesian Product(카티션 곱) ] 검색하고자 했던 데이터뿐 아니라 조인에 사용된 테이블들의 모든 데이터가 Retrun되는 현상 [ Cartesian product는 다음과 같은 경우에 발생됩니다. ] - 조인 조건을 정의하지 않았을 경우 - 조인 조건이 잘못된 경우 - 첫 번째 테이블의 모든 행들이 두 번째 테이블의 모든 행과 조인이 되는 경우 - 테이블의 개수가 N이라면 Cartesian product를 피하기 위해서는 적어도 N-1개의 등가 조건을 SELECT 문안에 포함시켜서 다른 테이블 안에 있는 각 테이블의 컬럼이 적어도 한번은 참조되도록 해야 합니다.
99
SQL 기초 02 8. 데이터 조작어(DML) ◈ Equi Join
▷ 조건절 Equality Condition(=)에 의하여 조인이 이루 집니다. ▷ Equi join의 성능을 높이기 위해서는 Index 기능을 사용하는 것이 좋습니다. SELECT E.ENAME, D.DNAME WHERE 절에 조인 조건을 작성하고 column명 앞에 테이블명을 적습니다. FROM EMP E , DEPT D WHERE E.DEPTNO = D.DEPTNO; -- INNER JOIN절을 이용하여 조인하는 예제 SELECT E.EMPNO, E.ENAME, D.DNAME FROM DEPT D INNER JOIN EMP E 콤마(,) 대신 INNER JOIN을 사용 할 수 있으며, INNER는 생략 가능합니다. JOIN 조건은 ON 절에 온다. ON D.DEPTNO = E.DEPTNO; -- NATURAL JOIN절을 이용하여 조인하는 예제 SELECT E.EMPNO, E.ENAME, D.DNAME FROM DEPT D NATURAL JOIN EMP E; NATURAL JOIN을 사용 하면 동일한 컬럼을 내부적으로 모두조인 하므로, ON절이 생략 가능합니다. -- JOIN~USING절을 이용하여 조인하는 예제 SELECT E.EMPNO, E.ENAME, DEPTNO FROM EMP E JOIN DEPT D USING (DEPTNO); NATURAL JOIN의 단점은 동일한 이름을 가지는 칼럼은 모두 조인이 되는데, USING 문을 사용하면 컬럼을 선택해서 조인을 할 수가 있습니다.
100
SQL 기초 02 8. 데이터 조작어(DML) ◈ Non-Equijoin ◈ Self Join
▷ Non-equijoin은 테이블의 어떤 column도 join할 테이블의 column에 일치하지 않을 때 사용하고 조인조건은 동등( = )이외의 연산자를 갖습니다. (BETWEEN AND, IS NULL, IS NOT NULL, IN, NOT IN) -- emp 테이블과 dept 테이블의 Non-Equi Join 예제 SELECT E.ENAME, D.DNAME FROM EMP E, DEPT D WHERE E.SAL BETWEEN 3000 AND 4000; ◈ Self Join ▷ Equi Join과 같으나 하나의 테이블에서 조인이 일어나는 것이 다릅니다. ▷ 같은 테이블에 대해 두 개의 alias를 작성함으로 FROM절에 두 개의 테이블을 사용 하는 것과 같이 합니다. SELECT CONCAT(A.ENAME,' ') ||' : \'|| B.SAL 급여 FROM EMP A, EMP B WHERE A.EMPNO = B.EMPNO
101
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 1) 사원과 자신이 속한 부서의 부서장을 읽어내는 SQL을 만들어 보시오 - TEMP: 사원테이블, TDEPT: 부서테이블 - EMP_ID: 사원번호, EMP_NAME: 사원명, B.BOSS_ID: 부서장사원번호 2) 위 결과를 Header를 ‘사원번호’, ‘사원명’, ‘부서장사원번호’, ‘부서장명’으로 바꾸어 출력 하시오 3) TCOM테이블의 WORK_YEAR이 ‘2001’인 자료에서 TEMP를 사번으로 연결해서 JOIN 한 후 보너스(COMM)을 받는 직원의 사번, 성명, 연봉(SALARY)+ 보너스(COMM) 를 조회 해 보자. 4) TEMP테이블과 EMP_LEVEL테이블을 이용해 EMP_LEVEL의 과장 직급(LEV)의 연봉 상한(TO_SAL)/하한 범위(FROM_SAL) 내에 드는 직원의 사번과,성명,직급,SALARY를 구하시오.
102
SQL 기초 02 8. 데이터 조작어(DML) ◈ Out(외부) Join
▷ equi join 문장들의 한가지 제약점은 그것들이 조인을 생성하려 하는 두 개의 테이블의 두 개 컬럼에서 공통된 값이 없다면 테이블로부터 테이터를 Return하지 않는 다는 것입니다. ▷ 정상적으로 조인 조건을 만족하지 못하는 행들을 보기 위해 outer join을 사용합니다. Outer join 연산자 "( + )"입니다. ▷ 조인시킬 값이 없는 조인측에 "(+)"를 위치 시킵니다. ▷ Outer join 연산자는 표현식의 한 편에만 올 수 있습니다. ▷ Outer join은 IN 연산자를 사용할 수 없고 OR 연산자에 의해 다른 하나의 조건에 연결될 수 없습니다. 예제1) 일반 조인의 경우 SELECT DISTINCT(A.DEPTNO), B.DEPTNO FROM EMP A, DEPT B WHERE A.DEPTNO = B.DEPTNO DEPTNO DEPTNO 예제2) out join을 했을 경우 SELECT DISTINCT(A.DEPTNO), B.DEPTNO FROM EMP A, DEPT B WHERE A.DEPTNO(+) = B.DEPTNO DEPTNO DEPTNO 40
103
SQL 기초 02 8. 데이터 조작어(DML) ◈ LEFT, RIGHT, FULL Outer Join
▷ LEFT OUTERL JOIN은 오른쪽 테이블(아래 예제에서 emp테이블)에 조인시킬 컬럼의 값이 없는 경우 사용합니다. -- LEFT OUTER JOIN 조인 예제 SELECT DISTINCT(E.DEPTNO), D.DEPTNO FROM DEPT D LEFT OUTER JOIN EMP E ON D.DEPTNO = E.DEPTNO; ▷ RIGHT OUTERL JOIN은 왼쪽 테이블(아래 예제에서 emp테이블)에 조인시킬 컬럼의 값이 없는 경우 사용합니다. -- RIGHT OUTER JOIN 조인 예제 FROM EMP E RIGHT OUTER JOIN DEPT D ON E.DEPTNO = D.DEPTNO; ▷ FULL OUTERL JOIN은 양쪽 테이블 모두 Outer Join걸어야 하는 경우 사용 합니다. -- FULL OUTER JOIN 조인 예제 FULL OUTER JOIN DEPT D
104
SQL 기초 02 8. 데이터 조작어(DML) ◈ 실습 1) 각 사번의 성명, 이름, SALARY, 연봉하한금액, 연봉상한금액을 보고자 한다. TEMP와 EMP_LEVEL 을 조인하여 결과를 보여주되, 연봉의 상하한이 등록되어 있지 않은 ‘수습’ 사원은 성명, 이름, SALARY 까지만이라도 나올 수 있도록 QUERY를 구성해 보라. 2) TDEPT 테이블에 자신의 상위 부서 정보를 관리하고 있다. 이 테이블을 이용하여 부서코드, 부서명, 상위부서코드, 상위부서명을 읽어오는 SQL 을 만들어 보자. 3) TEMP 와 TDEPT를 이용하여 다음 컬럼을 보여주는SQL 을 만들어 보자. 상위부서가 ‘CA0001’ 인 부서에 소속된 직원을 1.사번, 2.성명, 3.부서코드, 4.부서명, 5.상위부서코드, 6.상위부서명, 7.상위부서장코드, 8.상위부서장성명 순서로 보여주면 된다.
105
SQL 기초 02 8. 데이터 조작어(DML) ◈ MERGE MERGE INTO 테이블 명 [별명]
USING {대상 테이블|뷰|} [별칭] ON 조인 조건 WHEN MATCHED THEN UPDATE SET 컬럼명 = 값, ……………. WHEN NOT MATCHED THEN INSERT [(컬럼 명, …)] VALUES (값, …); ▷ 추가하는 데이터가 테이블에 존재하지 않을 때는 INSERT가 수행되고, 이미 데이터가 존재할 경우에는 UPDATE가 수행됩니다. ▷ MERGE문장 작성 순서 1. 새로운 행이 추가되거나 갱신이 될 테이블을 지정합니다. 2. 다른 테이블을 참조하여 데이터를 비교한다면 대상 테이블 명을 별칭과 함께 정의합니다. 3. 새로운 행을 추가하려고 하는 테이블과 대상 테이블 간에 조인이 필요하면 ON절을 활용 합니다. 4. 조인 조건에 의해 만족하는 데이터가 있을 경우엔 UPDATE가 수행되고 만족하는 데이터가 존재하지 않으면 INSERT문이 수행됩니다.
106
SQL 기초 02 8. 데이터 조작어(DML) ◈ MERGE 예제1
▷ 부서번호 20,30의 사원이 존재하면 급여를 10% 인상하고, 존재하지 않으면 급여가 1000보다 큰 사원정보를 등록 -- 부서번호 10, 20의 사원정보를 가지는 테스트 테이블을 생성하자 CREATE TABLE EMP_MERGE_TEST AS SELECT EMPNO, DEPTNO, SAL FROM EMP WHERE DEPTNO IN (10, 20); -- 데이터를 확인해 보자 SELECT * FROM EMP_MERGE_TEST; -- 사원이 존재하면 급여를 10% 인상하고, 없으면 INSERT 합니다. MERGE INTO EMP_MERGE_TEST M USING ( SELECT EMPNO, DEPTNO, SAL -- USING절에 뷰가 올수 있습니다. FROM EMP WHERE DEPTNO IN (20,30)) E ON ( M.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET M.SAL = ROUND(M.SAL*1.1) WHEN NOT MATCHED THEN INSERT (M.EMPNO, M.DEPTNO, M.SAL) VALUES (E.EMPNO, E.DEPTNO, E.SAL) WHERE E.SAL > 1000 -- INSERT 절의 조건절도 지정이 가능하다 -- 20부서의 급여가 10%증가했고, 30부서는 등록되었는지 확인해 보자 -- 다음 테스트를 위해서 EMP_MERGE_TEST 테이블에 30부서 데이터를 삭제하자 -- 부서번호 10과 20의 사원정보만 남을 것입니다. DELETE FROM EMP_MERGE_TEST WHERE DEPTNO = 30;
107
SQL 기초 02 8. 데이터 조작어(DML) ◈ MERGE 예제2
▷ 부서번호 10의 사원 급여를 10% 인상하고, 부서번호 20의 사원정보는 삭제하며, 부서번호 30의 사원 급여를 20% 인상 -- 30 부서가 삭제되었는지 확인합니다. SELECT * FROM EMP_MERGE_TEST; -- MERGE 문 작성 MERGE INTO EMP_MERGE_TEST M USING EMP E ON (M.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET M.SAL = ROUND(M.SAL*1.1) DELETE WHERE (M.DEPTNO = 20) -- 부서번호 20의 사원정보는 삭제. WHEN NOT MATCHED THEN INSERT (M.EMPNO, M.DEPTNO, M.SAL) VALUES (E.EMPNO, E.DEPTNO, ROUND(E.SAL*1.2)); -- 정상적으로 변경되었는지 확인해 보자 -- 테스트 테이블은 삭제하자 DROP TABLE EMP_MERGE_TEST;
108
SQL 기초 02 8. 데이터 조작어(DML) ◈ TRANSACTION ▷ 트랜잭션은 데이터 처리의 한 단위 입니다.
▷ Oracle 서버에서 발생하는 SQL문들을 하나의 논리적인 작업단위로써 성공하거나 실패하는 일련의 SQL문을 Transaction이라 보시면 됩니다. ▷ ORACLE SERVER는 TRANSACTION을 근거로 데이터의 일관성을 보증 합니다. ▷ TRANSACTION은 데이터를 일관되게 변경하는 DML문장으로 구성됩니다 (COMMIT, ROLLBACK, SAVEPOINT) ① TRANSACTION의 시작 -실행 가능한 SQL문장이 제일 처음 실행될 때 ② TRANSACTION의 종료 - COMMIT이나 ROLLBACK - DDL이나 DCL문장의 실행(자동 COMMIT) - 기계 장애 또는 시스템 충돌(crash) - deadlock 발생 - 사용자가 정상 종료 ③ 자동 COMMIT은 다음의 경우 발생 합니다. - DDL,DCL문장이 완료 될때 - 명시적인 COMMIT이나 ROLLBACK없이 SQL*Plus를 정상 종료 했을 경우 ④ 자동 ROLLBACK은 다음의 경우 발생 합니다. - SQL*Plus를 비정상 종료 했을 경우 - 비정상적인 종료, system failure
109
SQL 기초 02 8. 데이터 조작어(DML) ◈ COMMIT과 ROLLBACK
- 데이터의 일관성을 제공 합니다. - 데이터를 영구적으로 변경하기 전에 데이터 변경을 확인하게 합니다. - 관련된 작업을 논리적으로 그룹화 할 수 있습니다. - COMMIT, SAVEPOINT,ROLLBACK 문장으로 TRANSACTION의 논리를 제어할 수 있습니다. ② COMMIT이나 ROLLBACK 이전의 데이터 상태 - 데이터 이전의 상태로 복구가 가능합니다. - 현재 사용자는 SELECT문장으로 DML작업의 결과를 확인할 수 있습니다. - 다른 사용자는 SELECT문장으로 현재 사용자 사용한 DML문장의 결과를 확인할 수 없습니다. - 변경된 행은 LOCK이 설정되어서 다른 사용자가 변경할 수 없습니다. ③ COMMIT이후의 데이터 상태 - 데이터베이스에 데이터를 영구적으로 변경 - 데이터의 이전 상태는 완전히 상실 - 모든 사용자가 결과를 볼 수 있습니다. - 변경된 행의 LOCK이 해제되고 다른 사용자가 변경할 수 있습니다. - 모든 SAVEPOINT는 제거 됩니다.
110
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 숫자함수(Number Functions)
▷ ABS(n) : ABS함수는 절대값을 계산하는 함수입니다. -- ABS 예제 SELECT ABS (-1.234) absolute FROM DUAL; ▷ CEIL(n) : CEIL함수는 주어진 값보다는 크지만 가장 근접하는 최소값을 구하는 함수입니다. -- CEIL 양수 예제 SELECT CEIL( ) "CEIL" FROM DUAL; -- CEIL 음수 예제 SELECT CEIL( ) "CEIL" FROM DUAL; ▷ EXP(n) : EXP함수는 주어진 값의 e의 승수를 나타냅니다. e는 입니다. ▷ FLOOR(n) : FLOOR함수는 주어진 값보다 작거나 같은 최대 정수값을 구하는 함수입니다. (CEIL 함수와 비교해 보세요. ) -- FLOOR 양수 예제 SELECT FLOOR( ) "FLOOR" FROM DUAL; -- FLOOR 음수 예제 SELECT FLOOR( ) "FLOOR" FROM DUAL; ▷ LN(n) : LN함수는 주어진 값의 자연로그 값을 반환합니다.
111
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 숫자함수(Number Functions)
▷ MOD(m, n) : MOD함수는 m을 n으로 나누어 남은 값을 반환합니다. n이 0일 경우 m을 반환합니다. -- MOD예제 SELECT MOD(9, 4) "MOD" FROM DUAL ; ▷ POWER(m, n) : POWER함수는 m의 n승 값을 계산합니다. ▷ ROUND(n, [m]) : ROUND함수는 n값의 반올림을 하는 함수로 m은 소숫점 아래 자릿수를 나타낸다. -- ROUND 예제 SELECT ROUND( , 1) TEST FROM dual; SELECT ROUND( , -1) TEST FROM dual ; ▷ SIGN(n) : SIGN함수는 n<0일 경우 -1DFM N=0일 경우 0을 N>0일 경우 1을 반환합니다. ▷ SQRT(n) : SQRT함수는 n값의 루트값을 계산합니다. n은 양수여야 합니다. ▷ TRUNC(n, m) : TRUNC함수는 n값을 m 소숫점 자리로 반내림한 값을 반환합니다. (ROUND 함수와 비교해 보세요) -- TRUNC 예제 SELECT TRUNC(7.5597, 2) TEST FROM dual; SELECT TRUNC( , -2 ) TEST FROM dual ;
112
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 문자열 처리 함수(Character Functions) ▷ CONCAT(char1, char2) CONCAT 함수는 Concatenation의 약자로 두 문자를 결합하는 역할을 합니다. "||" 연산자와 같은 역할을 합니다. SELECT CONCAT('Oracle', ' Korea') NAME FROM dual ; ▷ INITCAP(char) : 주어진 문자열의 첫 번째 문자를 대문자로 변환시켜 줍니다. SELECT INITCAP('oracleclub') name FROM DUAL ▷ LOWER(char) : 문자열을 소문자로 변환 시켜 줍니다. SELECT LOWER(‘ORACLECLUB’) name FROM DUAL; ▷ UPPER(char) : 문자열을 대문자로 변환 시켜 줍니다. SELECT UPPER('oracleclub') name FROM DUAL ▷ LPAD(char1, n [,char2]) :왼쪽에 문자열을 끼어 놓는 역할을 합니다. n은 반환되는 문자열의 전체 길이를 나타내며, char1의 문자열이 n보다 클 경우 char1을 n개 문자열 만큼 반환합니다. SELECT LPAD('JUNG-SICK', 10, '*') NAME FROM dual ; ▷ RPAD(char1, n [,char2]) : LPAD와 반대로 오른쪽에 문자열을 끼어 놓는 역할을 합니다 SELECT RPAD('JUNG-SICK', 10, '*') NAME FROM dual ;
113
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 실습
1) 부서(TDEPT) 테이블의 자료 중 부서명(DEPT_NAME)을 우측 정렬 시키고 전체 10자리를 기준으로 앞의 공란에 ‘*’ 기호를 찍어주는 표현하는 문장을 만들어 보시오. 2) 부서(TDEPT) 테이블의 부서명(DEPT_NAME)을 10자리에 맞춰 읽어오는데 왼쪽의 공란에 순서대로 번호를 붙이는 문장을 만들어 보시오. 단, DEPT_NAME 은 최소 1자리의 값이 들어 있다. 3) 부서(TDEPT) 테이블의 부서명(DEPT_NAME)을 10자리에 맞춰서 뒤에 남는 자리에 자신의 자릿수에 해당하는 숫자를 붙여 보시오.
114
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 문자열 처리 함수(Character Functions) ▷ INSTR : 문자열이 포함되어 있는지를 조사하여 문자열의 위치를 반환합니다. 지정한 문자열이 발견되지 않으면 0이 반환 됩니다. -- 지정한 문자 OK가 발견되지 않아 0을 반환. SELECT INSTR('CORPORATE FLOOR','OK') idx FROM DUAL; -- OR이 있는 위치 2를 반환. 왼쪽부터 비교를 한다는 것을 알 수 있습니다. SELECT INSTR('CORPORATE FLOOR','OR') idx FROM DUAL; -- 왼쪽에서 세 번째부터 시작을 해서 검색된 OR의 위치를 반환 합니다. SELECT INSTR('CORPORATE FLOOR','OR', 3) idx FROM DUAL; -- 왼쪽에서 세 번째부터 시작을 해서 비교를 하여 OR이 두 번째 검색되는 지점의 위치를 반환 합니다. SELECT INSTR('CORPORATE FLOOR','OR', 3, 2) idx FROM DUAL;
115
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 문자열 처리 함수(Character Functions) ▷ SUBSTR(char, m ,[n]) : SUBSTR함수를 이용하여 m 번째 자리부터 길이가 n개인 문자열을 반환한 합니다. m이 음수일 경우에는 뒤에서 M번째 문자부터 반대 방향으로 n개의 문자를 반환합니다. -- 세번째 이후 문자열 반환. SELECT SUBSTR('oracleclub', 3) name FROM DUAL; -- 세번째 이후 네개의 문자열 반환. SELECT SUBSTR('oracleclub', 3, 4) name FROM DUAL; -- 뒤에서 세번째 이후 두개의 문자열 반환. SELECT SUBSTR('oracleclub', -3, 2) name FROM DUAL; ▷ LENGTH(char1) : 문자열의 길이를 리턴 합니다. -- 문자열의 LENGTH를 조회하는 예제. SELECT LENGTH('오라클클럽') len FROM DUAL UNION ALL SELECT LENGTHB('오라클클럽') len FROM DUAL; ▷ REPLACE(char1, str1, str2) : REPLACE는 문자열의 특정 문자를 다른 문자로 변환 합니다. -- 대소문자를 구분한다는 것을 알수 있습니다. SELECT REPLACE('OracleClub','oracle','DB') name FROM DUAL SELECT REPLACE('OracleClub','Oracle','DB') name FROM DUAL;
116
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 실습
1) ‘ABC좋은나라DEF웃긴나라’ 문자열의 두 번째부터 10 개의 문자열을 읽어 보시오. 2) 위 결과와 동일한 문자열의 동일한 문자열을 읽을 때 INSTRB를 사용해 보시오. 3) 위의 결과 중 마지막 글자인 ‘라’ 가 1바이트만 걸리도록 9바이트만 읽도록 수정해서 조회해 보시오. 4) ‘ABC좋은나라DEF웃긴나라’ 문자열의 뒤에서 네번째 이후 두개의 문자열만을 반환해 보시오. 5) 'ABC좋은나라DEF웃긴나라' 의 길이를 구하시오. 6) 위 결과를 LENGTHB를 사용해 보시오. 7) ‘ABC좋은나라DEF웃긴나라’ 문자열의 ‘나라’를 ‘**’으로 치환해 보시오. 8) ‘ABC좋은나라DEF웃긴나라’ 문자열의 영어를 제거 하시오.
117
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 문자열 처리 함수(Character Functions) ▷ INSTR : 문자열이 포함되어 있는지를 조사하여 문자열의 위치를 반환합니다. 지정한 문자열이 발견되지 않으면 0이 반환 됩니다. -- 지정한 문자 OK가 발견되지 않아 0을 반환. SELECT INSTR('CORPORATE FLOOR','OK') idx FROM DUAL; -- OR이 있는 위치 2를 반환. 왼쪽부터 비교를 한다는 것을 알 수 있습니다. SELECT INSTR('CORPORATE FLOOR','OR') idx FROM DUAL; -- 왼쪽에서 세 번째부터 시작을 해서 검색된 OR의 위치를 반환 합니다. SELECT INSTR('CORPORATE FLOOR','OR', 3) idx FROM DUAL; -- 왼쪽에서 세 번째부터 시작을 해서 비교를 하여 OR이 두 번째 검색되는 지점의 위치를 반환 합니다. SELECT INSTR('CORPORATE FLOOR','OR', 3, 2) idx FROM DUAL;
118
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 실습
1) ‘ABC좋은나라DEF웃긴나라’ 라는 문자열을 이용해서 ‘D’ 와 ‘나’ 문자가 위치하는 자리 수를 구하시오. 2) 위 결과와 동일한 문자열의 동일한 문자의 위치를 찾는데 INSTRB를 사용해 보시오. 3) ‘ABC좋은나라DEF웃긴나라’ 문자열에서 두 번째 나타나는 ‘나’ 의 위치를 구하시오.
119
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 문자열 처리 함수(Character Functions) ▷ TRIM : 특정한 문자를 제거 합니다. 제거할 문자를 입력하지 않으면 기본적으로 공백이 제거 됩니다. 리턴값의 데이터타입은 VARCHAR2 입니다. -- o와 공백을 제거 하는 TRIM 예제입니다. SELECT TRIM('o' FROM 'oracleclub') name FROM DUAL UNION ALL SELECT TRIM(' oracleclub ') name FROM DUAL; -- 왼쪽의 문자열을 TRIM하는 예제입니다. -- 공백의 경우 왼쪽 공백만 제거 되는 것을 확인 할 수 있습니다. SELECT LTRIM('oracleclub','oracle') name FROM DUAL SELECT REPLACE(LTRIM(' oracleclub '),' ','*') name FROM DUAL; -- 오른쪽의 문자열을 TRIM 하는 예제입니다. -- 공백의 경우 오른쪽 공백만 제거 되는 것을 확인 할 수 있습니다. SELECT RTRIM('oracleclub','club') name FROM DUAL SELECT REPLACE(RTRIM(' oracleclub '),' ','*') name FROM DUAL;
120
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 날짜 처리 함수(Date Functions)
▷ SYSDATE : SYSDATE 함수를 사용하면 현재 일자와 시간(시스템기준)을 얻을 수 있습니다. SELECT TO_CHAR(SYSDATE, 'RRRR-MM-DD HH24:MI:SS') "지금시간“ FROM DUAL ; SELECT TO_CHAR(SYSDATE-1, 'RRRR-MM-DD HH24:MI:SS') "하루전지금시간“ FROM DUAL ; SELECT TO_CHAR(SYSDATE-1/24, 'RRRR-MM-DD HH24:MI:SS') "1시간전시간" FROM DUAL ; SELECT TO_CHAR(SYSDATE-1/24/60, 'RRRR-MM-DD HH24:MI:SS') "1분전시간“ FROM DUAL ; SELECT TO_CHAR(SYSDATE-1/24/60/10, 'RRRR-MM-DD HH24:MI:SS') "6초전시간" FROM DUAL ; SELECT TO_CHAR(SYSDATE-(5/ /24/ /24/60/60), 'RRRR-MM-DD HH24:MI:SS') "5시간 30분 10초전“ FROM DUAL ; ▷ SYSTIMESTAMP : SYSTIMESTAMP 함수를 사용하면 현재 일자와 시간(시스템기준)을 얻을 수 있습니다. SELECT TO_CHAR(SYSTIMESTAMP, 'RRRR-MM-DD HH24:MI:SS.FF3‘) FROM DUAL ; SELECT TO_CHAR(SYSTIMESTAMP, 'RRRR-MM-DD HH24:MI:SS.FF9') FROM DUAL ; SELECT TO_CHAR(SYSTIMESTAMP -1/24, 'RRRR-MM-DD HH24:MI:SS') "1시간전시간" FROM DUAL ; SELECT TO_CHAR(SYSTIMESTAMP -1/24/60, 'RRRR-MM-DD HH24:MI:SS') "1분전시간" FROM DUAL ;
121
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 날짜 처리 함수(Date Functions)
▷ ADD_MONTHS(a, b) : ADD_MONTHS 함수는 a의 날짜에 b의 달을 더한 값을 반환 합니다. -- SYSDATE를 이용한 예제 SELECT TO_CHAR(ADD_MONTHS(SYSDATE,3),'RRRR-MM-DD') "date“ FROM DUAL; -- TIMESTAMP를 이용한 예제 SELECT TO_CHAR(ADD_MONTHS(SYSTIMESTAMP,3),'RRRR-MM-DD') "date" ▷ MONTH_BETWEEN(a1, a2) : MONTH_BETWEEN은 a1과 a2 사이의 달의 수를 NUMBER형 타입으로 반환 합니다. -- 두 일자 사이에 달의 수를 조회하는 예제 SELECT MONTHS_BETWEEN(TO_DATE(' ','RRRR-MM-DD') , TO_DATE(' ','RRRR-MM-DD')) "month" FROM DUAL; -- 두 일자 사이에 일짜 수를 조회하는 예제 SELECT TO_DATE(' ','RRRR-MM-DD') - TO_DATE(' ','RRRR-MM-DD') "Day" FROM DUAL
122
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 날짜 처리 함수(Date Functions)
▷ LAST_DAY(d) : LAST_DAY함수는 달의 마지막 날의 날짜를 반환합니다 -- LAST_DAY예제 SELECT SYSDATE today, LAST_DAY(SYSDATE) lastday FROM DUAL; ▷ ROUND(d[,F]) : ROUND 함수는 F에 지정된 단위로 반올림 합니다, F가 연도라면 연도 단위로 반올림 합니다. -- ROUND예제 SELECT TO_CHAR(ROUND(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), 'YEAR'), 'RRRR-MM-DD HH24:MI:SS') FROM DUAL; SELECT TO_CHAR(ROUND(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), 'MONTH'), 'RRRR-MM-DD HH24:MI:SS') SELECT TO_CHAR(ROUND(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), 'DD'), SELECT TO_CHAR(ROUND(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS')), 'RRRR-MM-DD HH24:MI:SS')
123
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 날짜 처리 함수(Date Functions)
▷ NEXT_DAY(d,c1) : NEXT_DAY는 돌아오는 명시된 요일의 일자를 반환합니다. (요일은 1(일) ~ 7(토)로 입력) -- NEXT_DAY예제 SELECT NEXT_DAY(SYSDATE, 4) "Next Wednesday“ FROM DUAL; SELECT NEXT_DAY(TO_DATE(' ','RRRRMMDD'), 2) "5월 첫째주 월요일" FROM DUAL; ▷ TRUNC(d,[F]) : TRUNC 함수는 F에 지정된 단위로 절삭 합니다. -- TRUNC예제 SELECT TO_CHAR(TRUNC(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), 'YEAR'), 'RRRR-MM-DD HH24:MI:SS') FROM DUAL; SELECT TO_CHAR(TRUNC(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), MONTH'), 'RRRR-MM-DD HH24:MI:SS') SELECT TO_CHAR(TRUNC(TO_DATE(' :00:01', 'RRRR-MM-DD HH24:MI:SS'), 'DD'), SELECT TO_CHAR(TRUNC(TO_DATE(' :00:01‘, 'RRRR-MM-DD HH24:MI:SS')), 'RRRR-MM-DD HH24:MI:SS')
124
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 변환 함수(Conversion Functions)
▷ TO_CHAR : TO_CHAR 함수는 DATE형, NUMBER형을 문자 타입으로 변환하는 함수입니다.. TO_CHAR(number), TO_CHAR(number, format), TO_CHAR(date, format) 형식으로 사용할 수 있습니다. ex) Number Format의 변환 예제 -- 콤마 예제 SELECT TO_CHAR( ,'999,999,999') comma FROM DUAL; -- 소숫점 예제 SELECT TO_CHAR( ,'999,999,999.99') period FROM DUAL; -- $ 표시 예제 SELECT TO_CHAR( ,'$999,999,999') dollar FROM DUAL; -- Local 화폐 표시 예제 (한국의 경우 ₩로 자동 변환 됨) SELECT TO_CHAR( ,'L999,999,999') local FROM DUAL; -- 왼쪽에 0을 삽입 SELECT TO_CHAR(123,'09999') zero FROM DUAL; -- 16진수로 변환 SELECT TO_CHAR(123,'XXXX') hexadecimal FROM DUAL; Format 예 설명 , (comma) 9,999 콤마 형식으로 변환 . (period) 99.99 소수점 형식으로 변환 09999 왼쪽에 0을 삽입 $ $9999 $ 통화로 표시 L L9999 Local 통화로 표시(한국의 경우 \) XXXX 16진수로 표시
125
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 변환 함수(Conversion Functions)
▷ Date Format의 변환 예제 -- 년,월,일,시,분,초 예제 SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') "sysdate“ FROM DUAL; -- 365일 중 몇 일째인지 조회 SELECT TO_CHAR(SYSDATE, 'DDD') "Day of year" FROM DUAL; -- 53주 중 몇 주차 인지 조회 SELECT TO_CHAR(SYSDATE, 'IW') "Week of year" FROM DUAL; -- 해당 월의 이름 조회 SELECT TO_CHAR(SYSDATE, 'MONTH') "Name of month" FROM DUAL; Format 설명 YYYY 4자리 연도 YY 두자리 연도 D Day of week (1-7) DAY 요일(월,화..) DD Day of month (1-31) DDD Day of year (1-366) MM 해당월을 01~12로 표시 MONTH Name of month WW Week of year (1-53) IW Week of year (1-53) 국제 표준 W Week of month (1-5) HH24 Hour of day (0-23) HH Hour of day (1-12) MI Minute (0-59) SS Second (0-59)
126
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 변환 함수(Conversion Functions)
▷ TO_DATE - TO_DATE 함수는 CHAR, VARCHAR2형을 DATE 타입으로 변환합니다. - TO_DATE(char, format) 형식으로 사용 할 수 있습니다. SELECT TO_DATE('2000/06/16','RRRR/MM/DD') FROM dual ; ▷ TO_NUMBER - TO_NUMBER 함수는 CHAR, VARCHAR2의 데이터 타입을 숫자형식으로 변환 합니다. - TO_ NUMBER(char) 형식으로 사용 할 수 있습니다. SELECT TO_NUMBER(' ') FROM DUAL;
127
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ NVL : NVL(컬럼 명|표현식, 대체할 값) - 첫번째 인자(컬럼 명 또는 표현식)가 NULL인 경우 두 번째 인자(대체할 값)로 바꾸어 RETURN하는 함수. - NULL은 어떠한 값과 연산을 해도 그 결과는 NULL이 됨을 유의합니다. - 대체할 값은 해당 컬럼의 데이터 타입과 동일해야 합니다. -- 매니저가 없는 값을 0으로 바꾸어서 출력하는 예제. SELECT EMPNO, NVL(MGR, 0) MGR FROM EMP WHERE DEPTNO = 10; ▷ NVL2 : NVL2(컬럼 명|표현식, NULL 값이 아닐 때의 대체할 값, NULL값일 때의 대체할 값) - 첫번째 인자(컬럼 명 또는 표현식)가 NULL이 아닌 경우 두 번째 인자의 값으로 대체하고, NULL인 경우에는 세 번째 인자의 값으로 대체합니다. - 대체할 값들은 해당 컬럼의 데이터 타입과 동일해야 합니다. -- 매니저가 있는경우 1을 없는경우 0을 출력하는 예제입니다. SELECT EMPNO, NVL2(MGR, 1, 0) MGR
128
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 실습
1) TEMP 테이블에서 취미(HOBBY) 가 NULL 이 아닌 사람의 성명(EMP_NAME)을 읽어오시오. 2) TEMP 테이블에서 취미(HOBBY) 가 NULL인 사람은 모두 취미(HOBBY)를 “없음” 이라고 값을 치환하여 가져오고 나머지는 그대로 값을 읽어오시오. 3) TEMP 의 자료 중 취미(HOBBY)의 값이 NULL 인 사원을 ‘등산’으로 치환했을 때 취미(HOBBY)가 ‘등산’ 인 사람의 성명을 가져오는 문장을 작성하시오.
129
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ NULLIF : NULLIF(컬럼 명|표현식, 컬럼 명|표현식) - 명시된 두 인자의 값을 비교하여 같으면 NULL값을 RETURN하고, 다를 경우엔 첫 번째 인자 값을 RETURN하는 함수입니다. SELECT E.EMP_NAME, M.EMP_NAME, NULLIF (SUBSTR(E.EMP_NAME,1,1), SUBSTR(M.EMP_NAME,1,1)) FROM EMP E JOIN EMP M ON (E.MANAGER_NO = M.EMP_NO); ▷ COALESCE : COALESCE(컬럼 명|표현식, 컬럼 명|표현식) - COALESCE(expr1,expr2,expr3,…) - expr1이 NULL이 아니면 expr1값을 그렇지 않으면 COALESCE(expr2,expr3,…)값을 반환합니다.. SELECT COALESCE(COMM,1), COMM FROM EMP;
130
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ DECODE : DECODE(컬럼 명|표현식, 조건1, 결과1, 조건2, 결과2, …, 디폴트 값) - 데이터를 원하는 다른 값으로 출력해주는 함수입니다. - 인자로 컬럼 또는 표현식으로 받은 후 값이 조건1에 해당하면 결과1이 출력되고 값이 조건2에 해당하면 결과2가 출력되는 식으로 사용되는 함수입니다. - 만일 어느 조건에도 해당하지 않으면 디폴트 값을 사용합니다. ex) DECODE 함수의 일반적인 예제 -- 부서번호가 10이면 ACCOUNTING, 20이면 RESEARCH, 30이면 SALES -- 나머지는 OPERATIONS를 출력하는 예제 SELECT DEPTNO, DECODE(DEPTNO, 10 , 'ACCOUNTING' , 20 , 'RESEARCH' , 30 , 'SALES', 'OPERATIONS') NAME FROM DEPT ex) DECODE 함수에서 집계 함수를 사용한 예제 -- 10부서는 급여합계를, 20부서는 최대값을, 30부서는 최소값을 출력하는 예제 SELECT DEPTNO, DECODE(DEPTNO, 10 , SUM(SAL), 20 , MAX(SAL), 30 , MIN(SAL)) SAL FROM EMP GROUP BY DEPTNO;
131
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ DECODE - DECODE함수는 집계함수와 함께 통계 데이터를 추출할 때 많이 사용합니다. ex) 부서별로 급여합계를 조회하는 예제 -- 부서별로 급여 합계를 출력합니다. SELECT deptno, NVL(SUM(DECODE(deptno, 10, sal)),0) deptno10, NVL(SUM(DECODE(deptno, 20, sal)),0) deptno20, NVL(SUM(DECODE(deptno, 30, sal)),0) deptno30, NVL(SUM(DECODE(deptno, 40, sal)),0) deptno40 FROM emp GROUP BY deptno; -- 부서별로 급여 합계를 행으로 출력합니다. SELECT d.deptno, NVL(SUM(e.sal),0) sal FROM emp e, dept d WHERE e.deptno(+) = d.deptno GROUP BY d.deptno; -- 부서별로 급여 합계를 열로 출력합니다. SELECT MAX(NVL(SUM(DECODE(deptno, 10, sal)),0)) deptno10, MAX(NVL(SUM(DECODE(deptno, 20, sal)),0)) deptno20, MAX(NVL(SUM(DECODE(deptno, 30, sal)),0)) deptno30, MAX(NVL(SUM(DECODE(deptno, 40, sal)),0)) deptno40 GROUP BY deptno;
132
SQL 기초 02 9. 내장 함수(Sing-Row Functions) ◈ 실습
1) LECTURE(강의) 테이블에서 LEC_ID(강의ID)별로 주당 강의 시간(LEC_TIME)과 학점(LEC_POINT)이 같으면 '일반’으로 표시되는 쿼리를 작성하시오. 2) LECTURE(강의) 테이블에서 주당강의시간과 학점이 같은 강의의 숫자를 구하시오. 3) 1의 결과에서 ‘일반’이 위로 오도록 정렬하시오. 4) 1의 결과에서 강의 시간과 학점이 다르면 NULL 이 리턴 되는 대신 '특별' 이라고 표시되게 쿼리를 작성하시오.
133
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ CASE : - CASE 함수는 DECODE함수가 제공하지 못하는 비교연산의 단점을 해결할 수 있는 함수입니다. - DECODE함수에서 비교연산을 수행하기 위해서는 GREATEST, LEAST등의 함수를 사용해야 하지만, CASE함수에서는 조건 연산자를 모두 사용 할 수 있습니다. - CASE함수는 IF.. THEN .. ELSE 구문과 비슷 합니다. WHEN절 다음에 여러 조건이 올 수 있습니다. -- DECODE예제를 CASE함수로 변환한 예 SELECT deptno, CASE deptno WHEN 10 THEN 'ACCOUNTING' WHEN 20 THEN 'RESEARCH' WHEN 30 THEN 'SALES' ELSE 'OPERATIONS' END as "Dept Name" FROM dept; --WHEN절 다음에 연산자가 오는 예 SELECT ename , CASE WHEN sal < 1000 THEN sal+(sal*0.8) WHEN sal BETWEEN 1000 AND 2000 THEN sal+(sal*0.5) WHEN sal BETWEEN 2001 AND 3000 THEN sal+(sal*0.3) ELSE sal+(sal*0.1) END sal FROM emp;
134
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ DUMP : DUMP는 바이트 크기와 해당 데이터 타입 코드를 반환합니다. SELECT ename, DUMP(ename, 16) "16진수" FROM emp WHERE ename = 'ALLEN' ename 16진수 ALLEN Typ=1 Len=5: 41,4c,4c,45,4e 만약에 16대신 8을 넣으면 8진수로, 10를 넣으면 10진수로 변환이 됩니다. 16, 10, 8, 17이 올 수 있는데요 17은 단일 문자열을 반환 합니다. Len은 ename의 해당 byte수 ▷ GREATEST : GREATEST함수는 검색값 중에서 가장 큰 값을 반환 합니다.. SELECT GREATEST(10, 100, 5, -7) FROM DUAL; GREATEST(10,100,5,-7) 가장 큰 수는 100 ▷ LEAST : LEAST함수는 GREATEST함수와 반대로 가장 작은 값을 반환합니다. SELECT LEAST(10, 100, 5, -7) FROM DUAL; LEAST(10,100,5,-7) -7
135
SQL 기초 02 9. 내장 함수(Sing-Row Functions)
◈ 기타 함수(Miscellaneous Single-Row Functions ) ▷ UID : 현재 사용자의 유일한 ID번호를 반환 합니다. SELECT USER, UID FROM DUAL; USER UID SCOTT ▷ USER : 현재 Oracle을 사용하는 사용자를 VARCHAR2형식으로 반환 합니다. ▷ USERENV : USERENV 함수는 현재 세션의 환경 정보를 반환합니다. SELECT USERENV('LANGUAGE') FROM DUAL; USERENV('LANGUAGE') KOREAN_KOREA.KO16KSC5601 ▷ ENTRYID : 사용 가능한 Auditing entry Identifier를 반환합니다. ▷ LABEL : 현재 세션의 Label을 반환합니다. ▷ LANGUAGE : 현재 세션에서 사용중인 언어와 테리토리 값을 반환합니다. ▷ SESSIONID : Auditing(감사) Session ID를 반환 합니다. ▷ TERMINAL : 현재 세션 터미널의 OS ID를 반환 합니다. ▷ VSIZE : 해당 문자의 BYTE수를 반환 합니다. 해당 문자가 NULL이면 NULL값이 반환 됩니다. SELECT VSIZE(ename), ename FROM emp WHERE deptno = 30; VSIZE(ENAME) ENAME 5 ALLEN 4 WARD 6 MARTIN
136
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ 그룹 함수란 ? ◈ 그룹 함수의 종류
▷ 그룹 함수란 여러 행 또는 테이블 전체의 행에 대해 함수가 적용되어 하나의 결과값을 가져오는 함수를 말합니다.. ▷ GROUP BY절을 이용하여 그룹 당 하나의 결과가 주어지도록 그룹화 할 수 있습니다. ▷ HAVING절을 사용하여 그룹 함수를 가지고 조건비교를 할 수 있습니다. ▷ COUNT(*)를 제외한 모든 그룹함수는 NULL값을 고려하지 않습니다. ▷ MIN, MAX 그룹함수는 모든 자료형에 대해서 사용 할 수 있습니다. ◈ 그룹 함수의 종류 ▷ COUNT : COUNT 함수는 검색된 행의 수를 반환합니다. SELECT COUNT(deptno) FROM DEPT ; ▷ MAX : MAX 함수는 컬럼중의 최대값을 반환합니다. SELECT MAX(sal) salary FROM emp ; ▷ MIN : MIN 함수는 컬럼 중의 최소값을 반환합니다. SELECT MIN(sal) salary FROM emp ;
137
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ 그룹 함수의 종류
▷ AVG : AVG 함수는 평균값을 반환합니다. SELECT ROUND(AVG(sal),1) salary FROM emp WHERE deptno = 30 ▷ SUM : SUM 함수는 검색된 컬럼의 합을 반환합니다. SELECT SUM(sal) salary FROM emp WHERE deptno = 30; ▷ STDDEV : STDDEV 함수는 표준편차를 반환합니다. SELECT ROUND(STDDEV(sal),3) salary FROM emp WHERE deptno = 30 ; Ex) 그룹함수 예 SELECT deptno 부서번호, COUNT(*) 사원수 , MAX(sal) 최대급여, MIN(sal) 최소급여 , SUM(sal) 급여합계, ROUND(AVG(sal)) 평균급여 FROM emp GROUP BY deptno ORDER BY SUM(sal) DESC;
138
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ GROUP BY
▷ 특정한 컬럼의 테이터 들을 다른 데이터들과 비교해 유일한 값에 따라 무리를 짓습니다. ▷ GROUP BY절을 사용하여 한 테이블의 행들을 원하는 그룹으로 나눕니다. ▷ Column명을 GROUP함수와 SELECT절에 사용하고자 하는 경우 GROUP BY뒤에 Column명을 추가 합니다. -- 부서별 사원수 조회 SELECT '2005년' year, deptno 부서번호, COUNT(*) 사원수 FROM emp GROUP BY deptno ORDER BY COUNT(*) DESC; -- 부서별로 그룹하여 부서번호, 인원수, 급여의 평균, 급여의 합을 조회하는 예제 SELECT deptno, COUNT(*), ROUND(AVG(sal)) "급여평균", ROUND(SUM(sal)) "급여합계" GROUP BY deptno; -- 업무별로 그룹하여 업무, 인원수, 평균 급여액, 최고 급여액, 최저 급여액 및 합계를 조회하는 예제 SELECT job, COUNT(empno) "인원수", AVG(sal) "평균급여액", MAX(sal) "최고급여액", MIN(sal) "최저급여액", SUM(sal) "급여합계" GROUP BY job;
139
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ 실습
1) TEMP(사원) 테이블에서 최고 연봉을 조회하시오 2) TEMP(사원) 테이블에서 직급(LEV)별로 최고 액 연봉을 조회하시오 3) TDEP 테이블의 자료를 이용해서 AREA 별로 최소 BOSS_ID를 골라내고 이 결과를 BOSS_ID 별로 정렬 하자. 4) TEMP(사원) 테이블의 ROW 수를 읽어 보자. 5) TEMP(사원) 테이블의 EMP_ID, HOBBY을 넣어서 COUNT문을 작성해 보시오. 6) 위 결과에서 직급별로 인원수를 세어보시오. 7) TEMP(사원) 테이블에서 직급(LEV)이 ‘과장’ 이면서 SALARY 가 이상인 사람의 수를 세어보자. 8) TEMP(사원) 테이블에서 직급(LEV)의 종류를 세어보자 9) TEMP(사원) 테이블에서 사번(EMP_ID)이 가장 빠른 값을 구하시오. 10) 위 결과에서 직급별로 가장 빠른 사번을 구하시오. 11) TEMP(사원) 테이블에서 직급 (LEV) 별 연봉(SALARY)의 합,평균,합/COUNT를 구하시오.
140
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ DISTINCT와 GROUP BY
▷ DISTINCT는 주로 UNIQUE(중복을 제거)한 컬럼이나 레코드를 조회하는 경우 사용합니다. GROUP BY는 데이터를 그룹핑해서 그 결과를 가져오는 경우 사용합니다. 하지만 두 작업은 조금만 생각해보면 동일한 형태의 작업이라는 것을 쉽게 알 수 있으며, 일부 작업의 경우 DISTINCT로 동시에 GROUP BY로도 처리될 수 있는 쿼리들이 있습니다. -- DISTINCT를 사용한 중복 데이터 제거 SELECT DISTINCT deptno FROM emp; -- GROUP BY를 사용한 중복 데이터 제거 SELECT deptno FROM emp GROUP BY deptno; ▷ 집계함수를 사용하여 특정 그룹으로 구분 할 때는GROUP BY 절을 사용하며, 특정 그룹 구분없이 중복된 데이터를 제거할 경우에는 DISTINCT 절을 사용 -- 아래와 같은 기능은 DISTINCT를 사용하는 것이 훨씬 효율적 SELECT COUNT(DISTINCT d.deptno) "중복제거 수", COUNT(d.deptno) "전체 수" FROM emp e, dept d WHERE e.deptno = d.deptno; -- 집계 함수가 필요한 경우는 GROUP BY를 사용 SELECT deptno, MIN(sal) FROM emp GROUP BY deptno;
141
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ GROUP BY의 HAVING 절
▷ WHERE절에 GROUP Function을 사용할 수 없습니다. ▷ HAVING절은 GRUOP 함수를 가지고 조건비교를 할 때 사용 합니다. ▷ WHERE → GRUOP BY → HAVING → ORDER BY순으로 쿼리문이 와야 됩니다. -- 사원수가 5명이 넘는 부서의 부서명과 사원수 조회 SELECT b.dname, COUNT(a.empno) FROM emp a, dept b WHERE a.deptno = b.deptno GROUP BY dname HAVING COUNT(a.empno) > 5 -- 전체 월급이 5000을 초과하는 각 업무에 대해서 업무와 월급여 합계를 조회 단 판매원은 제외하고 월 급여 합계로 내림차순 정렬 SELECT job, SUM(sal) "급여합계“ FROM emp WHERE job NOT IN ('SALES') 판매원은 제외 GROUP BY job 업무별로 Group By HAVING SUM(sal) > 전체 월급이 5000을 초과하는 ORDER BY SUM(sal) DESC; 월급여 합계로 내림차순 정렬
142
SQL 기초 02 10. 그룹 함수(Group Functions) ◈ 실습
1) TEMP(사원) 테이블에서 평균 연봉이 5천만원 이상인 경우의 직급(LEV)별 평균 연봉(SALARY)을 구하시오. ( HAVING 이용) 2) TEMP(사원) 테이블에서 직급별로 사번이 제일 늦은 사람을 구하고 그 결과 내에서 사번이 1997로 시작하는 결과만 보여 주시오. ( HAVING 이용)
143
SQL 기초 02 11. 서브쿼리(Subquery) ◈ Subquery란 ? ◈ Guidelines ◈ Subquery종류
▷ SUBQUERY는 다른 하나의 SQL 문장의 절에 NESTEDED된 SELECT 문장 입니다. ▷ SELECT, UPDATE, DELETE, INSERT와 같은 DML문과 CREATE TABLE 또는 VIEW에서 이용 될 수 있습니다. ▷ 알려지지 않은 조건에 근거한 값들을 검색하는 SELECT 문장을 작성하는데 유용 합니다. ▷ SUBQUERY는 MAIN QUERY가 실행되기 이전에 한번 실행 됩니다. ◈ Guidelines ▷ SUBQUERY는 괄호로 묶어야 합니다. ▷ SUBQUERY는 연산자의 오른쪽에 나타나야 합니다. ▷ 두 종류의 비교 연산자들이 SUBQUERY에 사용 됩니다. - 단일 행 연산자(=,>, >=, <, <=, <>, !=) - 복수 행 연산자(IN, NOT IN, ANY, ALL, EXISTS) ◈ Subquery종류 ▷ 단일 행(Sing-Row) 서브쿼리 : SELECT문장으로부터 오직 하나의 행만을 검색하는 질의입니다 ▷ 다중 행(Multiple-Row) 서브쿼리 : SELECT문장으로부터 하나 이상의 행을 검색하는 질의입니다 ▷ 다중 열(Multiple-Column) 서브쿼리 : SELECT문장으로부터 하나 이상의 컬럼을 검색하는 질의입니다 ▷ FROM절상의 서브쿼리(INLINE VIEW) : FROM절상에 오는 서브쿼리로 VIEW처럼 작용 합니다. ▷ 상관관계 서브 쿼리 : 바깥쪽 쿼리의 컬럼 중의 하나가 안쪽 서브쿼리의 조건에 이용되는 처리 방식 입니다.
144
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 단일 행(Sing-Row) 서브쿼리
▷ 오직 한개의 행(값)을 반환 합니다.(Return only one row) ▷ 단일 행 연산자(=,>, >=, <, <=, <>, !=) 만 사용 할 수 있습니다. SELECT ename,job FROM emp WHERE job = (SELECT job FROM emp WHERE empno = 7369); 위의 서브쿼리를 실행 시키면. 오른쪽의 그림처럼. empno가 7369인 job을 먼저 검색하고.. job이 'CLERK'인 사원의 이름과 직업을 반환 합니다.
145
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 다중 행(Multiple-Row) 서브쿼리 ◈ IN 연산자의 사용 예제
▷ 하나 이상의 행을 RETURN하는 SUBQUERY를 다중 행 SUBQUERY라고 합니다. ▷ 복수 행 연산자(IN, NOT IN, ANY, ALL, EXISTS)를 사용 할 수 있습니다. ◈ IN 연산자의 사용 예제 ▷ IN 연산자는 하나의 컬럼이 여러개의 '=' 조건을 가지는 경우에 사용 -- 부서별로 가장 급여를 많이 받는 사원의 정보를 출력하는 예제 SELECT empno, ename, sal, deptno FROM emp WHERE sal IN ( SELECT MAX(sal) GROUP BY deptno ); ◈ ANY 연산자의 사용 예제 ▷ ANY연산자는 서브쿼리의 결과값중 어느 하나의 값이라도 만족이 되면 결과값을 반환 합니다. -- SALESMAN 직업의 급여보다 많이 받는 사원의 사원명과 급여 정보를 출력하는 예제 SELECT ename, sal FROM emp WHERE deptno != 20 AND sal > ANY( SELECT sal WHERE job='SALESMAN');
146
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 실습
1) TEMP에서 연봉이 가장 많은 직원의 ROW를 찾아서 이 금액과 동일한 금액을 받는 직원의 사번과 성명을 구하세요. 2) TEMP의 자료를 이용해 SALARY의 평균을 구하고 이보다 큰 금액을 SALARY로 받는 직원의 사번과,성명,연봉을 구하세요. 3) TEMP의 직원 중 인천에 근무하는 직원의 사번과 성명을 읽어오는 SQL을 SUB QUERY 를 이용해 만들어 보시오. 이때 부서가 위치하는 있는 AREA 가 근무지가 된다. 4) TCOM에 연봉 외에 COMMISSION을 받는 직원의 사번이 보관되어 있다. 이 정보를 SUB QUERY로 SELECT 하여 부서 명칭별로 COMMISSION 을 받는 인원수를 세는 문장을 만들어 보시오.
147
SQL 기초 02 11. 서브쿼리(Subquery) ◈ ALL 연산자의 사용 예제 ◈ EXISTS 연산자의 사용 예제
-- 모든 SALESMAN직업의 급여보다 많이받는 사원의 사원명과 급여정보를 출력하는예제 SELECT ename, sal FROM emp WHERE deptno != 20 AND sal > ALL ( SELECT sal FROM emp WHERE job='SALESMAN'); ◈ EXISTS 연산자의 사용 예제 ▷ EXISTS 연산자를 사용하면 서브쿼리의 데이터가 존재하는가의 여부를 먼저 따져 존재하는 값들만을 결과로 반환해 줍니다. ▷ SUBQUERY에서 적어도 1개의 행을 RETURN하면 논리식은 참이고 그렇지 않으면 거짓 입니다. -- 아래 예처럼 emp 테이블을 통해 사원들이 속한 부서번호의 정보만 조회하는 경우 추출하고자 하는 대상은 dept 테이블이지만 emp 테이블과 조인하여 부서번호를 체크해야 합니다. -- 두 테이블의 관계가 1 : M 이므로 불필요하게 EMP 테이블을 모두 액세스하고 DISTINCT로 중복 제거를 합니다. SELECT DISTINCT d.deptno, d.dname FROM dept d, emp e WHERE d.deptno = e.deptno; -- EXISTS를 사용하는 Subquery로 변경 추출하고자 하는 대상만을 FROM절에 놓고 emp테이블은 체크만 하기위해 EXISTS절에 위치시켰으며 이로 인해 수행속도가 대폭 감소하게 됩니다. SELECT d.deptno, d.dname FROM dept d WHERE EXISTS (SELECT 1 FROM emp e WHERE e.deptno = d.deptno);
148
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 다중 열(Multiple-Column) 서브쿼리
▷ 다중 열 서브쿼리란 서브쿼리의 결과값이 두개 이상의 컬럼을 반환하는 서브쿼리 입니다. ◈ Pairwise(쌍비교) Subquery ▷ 서브쿼리가 한번 실행되면서 모든 조건을 검색해서 주 쿼리로 넘겨 줍니다. ex) SELECT empno, sal, deptno FROM emp WHERE (sal, deptno) IN ( SELECT sal, deptno WHERE deptno = 30 AND comm is NOT NULL ); EMPNO SAL DEPTNO ◈ Nonpairwise(비쌍비교) Subquery ▷ 서브쿼리가 여러 조건별로 사용 되어서 결과값을 주 쿼리로 넘겨 줍니다. ex) SELECT empno, sal, deptno FROM emp WHERE sal IN ( SELECT sal WHERE deptno = 30 AND comm is NOT NULL ) AND deptno IN ( SELECT deptno AND comm is NOT NULL ); EMPNO SAL DEPTNO ◈ Null Values in a Subquery ▷ 서브쿼리에서 null값이 반환되면 주 쿼리 에서는 어떠한 행도 반환되지 않습니다
149
SQL 기초 02 11. 서브쿼리(Subquery) ◈ FROM절상의 서브쿼리(INLINE VIEW)
▷ SUBQUERY는 FROM절에서도 사용이 가능 합니다. ▷ INLINE VIEW란 FROM절상에 오는 서브쿼리로 VIEW처럼 작용 합니다. 예제)급여가 20부서의 평균 급여보다 크고 사원을 관리하는 사원으로서 20부서에 속하지 않은 사원의 정보를 보여주는 SQL문 입니다. SELECT b.empno,b.ename,b.job,b.sal, b.deptno FROM (SELECT empno FROM emp WHERE sal >(SELECT AVG(sal) FROM emp WHERE deptno = 20)) a, emp b WHERE a.empno = b.empno AND b.mgr is NOT NULL AND b.deptno != 20 EMPNO ENAME JOB SAL DEPTNO BLAKE MANAGER CLARK MANAGER ◈ 상관관계 서브쿼리 ▷ 상관관계 서브쿼리란 바깥쪽 쿼리의 컬럼 중의 하나가 안쪽 서브쿼리의 조건에 이용되는 처리 방식 입니다. ▷ 이는 주 쿼리에서 서브 쿼리를 참조하고 이 값을 다시 주 쿼리로 반환한다는 것입니다. 예제) 사원을 관리할 수 있는 사원의 평균급여보다 급여를 많이 받는 사원의 정보를 출력 SELECT empno, ename, sal FROM emp e WHERE sal > (SELECT AVG(sal) sal FROM emp WHERE e.empno = mgr) EMPNO ENAME SAL BLAKE CLARK SCOTT KING FORD
150
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 실습
1) TDEPT에서 부서코드와 BOSS_ID를 읽어서, 이 두개의 컬럼이 TEMP의 부서코드와 사번에 일치하는 사람의 사번과 성명을 읽어오는 쿼리를 만들어 보시오. 2) TEMP에서 부서별 최고 연봉금액을 읽어서,해당 부서와 최고 연봉금액이 동시에 일치하는 사원의 사번, 성명, 연봉을 구하시오. 3) 서브쿼리를 통해 LEV = ‘과장’ 인 직원의 SALARY를 TEMP 에서 읽고 이중의 어떤 값 하나 보다 큰 연봉을 가진 직원의사번, 성명, 연봉을 읽어 오는 쿼리를 만들어 보시오. ( ANY 사용 ) 4) 위3번 문제를 EXISTS를 사용하여 작성해 보시오.
151
SQL 기초 02 11. 서브쿼리(Subquery) ◈ WITH절 ▷ 여러 개의 서브 쿼리가 메인 쿼리에서 사용될 때 생기는
복잡성을 보다 간결하게 정의해 사용함으로써 가독성이 높고 아울러 성능 저하 현상을 최소화할 수 있습니다. ▷ WITH 절을 이용한 쿼리 작성 정리 1. 먼저 메인 쿼리에 정의될 서브 쿼리를 WITH절과 함께 선언합니다. 2. 각각의 서브 쿼리를 대신할 인 라인 뷰의 이름을 정의 합니다. 3. 만일 어떤 서브 쿼리가 다른 서브 쿼리를 참조할 경우 순서가 매우 중요합니다. 반드시 참조되는 인 라인 뷰가 먼저 선언되어 있어야 합니다. 4. 서브 쿼리 선언 후 메인 쿼리를 작성 합니다. 5. 메인 쿼리에서 WITH절에 미리 선언해 놓은 인 라인 뷰의 이름을 사용하여 서브 쿼리를 작성하여 사용합니다. ▷ WITH dept_cost AS ( SELECT dept_name,SUM(pay) AS dept_total FROM emp GROUP BY dept_name ) , avg_cost AS ( SELECT SUM(dept_total) / COUNT(*) AS dept_avg FROM dept_cost SELECT * FROM dept_cost WHERE dept_total >= (SELECT dept_avg FROM avg_cost) ORDER BY dept_name;
152
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 집합 쿼리(UNION, INTERSECT, MINUS) ◈ UNION
▷ 집합 연산자를 사용시 집합을 구성할 컬러의 데이터 타입이 동일해야 합니다. ▷ UNION : 합집합 ▷ UNION ALL : 공통원소 두번 씩 다 포함한 합집합 ▷ INTERSECT : 교집합 ▷ MINUS : 차집합 ◈ UNION ▷ UNION은 두 테이블의 결합을 나타내며, 결합시키는 두 테이블의 중복되지 않은 값들을 반환 합니다. SELECT deptno FROM emp UNION SELECT deptno FROM dept; DEPTNO 10 20 30 40 ◈ UNION ALL ▷ UNION과 같으나 두 테이블의 중복되는 값까지 반환 합니다. SELECT deptno FROM emp UNION ALL SELECT deptno FROM dept; DEPTNO 20 30 10 ....
153
SQL 기초 02 11. 서브쿼리(Subquery) ◈ INTERSECT ▷ INTERSECT는 두 행의 집합 중 공통된 행을
반환 합니다. SELECT deptno FROM emp INTERSECT SELECT deptno FROM dept; DEPTNO 10 20 30 ◈ MINUS ▷ MINUS는 첫 번째 SELECT문에 의해 반환되는 행 중에서 두 번째 SELECT문에 의해 반환되는 행에 존재하지 않는 행들을 보여 줍니다. SELECT deptno FROM dept MINUS SELECT deptno FROM emp; DEPTNO 40
154
SQL 기초 02 11. 서브쿼리(Subquery) ◈ 실습
1) TEMP테이블과 TCOM테이블의 EMP_ID를 UNION 해 보시오. 2) TEMP테이블의 EMP_ID,EMP_NAME와 TCOM테이블의 EMP_ID,BONUS_RATE를 UNION 해 보시오. 3) UNION을 이용해서 TEMP테이블과 TCOM테이블의 자료 중 EMP_ID, SALARY, COMM 을 보여주는 SQL 을 만들어 보시오. 4) TEMP테이블과 TCOM테이블의 EMP_ID를 UNION ALL 해 보시오. 5) 위 결과를 ORDER BY 해 보시오. 6) TEMP테이블과 TCOM테이블의 EMP_ID를 교집합을 만들어 보시오. 7) TEMP테이블에 사번(EMP_ID)에서 TCOM테이블에 존재하는 사번을 제외해 보시오.
155
SQL 기초 02 12. 데이터 사전(Data Dictionary) ◈ 데이터 사전(Data Dictionary) 이란 ?
데이터베이스 전반에 대한 정보를 제공 합니다. ▷ 데이터 사전에 저장되는 내용은 아래와 같습니다. - Oracle의 사용자 이름 - Oracle 권한과 롤 - 데이터베이스 스키마 객체(Table, View, index, cluster, Synonym, Sequence..) 이름과 정의들 - 무결성제약 조건에 관한 정보 - 데이터베이스의 구조 정보 - Oracle 데이터베이스의 함수 와 Prucedure 및 Triger에 대한 정보 - 기타 일반적인 DataBase 정보 들이 있습니다. ▷ Oracle 사용자 SYS는 Data Dictionary의 모든 기본 Table과 View를 소유 합니다. ▷ Oracle은 DDL 명령이 실행 될때 마다 Data Dictionary를 Access 합니다. ▷ 모든 Oracle 사용자는 DB정보에 대한 읽기 전용 참조로 Data Dictionary 사용할 수 있습니다. ▷ DB작업동안 Oracle은 Data Dictionary를 읽어 개체의 존재여부와 사용자에게 적합한 Access 권한이 있는지를 확인 합니다. 또한 Oracle은 Data Dictionary를 계속 갱신하여 DataBase 구조, 감사, 사용자권한, 데이터등의 변경사항을 반영 합니다. ▷ 데이터 사전 테이블은 아래의 스크립트를 실행시켜서도 생성할 수 있습니다. ==> 기본 데이터사전 테이블 생성 스크립트 ==> 자주 사용되는 데이터사전 뷰 생성 스크립트
156
SQL 기초 02 12. 데이터 사전(Data Dictionary) ◈ User_XXXX View ◈ ALL_XXXX View
▷ 한 특정 사용자에게 종속되어 있고, 그 사용자가 조회 가능한 데이터 사전 뷰들 입니다. ▷ ALL_XXXX View의 모든 정보의 부분 집합 입니다. ▷ Public Synonym을 가질 수 있습니다. 아래의 예는 Scott 사용자의 Table 조회 결과 입니다. SELECT table_name, tablespace_name FROM USER_TABLES; TABLE_NAME TABLESPACE_NAME BONUS TOOLS DEPT TOOLS DUMMY TOOLS ◈ ALL_XXXX View ▷ 한 특정 사용자가 조회 가능한 모든 데이터사전 뷰를 의미 합니다. ▷ 자신이 조회하려는 객체의 주인이 아니더라도 그 객체에 접근 할 수 있는 권한을 가지고 있다면 ALL_XXX 뷰를 통하여 조회가 가능 합니다. SELECT table_name, tablespace_name FROM ALL_TABLES; DUAL SYSTEM SYSTEM_PRIVILEGE_MAP SYSTEM TABLE_PRIVILEGE_MAP SYSTEM DEPT TEST DUMMY TEST
157
SQL 기초 02 12. 데이터 사전(Data Dictionary) ◈ DBA_XXXX View
모든 Oracle 데이터베이스 객체에 대한 정보를 보여 줍니다. ▷ SELECT ANY TABLE 권한이 있는 사용자 또한 질의가 가능 합니다. ▷ 이러한 View에 대한 동의어는 생성되지 않으며, 다른 사용자가 질의 하려면 앞에 sys.이라는 접두어를 붙여야 합니다. ex) SELECT OWNER, OBJECT_NAME FROM SYS.DBA_OBJECTS;
158
SQL 기초 02 13. Oracle 객체 ◈ 인덱스(Index)
원하는 레코드를 빠르게 찾아갈 수 있도록 만들어진 데이터 구조입니다. ▷ 자동 인덱스 : 프라이머리 키 또는 uinque 제한 규칙에 의해 자동적으로 생성되는 인덱스 입니다. ▷ 수동 인덱스 : CREATE INDEX 명령을 실행해서 만드는 인덱스들 입니다. ◈ Index를 생성하는 것이 좋은 Column ① WHERE절이나 join조건 안에서 자주 사용되는 컬럼 ② null 값이 많이 포함되어 있는 컬럼 ③ WHERE절이나 join조건에서 자주 사용되는 두 개 이상의 컬럼들 ▷ 다음과 같은 경우에는 index 생성이 불필요 합니다. ① table이 작을 때 ③ 테이블이 자주 갱신될 때 ※ Oracle 인덱스는 B-tree(binary search tree)에 대한 원리를 기반으로 하고 있습니다. B-tree인덱스는 컬럼안에 독특한 데이터가 많을 때 가장 좋은 효과를 냅니다. 이 알고리즘 원리는 ① 주어진 값을 리스트의 중간점에 있는 값과 비교합니다. 만약 그 값이 더 크면 리스트의 아래쪽 반을 버립니다. 만약 그 값이 더 작다면 위쪽 반을 버립니다. ② 하나의 값이 발견될 때 까지 또는 리스트가 끝날 때까지 그와 같은 작업을 다른 반쪽에도 반복합니다.
159
SQL 기초 02 13. Oracle 객체 ◈ Unique 인덱스
▷ 프라이머리키 와 Unique 제약 조건 시 생성되는 인덱스는 Unique 인덱스입니다. CREATE UNIQUE INDEX emp_ename_indx ON emp(ename); ◈ Non-Unique 인덱스 ▷ Non-Unique 인덱스는 인덱스를 사용한 컬럼에 중복 데이터 값을 가질 수 있습니다. CREATE INDEX dept_dname_indx ON dept(dname);
160
SQL 기초 02 13. Oracle 객체 ◈ 결합 (Concatenated(=Composite)) 인덱스
▷ 복수개의 컬럼에 생성할 수 있으며 복수키 인덱스가 가질수 있는 최대 컬럼값은 16개입니다 CREATE UNIQUE INDEX emp_empno_ename_indx ON emp(empno, ename); ◈ 인덱스의 삭제 ▷ 인덱스의 구조는 테이블과 독립적이므로 인덱스의 삭제는 테이블의 데이터에는 아무런 영향도 미치지 않습니다. ▷ 인덱스를 삭제하려면 INDEX의 소유자이거나 DROP ANY INDEX권한을 가지고 있어야 합니다. ▷ INDEX는 ALTER를 할 수 없습니다. DROP INDEX emp_empno_ename_indx ; ※ 인덱스에 대한 정보는 USER_INDEXES 뷰 또는 USER_IND_COLUMNS 뷰를 통해 검색할 수 있습니다. SELECT index_name , index_type FROM USER_INDEXES WHERE table_name='EMP'; INDEX_NAME INDEX_TYPE EMP_DEPTNO_INDX BITMAP EMP_PK_EMPNO NORMAL
161
SQL 기초 02 13. Oracle 객체 ◈ 뷰 란? ▷ 뷰는 하나의 가상 테이블이라 생각 하시면 됩니다. ▷ 뷰는 실제 데이터가 저장 되는 것은 아니지만 뷰를 통해 데이터를 관리 할 수 있습니다. ▷ 뷰는 복잡한query를 통해 얻을 수 있는 결과를 간단한 query를 써서 구할 수 있게 합니다. ▷ 한개의 뷰로 여러 테이블에 대한 데이터를 검색할 수 있습니다. ▷ 특정 평가기준에 따른 사용자 별로 다른 데이터를 액세스할 수 있도록 합니다. ◈ 뷰의 제한 조건 ▷ 테이블에 NOT NULL로 만든 컬럼들이. 뷰에 다 포함이 되 있어야 됩니다. ▷ 그리고 ROWID, ROWNUM, NEXTVAL, CURRVAL등과 같은 가상 컬럼에 대한 참조를 포함하고 있는 뷰 에는 어떤 데이터도 Insert할 수 없습니다. ▷ WITH READ ONLY 옵션을 설정한 뷰도 데이터를 갱신할 수 없습니다. ▷ WITH CHECK OPTION을 설정한 뷰는 뷰의 조건에 해당되는 데이터만 삽입, 삭제, 수정을 할 수 있습니다.
162
SQL 기초 02 13. Oracle 객체 ◈ 뷰 생성 문법 - FORCE : 기본 테이블 유무에 관계없이 VIEW를 생성 - WITH CHECK OPTION : VIEW에 의해 엑세스될 수 있는 행만이 입력되거나 변경될 수 있음을 지정 합니다. - WITH READ ONLY : SELECT만 가능한 VIEW의 생성 - 함수를 사용한 컬럼은 반드시 ALIAS를 지정해야 합니다. CTEATE [OR REPLACE] [FORCE | NOFORCE] VIEW view_name AS subquery [WITH CHECK OPTION [CONSTRAINT 제약조건]] [WITH READ ONLY] CREATE OR REPLACE VIEW Name_Query AS SELECT a.ename, b.dname FROM emp a, dept b WHERE a.deptno = b.deptno AND b.deptno = 20 이렇게 뷰를 생성해 놓고 뷰를 통해 검색을 하면 됩니다. SELECT * FROM Name_Query; ENAME DNAME SMITH RESEARCH JONES RESEARCH
163
SQL 기초 02 13. Oracle 객체 ◈ WITH CHECK OPTION ◈ WITH READ ONLY
▷ view 의 조건식을 만족하는 데이터만 INSERT 또는 UPDATE가 가능하도록 하는 옵션 입니다. CREATE OR REPLACE VIEW Check_Option AS SELECT empno, ename, deptno FROM emp WHERE deptno = 10 WITH CHECK OPTION INSERT INTO Check_Option(empno, ename, deptno) VALUES (10005, 'jain', 30); * 1행에 오류: ORA-01402: 뷰의 WITH CHECK OPTION의 조건에 위배 됩니다 부서 번호가 10인 사원만 INSERT, UPDATE할 수 있습니다. ◈ WITH READ ONLY ▷ SELECT만 가능한 VIEW를 생성 합니다. CREATE OR REPLACE VIEW Read_Only AS SELECT empno, ename, deptno FROM emp WHERE deptno = 10 WITH READ ONLY view created. 단순히 읽기 만 할 수 있고 데이터는 입력하지 못합니다. ▷ 뷰의 정보 조회 : USER_VIEWS 데이터 사전을 통해서 뷰에 대한 정보를 조회 할 수 있습니다. SELECT view_name , text FROM USER_VIEWS; ◈ 뷰의 삭제 DROP VIEW Read_Only; view dropped.
164
SQL 기초 02 13. Oracle 객체 ◈ SEQUENCE(시퀀스)
▷ 유일(UNIQUE)한 값을 생성해주는 Oracle 객체입니다. ▷ 시퀀스를 생성하면 기본 키와 같이 순차적으로 증가하는 컬럼을 자동적으로 생성할 수 있습니다. ▷ 보통 primary key 값을 생성하기 위해 사용합니다. ▷ 메모리에 Cache되었을 때 Sequence 값의 액세스 효율이 증가 합니다. ▷ Sequence는 테이블과는 독립적으로 저장되고 생성됩니다. 따라서 하나의 sequence를 여러 테이블에서 쓸 수 있습니다. ◈ SEQUENCE(시퀀스) ▷ START WITH : 시퀀스의 시작 값을 지정합니다. n을 1로 지정하면 1부터 순차적으로 시퀀스번호가 증가 합니다. ▷ INCREMENT BY : 시퀀스의 증가 값을 말합니다. n을 2로 하면 2씩 증가합니다. START WITH를 1로 하고 INCREMENT BY를 2으로 하면 1, 3,5,7,.. 이렇게 시퀀스 번호가 증가하게 됩니다. ▷ MAXVALUE n | NOMAXVALUE : MAXVALUE는 시퀀스가 증가할수 있는 최대값을 말합니다 NOMAXVALUE는 시퀀스의 값을 무한대로 지정합니다. ▷ MINVALUE n | NOMINVALUE : MINVALUE는 시퀀스의 최소값을 지정 합니다. 기본값은 1이며, NOMINVALUE를 지정할 경우 최소값은 무한대가 됩니다 CREATE SEQUENCE sequence_name [START WITH n] [INCREMENT BY n] [MAXVALUE n | NOMAXVALUE] [MINVALUE n | NOMINVALUE] [CYCLE | NOCYCLE]
165
SQL 기초 02 13. Oracle 객체 CREATE SEQUENCE emp_seq START WITH 1
INCREMENT BY 1 MAXVALUE ; 시작 값이 1일고 1씩 증가하고, 최대값이 만이 되는 시퀀스를 생성했습니다. INSERT INTO emp(empno, ename, hiredate ) VALUES(emp_seq.NEXTVAL, 'julia' , sysdate); empno는 컬럼값을 입력할 때 일일이 다음 값을 기억하지 않아도 NEXTVAL을 사용하여 자동으로 입력할 수 있습니다. - CURRVAL : 현재 값을 반환 합니다. . - NEXTVAL : 현재 시퀀스값의 다음 값을 반환 합니다. SELECT emp_seq.CURRVAL FROM DUAL ; SELECT emp_seq.NEXTVAL FROM DUAL ; CURRVAL NEXTVAL ◈ 시퀀스 사용 규칙 ▷ NEXTVAL, CURRVAL을 사용할 수 있는 경우 - subquery가 아닌 select문 insert문의 select절 - insert문의 value절 update문의 set절 ▷ NEXTVAL, CURRVAL을 사용할 수 없는 경우 - view의 select절 distinct 키워드가 있는 select문 - group by, having, order by절이 있는 select문 select, delete, update의 subquery - create table, alter table 명령의 default값
166
SQL 기초 02 13. Oracle 객체 ◈ 시퀀스의 수정 및 삭제 ALTER SEQUENCE sequence_name
START WITH는 수정할 수 없습니다. ▷ START WITH 절이 없다는 점을 빼고는 CREATE SEQUENCE와 같습니다. ALTER SEQUENCE emp_seq INCREMENT BY 2 CYCLE; 2씩 증가하고, 최대값을 넘으면 다시 처음부터 순환하도록 수정하였습니다. ▷ DROP 문으로 필요하지 않은 시퀀스는 삭제 할 수 있습니다. DROP SEQUENCE PRD_SEQ; sequence dropped. ALTER SEQUENCE sequence_name [INCREMENT BY n] [MAXVALUE n | NOMAXVALUE] [MINVALUE n | NOMINVALUE] [CYCLE | NOCYCLE]
167
SQL 기초 02 13. Oracle 객체 ◈ SYNONYM(동의어)
▷ Synonym 은 Oracle 객체(테이블, 뷰, 시퀀스, 프로시저)에 대한 대체이름(Alias)를 말합니다. ▷ Synonym은 실질적으로 그 자체가 Object가 아니라 Object에 대한 직접적인 참조 입니다. ▷ Synonym 을 사용하는 이유 ① 데이터베이스의 투명성을 제공하기 위해서 사용 한다고 생각하면 됩니다. Synonym 은 다른 유저의 객체를 참조할 때 많이 사용을 합니다. ② 만약에 다른 유저의 객체를 참조할 경우가 있을 때 Synonym 을 생성해서 사용을 하면은 추후에 참조하고 있는 Object가 이름을 바꾸거나 이동할 경우 객체를 사용하는 SQL문을 모두 다시 고치는 것이 아니라 Synonym만 다시 정의하면 되기 때문에 매우 편리 합니다. ③ 객체의 긴 이름을 사용하기 편한 짧은 이름으로 해서 SQL코딩을 단순화 시킬 수 있습니다. ④ 또한 객체를 참조하는 사용자의 오브젝트를 감출 수 있기 때문에 이에 대한 보안을 유지할 수 있습니다. Synonym 을 사용하는 유저는 참조하고 있는 객체에 대한 사용자의 object의 소유자, 이름, 서버이름을 모르고 Synonym 이름만 알아도 사용 할 수 있습니다.
168
SQL 기초 02 13. Oracle 객체 ◈ SYNONYM 사용 이유
▷ 오브젝트의 실제 이름과 소유자 그리고 위치를 감춤으로써 database 보안을 개선하는데 사용 됩니다 ▷ Object에의 Public Access를 제공 합니다. ▷ Remote Database의 Table, View, Program Unit를 위해 투명성을 제공 합니다. ▷ Database 사용자를 위해 SQL 문을 단순화 할 수 있습니다. ◈ SYNONYM 종류 ▷ Private Synonym : 전용 Synonym은 특정 사용자만 이용할 수 있습니다. ▷ Public Synonym : 공용 Synonym은 공용 사용자 그룹이 소유하며 그 Database에 있는 모든 사용자가 공유 합니다.
169
SQL 기초 02 13. Oracle 객체 ◈ SYNONYM 생성 문법
▷ scott USER의 emp테이블을 test USER가 사용 하는 예제. 1. 먼저 scott/tiger USER로 접속해서 test USER에게 emp테이블을 조작할 권한을 부여합니다. GRANT ALL ON emp TO test; test user에 대하여 scott의 emp테이블을 조작할 수 있는 권한을 부여합니다. 2. test USER로 접속해 동의어를 생성합니다. connect test/test CREATE SYNONYM scott_emp FOR scott.emp ; scott USER가 소유하고 있는 emp 테이블에 대해 scott_emp라는 일반 Synonym 을 생성했습니다. scott 사용자의 emp테이블을 test 사용자가 scitt_emp라는 동의어로 사용 합니다. . ▷ Synonym 을 이용한 쿼리 일반 테이블을 쿼리 SELECT empno, ename FROM scott_emp; SELECT empno, ename FROM scott.emp; 이 두 쿼리의 결과는 같습니다. 동의어 삭제 DROP SYNONYM scott_emp CREATE [PUBLIC] SYSNONYM sysnonym_name FOR object_name
170
SQL 기초 02 13. 기타 ◈ ROWNUM ▷ ROWNUM 은 WHERE(WHERE 절이 없으면 FROM) 절에 의해 추출된 DATA SET 에 ROW단위로 붙는 순번입니다. ▷ 자료의 순서를 다른 목적으로 이용하고자 할 때 유용하게 쓰이는 정보이기도 합니다. ▷ WHERE 절에 ROWNUM 을 조건으로 줄때는 항상 다른 조건을 모두 만족시킨 결과에 대해 조건이 반영 됩니다. 즉 ROWNUM 이란 WHERE 까지를 만족시킨 자료에 붙는 순번이라고 할 수 있습니다. 이러한 이유로 ORDER BY 가 추가되면 ROWNUM까지 하나의 RECORD내의 COLUMN 으로 인식되어 정렬이 일어 납니다.
171
SQL 기초 02 13. 기타 ◈ 실습 1) TEMP테이블에서 수습사원의 사원번호 사원명을 구하는데 ROWNUM을 이용하여 순번을 붙여 보시오. 2) 위 결과값을 ROWNUM을 이용하여 5개만 출력 하시오. 3) 1번의 결과값을 ROWNUM >= 5 을 이용하여 쿼리를 작성하여 보시오. 4) 3번의 쿼리를 IN LINE VIEW를 이용하여 정상적으로 5번째 데이터 부터 출력해 보시오. 5) 1번의 결과를 ORDER BY를 이용하여 사원명 순으로 정렬 하시오. 6) 5번 결과의 IN LINE VIEW를 이용하여 ROWNUM 순번을 정상적을 정렬하여 보시오.
172
SQL 기초 02 13. 기타 ◈ 실습 7) 사원정보(TEMP) 테이블에서 아래와 같이 SELECT결과를 3개행씩 묶어 하나의 번호를 부여하는 SQL을 만들어보시오 ROWNUM, 부여된번호, EMP_ID, EMP_NAME 을 보여주면 된다. 결과 : ROWNUM 번호 EMP_ID EMP_NAME 1 1 정도령 2 1 강감찬 3 1 이순신 4 2 홍길동 5 2 배뱅이 6 2 설까치 7 3 지문덕 8 3 김길동 9 3 연흥부 …………………………………………… 8) 사원정보(TEMP) 테이블에서 ROWNUM을 채취해 값이 5와 10사이에 있는 행의 ROWNUM, 사번, 성명을 조회하는 SQL을 만들어 보시오(IN LINE VIEW 이용)
173
SQL 기초 02 14. 종합실습 ◈ 실습 1) TEMP(사원정보) 테이블에서 생일이 3월인 사원의 사번, 이름, 생일(년-월-일)을 출력하세요. 2) TEMP(사원정보) 테이블에서 생일이 1분기에 해당하는 사원의 사번, 이름, 급여, 직급을 출력하세요. 3) TEMP(사원정보) 테이블에서 이순신과 같은 부서에서 근무하는 사원들의 평균급여 및 인원수는? 4) TEMP(사원정보) 테이블에서 72년에 태어난 사람의 사번, 이름, 지사(AREA), 부서코드, 부서명을 구하시오. ( 지사(AREA), 부서명은 부서정모(TDEPT)테이블에 존재)
174
SQL 기초 02 14. 종합실습 ◈ 실습 5) TEMP(사원정보) 테이블에서 ‘과장’ 직급을 가진 사람중 급여가 가장 높은 사람의 사번, 이름, 부서코드, 부서명, 급여, 직급을 구하시오. 6) 1971년1월1일 부터 1973년3월31일 사이에 태어난 사람의 사번, 사원번호, 부서코드, 부서명, 취미를 구하시오. 7) 위 결과에서 취미가 없는 사람은 ‘없음’으로 표현하시오. 8) TEMP(사원정보) 테이블에서 ‘김길동’,’홍길동’이 가지고 있는 취미와 같은 사람의 사번, 이름, 취미를
175
SQL 기초 02 14. 종합실습 ◈ 실습 9) TEMP(사원정보) 테이블에서 직급이 ‘대리’,’과장’의 직급별 평균 급여를 구하시오. 10) TEMP(사원정보), TDEPT(부서정보) 테이블에서 ‘재무’,’총무’ 부서가 아닌 사람의 사번, 이름, 부서코드, 부서명을 구하시오. 11) TEMP(사원정보), TDEPT(부서정보) 테이블에서 영업관련 부서가 아닌 사람의 12) TEMP(사원정보), TDEPT(부서정보) 테이블에서 성이 김씨인 사람의 13) TEMP(사원정보), TDEPT(부서정보) 테이블에서 이름의 첫글자가 ‘길’인 사람의
176
SQL 기초 02 14. 종합실습 ◈ 실습 14) TDEPT(부서정보) 테이블에서 지역이 ‘서울’이 아닌 부서의 부서코드, 부서명, 지역을 NOT EXISTS를 이용하여 구하시오. 단, 본사는 서울에 존재 한다고 가정합니다. 15) TEMP(사원정보) 테이블에서 이순신이 속한 부서의 평균 연봉보다 많은 사람의 사번, 성명을 구하시오. 16) TEMP(사원정보) 테이블에서 사번, 성명, 연봉과 자신이 속한 부서의 평균 연봉보다 자신의 연봉이 높을 경우는 ‘H’ , 낮을 경우에는 ‘L’을 컬럼명을 ‘COMP_SALARY’로 치환하여 같이 구하시오.(CASE이용) 단, 연봉이 높은 순(DESC), 성명순으로 정렬하여 표현하시오. 17) TEMP(사원정보) 테이블에서 직급이 1명 이상인 직급의 직원수 및 평균 연봉을 구하시오 ( HAVING 이용 )
177
SQL 기초 02 14. 종합실습 ◈ 실습 18) TEMP(사원정보) 테이블에서 연봉이 높은 사람을 상위 3명만 연봉순으로 구하시오. ( ROWNUM 이용) 19) TEMP(사원정보), TDEPT(부서정보) 테이블에서 ‘H/W지원’ 부서의 평균 연봉보다 높은 부서의 부서코드, 부서명, 평균연봉을 구하시오. ( HAVING 이용 ) 20) TEMP(사원정보), TCOM(보너스정보) 테이블에서 사번, 사원명, 보너스, 보너스율을 구하시오. 단, 보너스가 없는 사람도 표현되게 구하고, 보너스가 없을 경우 보너스 컬럼에 ‘없음’으로 보너스율은 0으로 치환하여 구하시오. 21) TEMP(사원정보), TCOM(보너스정보) 테이블에서 수습사원을 제외하고 보너스를 받지 못한 사람의 사번, 사원명을 구하시오. (NOT EXISTS 이용)
178
SQL 기초 02 14. 종합실습 ◈ 실습 22) 다음 테이블을 생성 하시오. - 테이블명 : SALES
- 컬럼 : DOSI VARCHAR2(30), SALES NUMBER, SALE_DATE DATE 23) SALES테이블에 다음 DATA를 삽입하시오. - 24) 다음 테이블을 생성 하시오. - 테이블명 : GEOGRAPHY - 컬럼 : REGION VARCHAR2(10), DOSI VARCHAR2(30) 25) GEOGRAPHY 테이블에 다음 DATA를 삽입하시오.
179
SQL 기초 02 14. 종합실습 ◈ 실습 * 아래 결과를 만들어내는 쿼리를 작성하세요. 26) 지역별(REGION) 매출합계
27) 도시별 매출합계 28) 기간별, 지역별 매출합계 29) 지역별, 기간별(월별) 합계를 출력하는데 월별매출액이 1200 이상 30) EXISTS를 사용하여 REGION이 "WEST"인 곳의 매출합계를 출력하세요.
180
SQL 기초 02 14. 종합실습 ◈ 실습 31) TEMP(사원정보) 테이블을 이용하여 TEMP_BACK 테이블을 생성 하시오. (TEMP_BACK 테이블의 컬럼은 EMP_ID, EMP_NAME, DEPT_CODE, LEV 만 생성합니다. ) 32) TDEPT(부서정보) 테이블을 이용하여 TDEPT_BACK를 구조만 생성하시오. (DEPT_CODE, DEPT_NAME 컬럼을 생성합니다.) 33) TDEPT(부서정보) 테이블의 DEPT_CODE, DEPT_NAME DATA를 TDEPT_BACK에 삽입하시오. 34) SELECT * FROM USER_CONSTRAINTS WHERE TABLE_NAME IN ('TEMP', 'TEMP_BACK'); 을 실행하여 제약조건을 확인 하세요. 35) TEMP_BACK에 EMP_ID를 PRIMARY KEY로 생성 하시오. 36) SELECT * FROM ALL_IND_COLUMNS WHERE TABLE_NAME = 'TEMP_BACK'; 을 실행하여 인덱스를 확인 하세요.
181
SQL 기초 02 14. 종합실습 ◈ 실습 37) TEMP_BACK테이블에서 DEPT_CODE 의 CHECK 조건을 삭제 하시오. 38) TEMP_BACK테이블에 DEPT_CODE NOT NULL 조건을 추가 하시오. 39) TEMP_BACK 테이블에 EMP_ID, DEPT_CODE를 결합 인덱스로 생성 하시오. 40) SELECT * FROM ALL_IND_COLUMNS WHERE TABLE_NAME = 'TEMP_BACK'; 를 이용하여 39번에서 생성한 인덱스를 확인 하시요. 41) TEMP_BACK테이블에서 DEPT_CODE(부서코드) 가 ‘A’로 시작될 경우 ‘Z’로 수정하시오.
182
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 분석함수란?
▷ 테이블에 있는 데이터를 특정 용도로 분석하여 결과를 반환하는 함수 ▷ 복잡한 계산을 단순하게 처리해주는 함수 ▷ 쿼리 결과Set을 대상으로 계산을 수행하는 함수 ▷ SELECT 절에서 수행됨, FROM, WHERE, GROUP BY 절에서 사용 불가, ORDER BY 구문에서는 사용 가능 ▷ 오라클 부터 분석함수 지원 ◈ 집계함수 vs 분석함수 ▷ 집계함수 : 집계함수는 여러행 또는 테이블 전체 행으로부터 그룹별로 집계하여 결과를 반환합니다. SELECT deptno, SUM(sal) s_sal FROM emp GROUP BY deptno; ▷ 분석함수 : 분석 함수는 집계 결과를 각 행마다 보여줍니다. SELECT deptno, empno, sal, SUM(sal) OVER(PARTITION BY deptno) s_sal FROM emp; ▷ 집계함수 vs 분석함수 - 집계함수는 그룹별 최대, 최소, 합계, 평균, 건수 등을 구할 때 사용되며, 그룹별 1개의 행을 반환합니다. - 분석함수는 그룹단위로 값을 계산한다는 점에서 집계함수와 유사하지만, 그룹마다가 아니라 결과Set의 각 행마다 집계결과를 보여준다는 점에서 집계함수와 상당한 차이가 있습니다. - 분석함수는 쉽게 생각해서, 그룹별 계산결과를 각 행마다 보여주는 것입니다.
183
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 분석함수 Syntax
SELECT ANALYTIC_FUNCTION ( arguments ) OVER ( [ PARTITION BY 컬럼List ] [ ORDER BY 컬럼List ] [ WINDOWING 절 (Rows|Range Between)] ) FROM 테이블 명; - ANALYTIC_FUNCTION : 분석함수명(입력인자) - OVER : 분석함수임을 나타내는 키워드. - PARTITION BY : 계산 대상 그룹을 정합니다. - ORDER BY : 대상 그룹에 대한 정렬을 수행합니다. - WINDOWING 절 : 분석함수의 계산 대상 범위를 지정합니다. ORDER BY 절에 종속적입니다. 기본 생략 구문 : 정렬된 결과의 처음부터 현재행까지 [RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW] ◈ 분석함수의 종류 - 순위함수 : RANK, DENSE_RANK, ROW_NUMBER, NTILE - 집계함수 : SUM, MIN, MAX, AVG, COUNT - 기타함수 : LEAD, LAG, FIRST_VALUE, LAST_VALUE, RATIO_TO_REPORT - 분석함수(?) : KEEP, LISTAGG
184
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 순위 함수
▷ RANK 함수는 순위를 부여하는 함수로 동일순위 처리가 가능합니다. (중복 순위 다음 순서 건너뜀 - 1,2,2,4) ▷ DENSE_RANK 함수는 RANK 함수와 같은 역할을 하지만 동일 등수가 순위에 영향이 없습니다.(중복순위 다음 순위 연속 - 1,2,2,3) ▷ ROW_NUMBER 함수는 특정 순위로 일련번호를 제공하는 함수로 동일순위 처리가 불가능합니다. (중복순위 없이 유일값 - 1,2,3,4) ▷ 순위 함수 사용시 ORDER BY절은 필수로 입력해야 합니다. -- 아래는 급여가 높은 순서대로 순위를 구하는 예제 SELECT deptno, empno, sal , RANK() OVER(ORDER BY sal DESC) rk FROM emp; 급여가 같은 경우 동일 순위로 처리되는 것을 확인 할 수 있다 -- 부서별(PARTITION BY deptno)로 급여가 높은 순서대로(ORDER BY sal DESC) 순위를 구하는 예 , RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) rk [ 순위함수의 특징 ] - ORDER BY는 생략할 수 없습니다. - WINDOWING 절은 사용 할 수 없다
185
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 순위 함수 비교
-- 예제를 통해서 RANK, DENSE_RANK, ROW_NUMBER 함수의 차이점을 이해하자 SELECT DEPTNO, EMPNO, SAL , RANK() OVER(ORDER BY SAL DESC) RK , DENSE_RANK() OVER(ORDER BY SAL DESC) DR , ROW_NUMBER() OVER(ORDER BY SAL DESC) RN FROM EMP; RANK : 중복 순위 다음 순서 건너뜀.(1,2,2,4) DENSE_RANK : 중복순위 다음 순위 연속.(1,2,2,3) ROW_NUMBER : 중복순위 없이 유일값. (1,2,3,4) DEPTNO EMPNO SAL RK DR RN 10 7839 5000 1 20 7902 3000 2 7788 3 7566 2975 4 30 7698 2850 5 7782 2450 6
186
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 집계함수 ▷ SUM(누적합계)
-- 사원의 전체급여 합계(all_sum), 부서별 급여 합계(dept_sum), 부서별로 누적 합계(nujuk_sum)를 조회 SELECT EMPNO, ENAME, DEPTNO , SUM(SAL) OVER () ALL_SUM , SUM(SAL) OVER (PARTITION BY DEPTNO) DEPT_SUM , SUM(SAL) OVER (PARTITION BY DEPTNO ORDER BY EMPNO) NUJUK_SUM FROM EMP; - ALL_SUM : PARTITION BY절과 ORDER BY절이 생략되어 전체 급여 합계를 계산합니다. - DEPT_SUM : PARTITION BY절에 deptno를 사용하여 부서별 급여 합계를 계산합니다. - NUJUK_SUM : 부서별로 구분하고, empno로 ORDER BY절을 사용하였다. 사원번호 별로 급여 합계가 누적되어 계산되는 것을 확인 할 수 있습니다. EMPNO ENAME DEPTNO ALL_SUM DEPT_SUM NUJUK_SUM 7782 CLARK 10 29025 8750 2450 7839 KING 7450 7934 MILLER 7369 SMITH 20 10875 800 7566 JONES 3775 …
187
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ 윈도우함수
▷ 분석함수 중에서 윈도우절(WINDOWNING 절)을 사용하는 함수를 윈도우 함수라고 합니다. ▷ 윈도우절을 사용하면 PARTITION BY 절에 명시된 그룹을 좀 더 세부적으로 그룹핑 할 수 있습니다. ▷ 윈도우절은 분석함수중에서 일부(AVG, COUNT, SUM, MAX, MIN)만 사용 할 수 있습니다. ▷ WINDOWNING 절 Syntax 윈도우 함수 OVER ( PARTITION BY 절 ORDER BY 절 [ASC|DESC] ROWS | RANGE BETWEEN UNBOUNDED PRECEDING | n PRECEDING | CURRENT ROW AND UNBOUNDED FOLLOWING | n FOLLOWING | CURRENT ROW - ROWS : 물리적인 ROW 단위로 행 집합을 지정합니다. - RANGE : 논리적인 상대번지로 행 집합을 지정합니다. - BETWEEN ~ AND 절 : 윈도우의 시작과 끝 위치를 지정합니다. - UNBOUNDED PRECEDING : PARTITION의 첫 번째 로우에서 윈도우가 시작합니다. - UNBOUNDED FOLLOWING : PARTITION의 마지막 로우에서 윈도우가 시작합니다. - CURRENT ROW : 윈도우의 시작이나 끝 위치가 현재 로우 입니다.
188
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ WINDOWING 절 예제
-- 부서별(PARTITION BY deptno)로 이전 ROW(ROWS 1 PRECEDING)의 급여와 현재 ROW의 급여 합계를 출력하는 예 SELECT EMPNO, ENAME, DEPTNO, SAL , SUM(SAL) OVER (PARTITION BY DEPTNO ORDER BY EMPNO ROWS 1 PRECEDING ) PRE_SUM FROM EMP; PRE_SUM : 이전 ROW와 현재 ROW의 급여 합계가 출력된 것을 확인 할 수 있습니다. -- 첫 번째 ROW부터 마지막 ROW까지의 합과(SAL1), 첫 번째 ROW부터 현재 ROW까지의 합(SAL2) 그리고 현재 ROW부터 마지막 ROW까지의 합(SAL3)을 출력하는 예 , SUM(SAL) OVER(ORDER BY DEPTNO, EMPNO ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) SAL1 , SUM(SAL) OVER(ORDER BY DEPTNO, EMPNO AND CURRENT ROW) SAL2 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) SAL3 SAL1 : 첫 번째 ROW부터 마지막 ROW까지의 급여 합계입니다. SAL2 : 첫 번째 ROW 부터 현재 ROW까지의 급여 합계입니다. SAL3 : 현재 ROW부터 마지막 ROW까지 급여 합계입니다.
189
Advanced SQL 03 1. 분석 함수( Analytic Functions )
-- 월별 금액 리스트를 출력하고, 직전 3개월 합계(AMT_PRE3)와 이후 3개월 합계(AMT_FOL3)를 함께 표시하는 예 -- 7월 데이터가 없기 때문에 직전 3개월 합계(AMT_PRE3) 8월의 경우 6월,5월 두 달치만 누적된 것을 확인 할 수 있습니다. WITH TEST AS ( SELECT '200801' YYYYMM, 100 AMT FROM DUAL UNION ALL SELECT '200802', 200 FROM DUAL UNION ALL SELECT '200803', 300 FROM DUAL UNION ALL SELECT '200804', 400 FROM DUAL UNION ALL SELECT '200805', 500 FROM DUAL UNION ALL SELECT '200806', 600 FROM DUAL UNION ALL SELECT '200808', 800 FROM DUAL UNION ALL SELECT '200809', 900 FROM DUAL UNION ALL SELECT '200810', 100 FROM DUAL UNION ALL SELECT '200811', 200 FROM DUAL UNION ALL SELECT '200812', 300 FROM DUAL ) SELECT YYYYMM, AMT , SUM(AMT) OVER(ORDER BY TO_DATE(YYYYMM,'YYYYMM') RANGE BETWEEN INTERVAL '3' MONTH PRECEDING AND INTERVAL '1' MONTH PRECEDING) AMT_PRE3 RANGE BETWEEN INTERVAL '1' MONTH FOLLOWING AND INTERVAL '3' MONTH FOLLOWING) AMT_FOL3 FROM TEST; AMT_PRE3 : 직전 3개월 합계 AMT_FOL3 : 이후 3개월 합계
190
Advanced SQL 03 1. 분석 함수( Analytic Functions )
◈ LAG, LEAD( 다른 행의 값을 참조 ) ▷ LAG (컬럼명[,offset][,default]) : 현재 ROW 기준으로 이전 행을 참조 ▷ LEAD (컬럼명[,offset][,default]) : 현재 ROW 기준으로 다음 행을 참조 -- 이전 row(S_1), 다음 row(S_2), 다음 두 번째 row(S_3)의 급여를 조회하는 예제 -- 다음 두 번째 row(S_3) 값이 NULL인 경우 0을 출력 SELECT DEPTNO, EMPNO, SAL , LAG (SAL) OVER(ORDER BY DEPTNO, EMPNO) S_1 , LEAD(SAL) OVER(ORDER BY DEPTNO, EMPNO) S_2 , LEAD(SAL, 2, 0) OVER(ORDER BY DEPTNO, EMPNO) S_3 FROM EMP; S_1 : 이전 ROW 의 급여 값을 출력합니다. S_2 : 다음 ROW 의 급여 값을 출력합니다. S_3 : 다음 두 번째 ROW의 급여 값을 출력합니다. 만약 값이 없으면 0을 출력합니다. [ LAG, LEAD 함수 사용시 ORDER BY 절은 필수 입력사항 입니다. ]
191
Advanced SQL 03 1. 분석 함수( Analytic Functions )
◈ RATIO_TO_REPORT( 점유율 ) ▷ RATIO_TO_REPORT 함수는 합에 대한 값의 비율을 계산합니다 SELECT DEPTNO , SUM(SAL) SAL , SUM(SUM(SAL)) OVER() TOT , ROUND(SUM(SAL) / SUM(SUM(SAL)) OVER(), 2) RAT1 , ROUND(RATIO_TO_REPORT(SUM(SAL)) OVER(), 2) RAT2 FROM EMP GROUP BY DEPTNO; SAL : 부서별 급여 합계를 집계함수를 사용하여 계산한 결과입니다. - TOT : SUM 분석함수를 이용하여 부서별 급여 합계의 전체 합계를 계산한 결과입니다. - RAT1 : 집계함수를 이용해서 계산한 부서별 합계에서 분석함수를 이용해 계산한 전체 합계를 나누어 비율을 계산한 결과입니다. - RAT2 : RATIO_TO_REPORT 분석함수를 사용하여 부서별 급여 합계의 비율을 계산한 결과이다 [ 집계함수와 분석함수의 중첩 사용 ] - 분석함수는 GROUP BY 보다 나중에 실행됩니다. - 따라서 GROUP BY의 결과Set을 대상으로 분석함수 사용이 가능합니다. - 반대로 분석함수를 집계함수 안에서 사용할 수는 없습니다. 예) SUM( SUM(sal) OVER() ) 에러발생
192
Advanced SQL 03 1. 분석 함수( Analytic Functions )
◈ FIRST_VALUE, LAST_VALUE ▷ FIRST_VALUE : 정렬된 값 중에서 첫 번째 값을 반환합니다. ▷ LAST_VALUE : 정렬된 값 중에서 맨 마지막 값을 반환합니다. -- 사원순 정렬의 첫번째 사원 급여(F_EMP)와 마지막 사원 급여(L_EMP)를 조회하는 예 SELECT EMPNO , SAL , FIRST_VALUE(SAL) OVER(ORDER BY EMPNO) F_EMP , LAST_VALUE (SAL) OVER(ORDER BY EMPNO) L_EMP FROM EMP; ▷ ORDER BY 사용시 분석함수의 기본 계산 범위는 처음부터 현재까지 입니다.
193
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ KEEP (최초값, 최종값)
- MAX() KEEP(DENSE_RANK FIRST[LAST] ORDER BY[ASC|DESC]) - MIN() KEEP(DENSE_RANK FIRST[LAST] ORDER BY[ASC|DESC]) -- 부서별 최대급여자 급여(MAX_SAL)와 사번(MAX_E), 최소급여자 급여(MIN_SAL)와 사번(MIN_E)을 조회하는 예 -- KEEP을 사용하지 않을 경우 SQL문 SELECT A.DEPTNO, A.MAX_S, E1.EMPNO MAX_E , A.MIN_S, E2.EMPNO MIN_E FROM (SELECT DEPTNO, MAX(SAL) MAX_S, MIN(SAL) MIN_S FROM EMP GROUP BY DEPTNO ) A , EMP E1, EMP E2 WHERE A.DEPTNO = E1.DEPTNO AND A.MAX_S = E1.SAL AND A.DEPTNO = E2.DEPTNO AND A.MIN_S = E2.SAL ORDER BY A.DEPTNO; -- KEEP을 사용 SQL문 SELECT DEPTNO , MAX(SAL) MAX_SAL , MAX(EMPNO) KEEP(DENSE_RANK LAST ORDER BY SAL) MAX_E , MIN(SAL) MIN_SAL , MIN(EMPNO) KEEP(DENSE_RANK FIRST ORDER BY SAL) MIN_E GROUP BY DEPTNO ORDER BY DEPTNO;
194
Advanced SQL 03 1. 분석 함수( Analytic Functions ) ◈ LISTAGG (문자열합치기)
▷ 함수 이름 그대로 LIST를 구분자로 AGGREGATE 해주는 함수이며, 행 데이터를 특정 구분자를 가지는 열로 쉽게 표현할 수 있습니다. ▷ LISTAGG(컬럼, 구분값) WITHIN GROUP( ORDER BY 절) 형식으로 사용합니다 -- 오라클 버전별로 문자열을 합치는 예제 SELECT DEPTNO , SUBSTR(XMLAGG(XMLELEMENT(X, ',', EMPNO) ORDER BY EMPNO).EXTRACT('//TEXT()'), 2) "9I" , WM_CONCAT(EMPNO) "10G" , LISTAGG(EMPNO, ',') WITHIN GROUP(ORDER BY EMPNO) "11G" FROM EMP GROUP BY DEPTNO ORDER BY DEPTNO ▷ WM_CONCAT은 정렬을 사용 할 수 없으며, 그 외 방법들은 정렬 기능을 사용이 가능 합니다. ▷ KEEP, WM_CONCAT 는 분석함수가 아닌 집계함수입니다. - 그룹별 집계결과를 1개행으로 반환 - OVER 구문이 없음
195
Advanced SQL 03 2. Group By 확장 기능 ◈ Rollup 과 Cube
▷ ROLLUP은 GROUP BY 절의 그룹 조건에 따라 전체 행을 그룹화 하고, 각 그룹에 대해 부분합을 구하는 연산자입니다. ▷ CUBE는 ROLLUP에 의한 그룹 결과와 GROUP BY 절에 기술된 조건에 따라 그룹 조합을 만드는 연산자입니다. 즉, ROLLUP 연산자를 수행한 결과에 더해 GROUP BY 절에 기술된 조건에 따라 모든 가능한 그룹핑 조합에 대한 결과를 출력합니다. ▷ ROLLUP과 CUBE는 GROUP BY 절 뒤에 기술한 컬럼 개수에 따라 출력되는 결과 셋이 달라집니다. ▷ GROUP BY 뒤에 기술한 컬럼이 2개일 경우 ROLLUP은 n+1에서 3개의 그룹별 결과가 출력되고, CUBE는 2*n에서 2*2=4개의 결과 셋이 출력된다 SELECT 컬럼명, 그룹함수(컬럼명) FROM 테이블명 WHERE 조건 GROUP BY [ROLLUP | CUBE] 그룹핑하고자 하는 컬럼명.. HAVING 그룹조건 ORDER BY 컬럼명 또는 위치번호
196
Advanced SQL 03 2. Group By 확장 기능 ◈ Rollup 과 Cube 개념 deptno별 모음
clerk salesman manager analyst president 계 ┃ ┃ ┃ ┃ ┃ ┃ ∨ 10 1 3 20 2 5 30 4 6 14 ROLLUP의 개념도 ━━━━━━━━━━━━ ROLLUP ━━━━━━━━━━━━> deptno clerk salesman manager analyst president 계 10 1 3 20 2 5 30 4 6 14 deptno별 모음 job별 모음 deptno 부분합계 job 부분합계 SELECT DEPTNO, JOB, SAL FROM EMP ORDER BY DEPTNO; DEPTNO JOB SAL 10 MANAGER 10 PRESIDENT 10 CLERK 20 CLERK 20 CLERK 20 ANALYST 20 MANAGER 30 SALESMAN 30 MANAGER 30 SALESMAN 30 CLERK 30 SALESMAN ORDER BY JOB; DEPTNO JOB SAL 20 ANALYST 20 CLERK 20 CLERK 10 CLERK 30 CLERK 20 MANAGER 10 MANAGER 30 MANAGER 10 PRESIDENT 30 SALESMAN 30 SALESMAN 30 SALESMAN SELECT DEPTNO, SUM(SAL) GROUP BY ROLLUP(DEPTNO); DEPTNO SUM(SAL) 29025 SELECT JOB, SUM(SAL) GROUP BY ROLLUP(JOB); JOB SUM(SAL) ANALYST CLERK MANAGER PRESIDENT SALESMAN
197
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 예제
위 예제에서 rollup(deptno, job)이나 cube(deptno, job)처럼 두 개에 대해서 분석하는 경우에는 부분합계를 세부적으로 계산합니다. scott.emp 스키마에서 deptno=20의 clerk=2명, analyst=2명이고 또한 deptno=30 그룹에서는 salesman=4명이 됩니다. 그들에 대한 각각의 부분합이 계산되어 집니다. ROLLUP 사용 CUBE 사용 SELECT DEPTNO, JOB, SUM(SAL) FROM EMP GROUP BY ROLLUP(DEPTNO, JOB); GROUP BY CUBE(DEPTNO, JOB); DEPTNO JOB SUM(SAL) 10 CLERK 1300 ← 10 그룹 clerk의 합계 MANAGER 2450 ← 10 그룹 manager의 합계 PRESIDENT 5000 ← 10 그룹 president의 합계 8750 ← 10 그룹의 부분합계 20 1900 ← 20 그룹 clerk의 합계 ANALYST 6000 ← 20 그룹 analyst의 합계 2975 ← 20 그룹 manager의 합계 10875 ← 20 그룹의 부분합계 30 950 ← 30 그룹 clerk의 합계 2850 ← 30 그룹 manager의 합계 SALESMAN 5600 ← 30 그룹 salesman의 합계 9400 ← 30 그룹의 부분합계 29025 ← 총합 DEPTNO JOB SUM(SAL) 29025 ← 총합 CLERK 4150 ← CLERK 그룹의 합계 ANALYST 6000 ← ANALYST 그룹의 합계 MANAGER 8275 ← MANAGER 그룹의 합계 SALESMAN 5600 ← SALESMAN 그룹의 합계 PRESIDENT 5000 ← PRESIDENT 그룹의 합계 10 8750 ← 10 그룹의 부분합계 1300 ← 10 그룹 clerk의 합계 2450 ← 10 그룹 manager의 합계 ← 10 그룹 president의 합계 20 10875 ← 20 그룹의 부분합계 1900 ← 20 그룹 clerk의 합계 ← 20 그룹 analyst의 합계 2975 ← 20 그룹 manager의 합계 30 9400 ← 30 그룹의 부분합계 950 ← 30 그룹 clerk의 합계 2850 ← 30 그룹 manager의 합계 ← 30 그룹 salesman의 합계
198
Advanced SQL 03 2. Group By 확장 기능 ◈ GROUPING과 GROUPING_ID
- GROUPING 함수는 ROLLUP, CUBE에 모두 사용할 수 있습니다. - GROUPING 함수는 해당 컬럼의 Row가 GROUP BY에 의해서 산출된 Row인 경우에는 0을 반환하고, ROLLUP이나 CUBE에 의해서 산출된 Row인 경우에는 1을 반환하게 됩니다. - 따라서 해당 Row가 결과집합에 의해 산출된 Data 인지, ROLLUP이나 CUBE에 의해서 산출된 Data 인지를 알 수 있도록 지원하는 함수입니다. ▷ GROUPING_ID(컬럼a, 컬럼b[, …]) : GROUPING(컬럼a)||GROUPING(컬럼b)의 값을 2진수에서 10진수로 변환한 값 SELECT DEPTNO , EMPNO , SUM(SAL) S_SAL , GROUPING(DEPTNO) GRP_DEPT , GROUPING(EMPNO) GRP_EMP , GROUPING_ID(DEPTNO, EMPNO) GID FROM EMP GROUP BY ROLLUP(DEPTNO, EMPNO); GRP_DEPT : deptno로 GROUP BY 되면 0, deptno의 값이 없으면 1 GRP_EMP : empno로 GROUP BY 되면 0, empno의 값이 없으면 1 GID : GROUPING(deptno) || GROUPING(empno)의 값을 2진수에서 10진수로 변환한 값
199
Advanced SQL 03 2. Group By 확장 기능 ◈ GROUPING과 GROUPING_ID
▷ 소계만 표시, 총계 제거 -- 부서별 소계만 조회하고, 전체 총계는 조회하지 않는 예제 -- 이전 GROUPING과 GROUPING_ID 예제 실행결과 [GROUPING(deptno)=0] 조건으로 소계만 조회가 가능 SELECT DEPTNO , DECODE(GROUPING(EMPNO),1,'소계',EMPNO) EMPNO , SUM(SAL) S_SAL FROM EMP GROUP BY ROLLUP(DEPTNO, EMPNO) HAVING GROUPING(DEPTNO) = 0; -- GROUP BY 절에서 empno만 ROLLUP 연산[GROUP BY deptno, ROLLUP(empno)]을 하여도 동일한 결과를 얻을 수 있습니다. GROUP BY DEPTNO, ROLLUP(EMPNO);
200
Advanced SQL 03 2. Group By 확장 기능 ◈ GROUPING과 GROUPING_ID
▷ 총계만 표시, 소계 제거 -- 전체 총계만 조회하고, 소계는 조회하지 않는 예제 -- 이전 GROUPING과 GROUPING_ID 예제 실행결과 [GROUPING_ID(deptno, empno) != 1] 조건으로 소계만 조회가 가능 SELECT DEPTNO , DECODE(GROUPING(DEPTNO),1,'합계',EMPNO) EMPNO , SUM(SAL) S_SAL FROM EMP GROUP BY ROLLUP(DEPTNO, EMPNO) HAVING GROUPING_ID(DEPTNO, EMPNO) != 1; -- ROLLUP 연산을 괄호로 묶어[GROUP BY ROLLUP((deptno, empno))]서 처리가 가능 괄호로 묶은 항목은 하나의 항목처럼 묶여 처리 이는 코드와 명칭을 함께 Group By Rollup 할 때 주로 사용 GROUP BY ROLLUP((DEPTNO, EMPNO));
201
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 - 문제
- 각 사원별로 부서코드, 사원번호, 성명, 급여가 조회돼야 합니다. - 각 부서별 급여 합계 및 평균금액을 새로운 행으로 표시해야 합니다.
202
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 1
SELECT DEPTNO , EMPNO , SUM(SAL) SAL FROM EMP GROUP BY ROLLUP(DEPTNO, EMPNO); ▷ 위 예제 쿼리와 실행 결과를 살펴보면 EMPNO가 비어있는 행 3개와, DEPTNO가 비어 있는 행 1개가 생성된 것을 볼 수 있습니다. ROLLUP은 GROUP BY 항목들의 합계를 표현하는 방법인 것입니다. ① 부서별 사원별 합계 가 기본으로 보여지고 ② 부서별 사원들의 합계가 부서별로 마지막에 보여지고 ③ 부서들의 합계가 맨 마지막에 보여집니다. 즉, 롤업 안에 나열된 항목들의 오른쪽 항목부터 왼쪽 항목으로 합계를 보여줍니다. 그런데 우리가 필요로 하는 자료는 ①, ② 일뿐 ③ 은 필요가 없습니다. 이때 단지 DEPTNO를 ROLLUP에서 제외 하면 됩니다. GROUP BY 항목들이 모두 ROLLUP에 참여할 필요는 없습니다.
203
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 2
SELECT DEPTNO , EMPNO , SUM(SAL) SAL FROM EMP GROUP BY DEPTNO, ROLLUP(EMPNO); ▷ DEPTNO 항목을 ROLLUP의 밖으로 빼냄으로 부서들의 합계는 결과에서 제외되었습니다. 이처럼 ROLLUP 에 참여할 항목들을 조정할 수 있습니다.
204
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 3
SELECT DEPTNO , EMPNO , ENAME , SUM(SAL) SAL FROM EMP GROUP BY DEPTNO, ROLLUP(EMPNO, ENAME); ▷ 부서별, 사원번호별 사원명별 합계가 기본으로 나오며, 부서별, 사원번호의 합계가 나오게 됩니다. 하지만 사원번호별 사원명의 합계는 불필요한 항목입니다. 여기서 주의해야 할 것은 ENAME은 GROUP BY에 있어서 키의 역할을 하는 것이 아니라 단지 EMPNO의 설명 역할, 보조 역할을 할 뿐이라는 것입니다. 이러한 보조 항목들은 주키 역할을 하는 항목과 함께 괄호로 묶어서 따로 ROLLUP 기능을 하지 못하도록 할 수 있습니다.
205
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 4
SELECT DEPTNO , EMPNO , ENAME , SUM(SAL) SAL FROM EMP GROUP BY DEPTNO, ROLLUP((EMPNO, ENAME)); ▷ EMPNO와 ENAME을 괄호로 묶어서 ROLLUP 에서 마치 하나의 항목처럼 동작하게 만들었습니다.
206
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 5
과연 어떤 항목을 더 추가해야 할까요? DEPTNO 항목을 추가해 보도록 하겠습니다. SELECT DEPTNO , EMPNO , ENAME , SUM(SAL) SAL FROM EMP GROUP BY DEPTNO, ROLLUP(DEPTNO, (EMPNO, ENAME)) ORDER BY DEPTNO, EMPNO; ▷ DEPTNO 항목을 두 번 사용해서 합계 행을 두 번 나오도록 만들었습니다. 단순 GROUP BY 에서 같은 항목을 두 번 사용한다면 무의미한 구문이 되어 버리겠지만 ROLLUP에서의 항목 중복 사용은 특별한 결과를 도출해 냅니다.
207
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 6
▷ 자 이제 목표결과에 대한 틀은 갖추어 졌으니 내용물을 가공하는 일만 남았습니다. 만들어낸 두 개의 합계행중 하나는 합계(SUM)을 보여주고 나머지 하나는 평균(AVG)을 보여주도록 조건문(DECODE)을 사용하면 되겠습니다. 하지만 보이는 것과 같이 두 개의 합계 행에는 차이점이 없습니다. 두 개 행의 차이점을 알아야지만 조건을 줄 수 있는데 말이죠. ROLLUP의 결과 행들을 구별해 내는 함수가 몇 가지 있는데 이에 대해 살펴보도록 하겠습니다. SELECT DEPTNO , EMPNO, ENAME , SUM(SAL) SUM_SAL , GROUPING(DEPTNO) G1 , GROUPING(EMPNO) G2 , GROUPING_ID(EMPNO, ENAME) G3 , GROUP_ID() G4 FROM SCOTT.EMP GROUP BY DEPTNO, ROLLUP(DEPTNO, (EMPNO, ENAME)) ORDER BY DEPTNO, EMPNO; - GROUPING(empno) g1 : 이는 empno 항목별 합계의 경우엔 0 empno 항목들의 합계의 경우엔 1입니다. - GROUPING_ID(empno, ename) : 이는 GROUPING(empno) || GROUPING(ename) 의 결과를 2진수로 보고 십진수로 환산한 값입니다. - GROUP_ID() : 중복 항목에 대한 롤업 결과를 구별해주는 함수입니다.
208
Advanced SQL 03 2. Group By 확장 기능 ◈ ROLLUP 과 CUBE 실습 – 해설 7
▷ 이전 결과를 보시면 GROUPING(컬럼), GROUPING_ID(컬럼리스트)로는 구별이 가질 않습니다. 결국 GROUP_ID()가 0일 경우엔 합계를 1일 경우엔 평균을 보여주도록 하면 됩니다. [ 정 답 ] SELECT DEPTNO , EMPNO , DECODE(GROUP_ID(), 0, NVL(ENAME,'합계'), '평균') ENAME , DECODE(GROUP_ID(), 0, SUM(SAL), ROUND(AVG(SAL),2)) SAL FROM EMP GROUP BY DEPTNO, ROLLUP(DEPTNO, (EMPNO, ENAME)) ORDER BY DEPTNO, GROUP_ID(), EMPNO;
209
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리
▷ 특정 인터넷 게시판에 상품에 대한 문의를 할 경우 거기에 대한 답변 그리고 그 답변에 대한 문의 또는 답변들을 볼 수 있습니다. 일반적으로 이런 경우 계층형 구조 쿼리를 사용하게 됩니다. ▷ emp 테이블을 보면 empno와 mgr컬럼이 있으며, mgr 컬럼 데이터는 해당 사원의 관리자의 empno를 의미 합니다. empno 7369사원의 관리자는 7902의 empno를 가진 사원이며 empno 7902사원의 관리자는 7566의 empno를 가진 사원입니다. ▷ 상위 계층과 하위계층의 관계를 Oracle에서는 START WITH와 CONNECT BY를 이용해서 쉽게 조회 할 수 있습니다. EMPNO ENAME SAL MGR 7369 SMITH 800 7902 FORD 3000 7566
210
Advanced SQL 03 3. 계층형 구조 ◈ 계층구조 쿼리 Synctax SELECT [LEVEL], 컬럼명
FROM 테이블명 WHERE 조건 [ START WITH 조건절 ] [ CONNECT BY PRIOR 조건절 ] 용어 의 미 LEVEL 계층구조에서 나온 값들에 대한 계층 순위(Depth를 표현) ex) 1,2,3… START WITH - 계층구조의 최상위 계층을 구체화 합니다. - 계층형 구조 쿼리에서는 필수 항목 CONNECT BY - 이 절을 이용하여 계층 질의에서 상위계층(부모행)과 하위계층(자식행)의 관계를 규정 할 수 있습니다. - PRIOR 연산자와 함께 사용하여 계층구조로 표현할 수 있습니다. - CONNECT BY PRIOR 자식컬럼 = 부모컬럼 : 부모에서 자식으로 트리구성 (Top Down) - CONNECT BY PRIOR 부모컬럼 = 자식컬럼 : 자식에서 부모로 트리 구성 (Bottom Up) - CONNECT BY NOCYCLE PRIOR : NOCYCLE 파라미터를 이용하여 무한루프 방지 - 서브쿼리를 사용할 수 없습니다. ORDER SIBLINGS BY ORDER SIBLINGS BY절을 사용하면 계층구조 쿼리에서 편하게 정렬작업을 할 수 있습니다.
211
Advanced SQL 03 3. 계층형 구조 ◈ 계층구조 쿼리 실행순서 ▷ 계층구조 쿼리 간단 예제
▷ 계층형구조 쿼리의 순서는 다음과 같이 진행 됩니다. - START WITH에 의해 ROOT로 이동합니다. - CONNECT BY에 의해 트리를 작성합니다. - PRIOR에 기술된 방향으로 트리를 탐색합니다. - CONNECT BY 조건이 적용되어 필요할 때에 트리의 가지를 제외합니다. - WHERE 조건을 적용하여 필요 때에 각 행을 제외합니다. ▷ 계층구조 쿼리 간단 예제 -- 직업이 PRESIDENT을 기준으로 계층 구조로 조회하는 예 -- LEVEL컬럼으로 depth를 알수 있습니다. -- JONES의 관리자는 KING 이며, SCOTT의 관리자는 JONES 입니다. -- 상/하의 계층 구조를 쉽게 조회 할 수 있습니다. SELECT LEVEL, EMPNO, ENAME, MGR FROM EMP START WITH JOB = 'PRESIDENT' CONNECT BY PRIOR EMPNO = MGR; * PRIOR 연산자 : 상위행의 컬럼임을 나타낸다. CONNECT BY 절에서 상하위간의 관계를 기술할때 사용.
212
Advanced SQL 03 3. 계층형 구조 ◈ LEVEL 활용
▷ LEVEL Pseudocolumn을 이용하면 계층구조 쿼리를 좀 더 다양하게 활용 할 수 있습니다. ▷ 아래는 LEVEL의 배율만큼 공백을 왼쪽에 추가하여 계층구조를 한눈에 볼 수 있게 표현한 예 -- 왼쪽에 LEVEL만큼 공백을 추가하여 계층구조로 조회하는 예제 SELECT LEVEL, LPAD(' ', 4*(LEVEL-1)) || ENAME ENAME, EMPNO, MGR, JOB FROM EMP START WITH JOB='PRESIDENT' CONNECT BY PRIOR EMPNO=MGR; -- LEVEL별로 급여 합계와 사원수를 조회하는 예제 SELECT LEVEL, AVG(SAL) TOTAL, COUNT(EMPNO) CNT FROM EMP CONNECT BY PRIOR EMPNO=MGR GROUP BY LEVEL ORDER BY LEVEL; -- 기간별 날짜 증가 SELECT TO_CHAR(TO_DATE(' ', 'YYYYMMDD') + LEVEL - 1, 'YYYYMMDD') AS DAYS FROM DUAL CONNECT BY TO_DATE(' ', 'YYYYMMDD') + LEVEL - 1 <= TO_DATE(' ', 'YYYYMMDD');
213
Advanced SQL 03 3. 계층형 구조 ◈ PRIOR 활용 ▷ PRIOR연산자를 SELECT 절에서 사용
SELECT LEVEL, LPAD(' ', 4*(LEVEL-1)) || ENAME ENAME, PRIOR ENAME MGRNAME, EMPNO, MGR, JOB FROM EMP START WITH JOB='PRESIDENT' CONNECT BY PRIOR EMPNO=MGR; ▷ PRIOR 연산자 : 상위행의 컬럼임을 나타낸다. CONNECT BY 절에서만 사용할 수 있는 것은 아니다. ◈ Bottom Up 조회 -- 역순(자식에서 부모로 트리 구성, Bottom Up)으로 조회하는 예 -- ename을 기준으로 Bottom Up으로 조회하는 예제입니다. SELECT LEVEL, LPAD(' ', 4*(LEVEL-1)) || ENAME ENAME, EMPNO, MGR, JOB START WITH ENAME='SMITH' -- 최 하위 노드 값이 와야 합니다. CONNECT BY PRIOR MGR = EMPNO; ▷ PRIOR 컬럼에 따라(상위 OR 하위) 계층전개 방향이 달라집니다. - 순방향(Top Down-상위~하위) : PRIOR 하위 = 상위 - 역방향(Bottom Up-하위~상위) : PRIOR 상위 = 하
214
Advanced SQL 03 3. 계층형 구조 ◈ CONNECT_BY_ROOT
-- 계층구조 쿼리에서 LEVEL이 0인 최상위 로우의 정보를 얻어 오는 예. SELECT LPAD(' ', 4*(LEVEL-1)) || ENAME ENAME, EMPNO, CONNECT_BY_ROOT EMPNO "ROOT EMPNO", LEVEL FROM EMP START WITH JOB='PRESIDENT' CONNECT BY PRIOR EMPNO=MGR; ◈ CONNECT_BY_ISLEAF -- 계층구조 쿼리에서 로우의 최하위 레벨(Leaf) 여부를 반환, 최하이 레벨이면 1, 아니면 0 CONNECT_BY_ISLEAF "LEAF", LEVEL CONNECT BY NOCYCLE PRIOR EMPNO=MGR; ◈ SYS_CONNECT_BY_PATH -- 계층구조 쿼리에서 현재 로우 까지의 PATH 정보를 쉽게 얻어 오는 예. SYS_CONNECT_BY_PATH(ENAME, '/') "PATH" FROM EMP START WITH JOB='PRESIDENT'
215
Advanced SQL 03 3. 계층형 구조 ◈ ORDER SIBLINGS BY
▷ 계층구조 쿼리에서 상관관계를 유지하면서 정렬을 할 수 있게 해줍니다. -- ORDER BY 예 -- 정렬이 이상하게 수행된 것을 확인. SELECT LPAD(' ', 4*(LEVEL-1)) || ENAME ENAME, ENAME ENAME2, EMPNO, LEVEL FROM EMP START WITH JOB='PRESIDENT' CONNECT BY NOCYCLE PRIOR EMPNO=MGR ORDER BY ENAME2; -- ORDER SIBLINGS BY 예 -- 정렬이 정상적으로 수행된 것을 확인. ENAME ENAME2, EMPNO, LEVEL ORDER SIBLINGS BY ENAME2;
216
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습1 - 문제
▷ EMP 테이블을 이용하여 아래와 같이 계층구조 결과테이블을 완성하는 쿼리를 작성하세요. 결과를 보면 상사가 없는 사원 "KING"으로부터 시작하여 레벨이 1이 되고, 그 다음 상사가 "KING"인 부하직원 "JONES", "BLAKE", "CLARK" 이 레벨 2가 됩니다. 이때 부하직원 3명의 정렬순서는 사원번호 순서대로 정렬을 합니다. 그리고 각각의 2레벨 직원들의 부하직원이 3레벨로 연결되고, 다시 3레벨 직원의 부하직원이 4레벨로 연결되는 구조로 이루어집니다. 결과에 추가된 항목은 다음과 같습니다. - LV 는 계층구조의 레벨을 의미합니다. - MGR_ENAME 은 상사의 이름을 의미합니다. - ENAMES 는 최상위 계층에서부터 해당 직원까지 연결된 이름을 나열한 것입니다. EMPNO ENAME LV MGR MGR_ENAME ENAMES 7839 KING 1 7566 JONES 2 KING-JONES 7788 SCOTT 3 KING-JONES-SCOTT 7876 ADAMS 4 KING-JONES-SCOTT-ADAMS 7902 FORD KING-JONES-FORD 7369 SMITH KING-JONES-FORD-SMITH 7698 BLAKE KING-BLAKE 7499 ALLEN KING-BLAKE-ALLEN 7521 WARD KING-BLAKE-WARD 7654 MARTIN KING-BLAKE-MARTIN 7844 TURNER KING-BLAKE-TURNER 7900 JAMES KING-BLAKE-JAMES 7782 CLARK KING-CLARK 7934 MILLER KING-CLARK-MILLER
217
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습1 – 해설1
동일 테이블끼리 EMPNO 와 MGR 을 조인하면 2단계까지 부하직원을 찾을 수 있습니다. 하지만 이 문제는 부하직원의 부하직원을 계속해서 찾아 내려가야만 하는 문제로, 부하직원 이 어느 레벨까지 내려갈지 알 수 없기 때문에 셀프 조인을 사용할 수는 없습니다. 따라서 이 문제를 풀기 위해서는 순환구조로 테이블을 반복적으로 읽어 내려갈 수 있는 재귀쿼리(Recursive Query) 가 필요합니다. 우선 계층구조를 전개하기 위해 필요한 것은 계층구조의 최상위 시작점입니다. 상사와 부하로 연결되는 구조에서 가장 최상위는 상사가 없는 직원이 됩니다. 즉 MGR 이 NULL 인 직원을 시작으로 계층구조를 전개하면 됩니다. START WITH 절은 계층구조의 시작조건을 주는 조건절이 됩니다. START WITH MGR IS NULL 두 번째로 계층구조를 전개하기 위해 필요한 것은 상위와 하위 간의 관계입니다. 이 문제에서는 사원번호(EMPNO)와 상사의 사원번호(MGR) 간의 관계를 이용합니다. 정확하게 표현하면 상위 행의 사원번호와 하위 행의 상사의 사원번호가 서로 연결되는 구조입니다. 계층구조의 상하위간의 관계에 대한 조건은 CONNECT BY 절에 주게 됩니다. 이때 PRIOR 는 상위에 해당하는 값임을 의미합니다. SELECT EMPNO , ENAME , MGR FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR
218
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습1 – 해설2
계층구조에서 단계, 레벨을 나타내 주는 함수는 LEVEL입니다. , LEVEL lv 계층구조의 경로를 보여주는 함수는 SYS_CONNECT_BY_PATH입니다. 계층 경로에 표현될 항목과 경로 사이 사이 표현될 구분자를 입력해주면 간단하게 원하는 결과가 나옵니다. 단, 구분자가 맨 앞에 한번 더 나오므로 맨 앞의 구분자는 SUBSTR으로 제거해 보도록 하겠습니다. , SUBSTR(SYS_CONNECT_BY_PATH(ename, '-'), 2) enames 상사의 이름은 어떻게 구할 수 있을까요? MGR 이 있으니 이를 이용해 EMP 테이블과 조인해서 구해야 할까요? , (SELECT ename FROM emp b WHERE b.empno = a.mgr) mgr_ename FROM emp a 여기까지 생각하셨다면 일단은 문제를 푸는 능력은 갖추고 계신 것입니다. 하지만 계층 쿼리에 대한 이해가 부족하다고 할 수 있겠네요. 앞에서 CONNECT BY 절에 조건을 줄때 사용한 PRIOR 는 상위의 값을 표현할 때 사용한다고 설명을 드렸습니다. 따라서 상위의 이름값을 가져오고 싶다면 간단하게 PRIOR ename 이라고 적어 주기만 하면 됩니다. , PRIOR ename mgr_ename
219
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습1 – 해설3
마지막으로 정렬입니다. 부하직원은 사원번호 순으로 정렬해야 합니다. 일반적인 정렬구문을 사용해 보겠습니다. SELECT empno , ename , LEVEL lv , mgr , PRIOR ename mgr_ename , SUBSTR(SYS_CONNECT_BY_PATH(ename, '-'), 2) enames FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr ORDER BY empno 일반 정렬 구문 결과를 보면 전체 자료가 사원번호 순서대로 정렬이 되어 계층구조가 흐트러진 것을 확인 할 수 있습니다. 우리가 원하는 결과는 계층구조는 그대로 유지하면서 부하사원들끼리의 순서만 정렬해주는 것입니다. 이때 사용되는 구문은 ORDER SIBLINGS BY 구문입니다. ORDER SIBLINGS BY empno [ 정 답 ] SELECT EMPNO , ENAME , LEVEL LV , MGR , PRIOR ENAME MGR_ENAME , SUBSTR(SYS_CONNECT_BY_PATH(ENAME, '-'), 2) ENAMES FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY EMPNO ;
220
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습2 - 문제
테이블 : JONGHB01 테이블 : JONGHB02 ▷ 다음과 같은 결과 만드는 쿼리를 작성 하시오. 1) 2) LEVEL ACCOUNT_CD PACCOUNT_CD 1 100 2 120 3 121 122 123 130 131 140 141 ACCOUNT_CD PACCOUNT_CD 100 120 130 122 121 123 131 140 141 CREATE TABLE JONGHB02( YYMMDD VARCHAR2(08) NOT NULL, ACCOUNT_CD VARCHAR2(04) NOT NULL, ACCOUNT_AM NUMBER, CONSTRAINT JONGHB02_PK PRIMARY KEY(YYMMDD,ACCOUNT_CD) ); INSERT INTO JONGHB02 VALUES (' ','122', 4000); INSERT INTO JONGHB02 VALUES (' ','130', 3000); INSERT INTO JONGHB02 VALUES (' ','120', 2150); INSERT INTO JONGHB02 VALUES (' ','141', 2030); INSERT INTO JONGHB02 VALUES (' ','131', 2570); CREATE TABLE JONGHB01 ( ACCOUNT_CD VARCHAR2(04) NOT NULL, PACCOUNT_CD VARCHAR2(04), CONSTRAINT JONGHB01_PK PRIMARY KEY (ACCOUNT_CD) INSERT INTO JONGHB01 VALUES ('100',''); INSERT INTO JONGHB01 VALUES ('120','100'); INSERT INTO JONGHB01 VALUES ('130','100'); INSERT INTO JONGHB01 VALUES ('122','120'); INSERT INTO JONGHB01 VALUES ('121','120'); INSERT INTO JONGHB01 VALUES ('123','120'); INSERT INTO JONGHB01 VALUES ('131','130'); INSERT INTO JONGHB01 VALUES ('140','100'); INSERT INTO JONGHB01 VALUES ('141','140'); SELECT level, account_cd, paccount_cd FROM jonghb01 CONNECT BY PRIOR account_cd = paccount_cd START WITH account_cd = '100'; SELECT a.yymmdd, b.account_cd, sum(a.account_am) FROM jonghb02 a , jonghb01 b WHERE a.account_cd IN ( SELECT account_cd START WITH account_cd = b.account_cd ) GROUP BY a.yymmdd, b.account_cd; CREATE TABLE jonghb03 ( C_CODE VARCHAR2(15) NOT NULL, P_CODE VARCHAR2(15), CONSTRAINT jonghb03_PK PRIMARY KEY (C_CODE) INSERT INTO jonghb03 VALUES ( '000',''); INSERT INTO jonghb03 VALUES ( '222','220'); INSERT INTO jonghb03 VALUES ( '200','000'); INSERT INTO jonghb03 VALUES ( '210','200'); INSERT INTO jonghb03 VALUES ( '212','210'); INSERT INTO jonghb03 VALUES ( '110','100'); INSERT INTO jonghb03 VALUES ( '220','200'); INSERT INTO jonghb03 VALUES ( '221','220'); INSERT INTO jonghb03 VALUES ( '100','000'); INSERT INTO jonghb03 VALUES ( '111','110'); INSERT INTO jonghb03 VALUES ( '120','100'); INSERT INTO jonghb03 VALUES ( '121','120'); INSERT INTO jonghb03 VALUES ( '122','120'); INSERT INTO jonghb03 VALUES ( '112','110'); INSERT INTO jonghb03 VALUES ( '211','210'); INSERT INTO jonghb03 VALUES ( '999','100'); CREATE TABLE jonghb04 ( C_CODE_DESC VARCHAR2(30), CONSTRAINT jonghb04_PK PRIMARY KEY (C_CODE) INSERT INTO jonghb04 VALUES ( '999','Parent level is 100'); INSERT INTO jonghb04 VALUES ('000','The highest level is'); INSERT INTO jonghb04 VALUES ( '222','Parent level is 220'); INSERT INTO jonghb04 VALUES ( '200','Parent level is 000'); INSERT INTO jonghb04 VALUES ( '210','Parent level is 200'); INSERT INTO jonghb04 VALUES ( '212','Parent level is 210'); INSERT INTO jonghb04 VALUES ( '110','Parent level is 100'); INSERT INTO jonghb04 VALUES ( '220','Parent level is 200'); INSERT INTO jonghb04 VALUES ( '221','Parent level is 220'); INSERT INTO jonghb04 VALUES ( '100','Parent level is 000'); INSERT INTO jonghb04 VALUES ( '111','Parent level is 110'); INSERT INTO jonghb04 VALUES ( '120','Parent level is 100'); INSERT INTO jonghb04 VALUES ( '121','Parent level is 120'); INSERT INTO jonghb04 VALUES ( '122','Parent level is 120'); INSERT INTO jonghb04 VALUES ( '112','Parent level is 110'); INSERT INTO jonghb04 VALUES ( '211','Parent level is 210'); SELECT a.lev, a.c_code, b.c_code_desc, a.p_code, c.c_code_desc FROM ( SELECT level lev, c_code, p_code FROM jonghb03 START WITH p_code = '000' AND c_code > ' ' CONNECT BY PRIOR c_code = p_code AND c_code > ' ' ) a , jonghb04 b , jonghb04 c WHERE b.c_code = a.c_code AND c.c_code = a.p_code ORDER BY a.c_code, a.lev; YYMMDD ACCOUNT_CD SUM(ACCOUNT_AM) 100 13750 120 6150 122 4000 130 5570 131 2570 140 2030 141 YYMMDD ACCOUNT_CD ACCOUNT_AM 122 4000 130 3000 120 2150 141 2030 131 2570
221
Advanced SQL 03 3. 계층형 구조 ◈ 계층형 구조 쿼리 실습3 - 문제
테이블 : JONGHB 테이블 : JONGHB02 ▷ 다음과 같은 결과 만드는 쿼리를 작성 하시오. LEV C_CODE C_CODE_DESC P_CODE P_CODE_DESC 1 100 Parent level is 000 000 The highest level is 2 110 Parent level is 100 3 111 Parent level is 110 112 120 121 Parent level is 120 122 200 210 Parent level is 200 211 Parent level is 210 212 220 221 Parent level is 220 222 999 C_CODE P_CODE 000 100 110 111 112 120 121 122 200 210 211 212 220 221 222 999 C_CODE C_CODE_DESC 000 The highest level is 100 Parent level is 000 110 Parent level is 100 111 Parent level is 110 112 120 121 Parent level is 120 122 200 210 Parent level is 200 211 Parent level is 210 212 220 221 Parent level is 220 222 999 CREATE TABLE JONGHB02( YYMMDD VARCHAR2(08) NOT NULL, ACCOUNT_CD VARCHAR2(04) NOT NULL, ACCOUNT_AM NUMBER, CONSTRAINT JONGHB02_PK PRIMARY KEY(YYMMDD,ACCOUNT_CD) ); INSERT INTO JONGHB02 VALUES (' ','122', 4000); INSERT INTO JONGHB02 VALUES (' ','130', 3000); INSERT INTO JONGHB02 VALUES (' ','120', 2150); INSERT INTO JONGHB02 VALUES (' ','141', 2030); INSERT INTO JONGHB02 VALUES (' ','131', 2570); CREATE TABLE JONGHB01 ( ACCOUNT_CD VARCHAR2(04) NOT NULL, PACCOUNT_CD VARCHAR2(04), CONSTRAINT JONGHB01_PK PRIMARY KEY (ACCOUNT_CD) INSERT INTO JONGHB01 VALUES ('100',''); INSERT INTO JONGHB01 VALUES ('120','100'); INSERT INTO JONGHB01 VALUES ('130','100'); INSERT INTO JONGHB01 VALUES ('122','120'); INSERT INTO JONGHB01 VALUES ('121','120'); INSERT INTO JONGHB01 VALUES ('123','120'); INSERT INTO JONGHB01 VALUES ('131','130'); INSERT INTO JONGHB01 VALUES ('140','100'); INSERT INTO JONGHB01 VALUES ('141','140'); SELECT level, account_cd, paccount_cd FROM jonghb01 CONNECT BY PRIOR account_cd = paccount_cd START WITH account_cd = '100'; SELECT a.yymmdd, b.account_cd, sum(a.account_am) FROM jonghb02 a , jonghb01 b WHERE a.account_cd IN ( SELECT account_cd START WITH account_cd = b.account_cd ) GROUP BY a.yymmdd, b.account_cd; CREATE TABLE jonghb03 ( C_CODE VARCHAR2(15) NOT NULL, P_CODE VARCHAR2(15), CONSTRAINT jonghb03_PK PRIMARY KEY (C_CODE) INSERT INTO jonghb03 VALUES ( '000',''); INSERT INTO jonghb03 VALUES ( '222','220'); INSERT INTO jonghb03 VALUES ( '200','000'); INSERT INTO jonghb03 VALUES ( '210','200'); INSERT INTO jonghb03 VALUES ( '212','210'); INSERT INTO jonghb03 VALUES ( '110','100'); INSERT INTO jonghb03 VALUES ( '220','200'); INSERT INTO jonghb03 VALUES ( '221','220'); INSERT INTO jonghb03 VALUES ( '100','000'); INSERT INTO jonghb03 VALUES ( '111','110'); INSERT INTO jonghb03 VALUES ( '120','100'); INSERT INTO jonghb03 VALUES ( '121','120'); INSERT INTO jonghb03 VALUES ( '122','120'); INSERT INTO jonghb03 VALUES ( '112','110'); INSERT INTO jonghb03 VALUES ( '211','210'); INSERT INTO jonghb03 VALUES ( '999','100'); CREATE TABLE jonghb04 ( C_CODE_DESC VARCHAR2(30), CONSTRAINT jonghb04_PK PRIMARY KEY (C_CODE) INSERT INTO jonghb04 VALUES ( '999','Parent level is 100'); INSERT INTO jonghb04 VALUES ('000','The highest level is'); INSERT INTO jonghb04 VALUES ( '222','Parent level is 220'); INSERT INTO jonghb04 VALUES ( '200','Parent level is 000'); INSERT INTO jonghb04 VALUES ( '210','Parent level is 200'); INSERT INTO jonghb04 VALUES ( '212','Parent level is 210'); INSERT INTO jonghb04 VALUES ( '110','Parent level is 100'); INSERT INTO jonghb04 VALUES ( '220','Parent level is 200'); INSERT INTO jonghb04 VALUES ( '221','Parent level is 220'); INSERT INTO jonghb04 VALUES ( '100','Parent level is 000'); INSERT INTO jonghb04 VALUES ( '111','Parent level is 110'); INSERT INTO jonghb04 VALUES ( '120','Parent level is 100'); INSERT INTO jonghb04 VALUES ( '121','Parent level is 120'); INSERT INTO jonghb04 VALUES ( '122','Parent level is 120'); INSERT INTO jonghb04 VALUES ( '112','Parent level is 110'); INSERT INTO jonghb04 VALUES ( '211','Parent level is 210'); SELECT a.lev, a.c_code, b.c_code_desc, a.p_code, c.c_code_desc FROM ( SELECT level lev, c_code, p_code FROM jonghb03 START WITH p_code = '000' AND c_code > ' ' CONNECT BY PRIOR c_code = p_code AND c_code > ' ' ) a , jonghb04 b , jonghb04 c WHERE b.c_code = a.c_code AND c.c_code = a.p_code ORDER BY a.c_code, a.lev;
222
PL/SQL 기초 04 1. PL/SQL 개요 ◈ PL/SQL 이란
▷ PL/SQL 은 Oracle’s Procedural Language extension to SQL 의 약자 입니다. ▷ SQL문장에서 변수정의, 조건처리(IF), 반복처리(LOOP, WHILE, FOR)등을 지원하며, 오라클 자체에 내장되어 있는 Procedure Language 입니다. ▷ DECLARE문을 이용하여 정의되며, 선언문의 사용은 선택 사항 입니다. ▷ PL/SQL 문은 블록 구조로 되어 있고 PL/SQL자신이 컴파일 엔진을 가지고 있습니다. ◈ PL/SQL의 장점 ▷ PL/SQL 문은 BLOCK 구조로 다수의 SQL 문을 한번에 ORACLE DB로 보내서 처리하므로 수행속도를 향상 시킬 수 있습니다. ▷ PL/SQL 의 모든 요소는 하나 또는 두개 이상의 블록으로 구성하여 모듈화가 가능합니다. ▷ 보다 강력한 프로그램을 작성하기 위해서 큰 블록안에 소블럭을 위치시킬 수 있습니다. ▷ VARIABLE, CONSTANT, CURSOR, EXCEPTION을 정의하고, SQL문장과 Procedural 문장에서 사용 합니다. ▷ 단순, 복잡한 데이터 형태의 변수를 선언 합니다. ▷ 테이블의 데이터 구조와 컬럼명에 준하여 동적으로 변수를 선언 할 수 있습니다. ▷ EXCEPTION 처리 루틴을 이용하여 Oracle Server Error를 처리 합니다. ▷ 사용자 정의 에러를 선언하고 EXCEPTION 처리 루틴으로 처리 가능 합니다.
223
PL/SQL 기초 04 2. PL/SQL Block의 구조 ◈ PL/SQL Block Structure
▷ PL/SQL 블록은 선언부(선택적), 실행부(필수적), 예외 처리부(선택적)로 구성되어 있고, BEGIN과 END 키워드는 반드시 기술해 주어야 합니다. ▷ PL/SQL 블록에서 사용하는 변수는 블록에 대해 논리적으로 선언할 수 있고 사용할 수 있습니다. DECLARE - Optional - Variables , curs ors , us er-defined exceptions BEGIN - Mandatory - SQL Statements - PL/SQL Statements EXCEPTION - Actions to perform when errors occur END DECLARE BEGIN EXCEPTION END; Declarative Section(선언부) Executable Section(실행부) Exception Handling Section(선언부)
224
PL/SQL 기초 04 2. PL/SQL Block의 구조 ◈ PL/SQL Block Structure
▷ Declarative Section(선언부) - 변수, 상수, CURSOR, USER_DEFINE Exception 선언 ▷ Executable Section(실행부) - SQL, 반복분, 조건문 실행 - 실행부는 BEGIN으로 시작하고 END로 종료됩니다. - 실행문은 프로그램 내용이 들어가는 부분으로서 필수적으로 사용되어야 합니다. ▷ Exception Handling Section(예외처리) - 예외에 대한 처리. - 일반적으로 오류를 정의하고 처리하는 부분으로 선택 사항입니다. ◈ PL/SQL 프로그램의 작성 요령 ▷ PL/SQL 블록내에서는 한 문장이 종료할 때마다 세미콜론(;)을 사용 합니다. ▷ END뒤에 세미콜론(;)을 사용하여 하나의 블록이 끝났다는 것을 명시 합니다. ▷ PL/SQL 블록의 작성은 편집기를 통해 파일로 작성할 수도 있고, SQL 프롬프트에서 바로 작성 할 수도 있습니다. ▷ SQL*PLUS 환경에서는 DECLARE나 BEGIN이라는 키워드로 PL/SQL블럭이 시작하는 것을 알 수 있습니다. ▷ 단일행 주석 : -- ▷ 여러행 주석 : /* */ ▷ PL/SQL 블록은 행에 / 가 있으면 종결 됩니다.
225
PL/SQL 기초 04 3. PL/SQL Block의 유형 ◈ PL/SQL Block의 유형
[ Anonymous ] [ Procedure ] [ Function ] ▷ Anonymous Block (익명 블록) 이름이 없는 블록을 의미 하며, 실행하기 위해 프로그램 안에서 선언 되고 실행 시에 실행을 위해 PL/SQL 엔진으로 전달 됩니다. 선행 컴파일러 프로그램과 SQL*Plus 또는 서버 관리자에서 익명의 블록을 내장 할 수 있습니다. ▷ Procedure (프로시저) 특정 작업을 수행할 수 있는 이름이 있는 PL/SQL 블록으로서, 매개 변수를 받을 수 있고, 반복적으로 사용할 수 있습니다. 보통 연속 실행 또는 구현이 복잡한 트랜잭션을 수행하는 PL/SQL블록을 데이터베이스에 저장하기 위해 생성 합니다. ▷ Function (함수) 보통 값을 계산하고 결과값을 반환하기 위해서 함수를 많이 사용 합니다. 대부분 구성이 프로시저와 유사하지만 IN 파라미터만 사용 할 수 있고, 반드시 반환 될 값의 데이터 타입을 RETURN문에 선언해야 합니다. 또한 PL/SQL블록 내에서 RETURN문을 통해서 반드시 값을 반환 해야 합니다. FUNCTION name RETURN datatype IS BEGIN -- statements RETURN value; [ EXCEPTION ] END ; PROCEDURE name IS BEGIN -- statements [ EXCEPTION ] END ; [ DECLARE ] BEGIN -- statements [ EXCEPTION ] END ;
226
PL/SQL 기초 04 4. 프로시저(PROCEDURE) ◈ 프로시저(Procedure)란?
▷ 특정 작업을 수행 하는, 이름이 있는 PL/SQL BLOCK 입니다. ▷ 매개 변수를 받을 수 있고, 반복적으로 사용 할 수 있는 BLOCK 입니다. ▷ 보통 연속 실행 또는 구현이 복잡한 트랜잭션을 수행하는 PL/SQL BLOCK을 데이터베이스에 저장하기 위해 생성 합니다. ◈ 프로시저 문법 CREATE OR REPLACE procedure name IN argument OUT argument IN OUT argument IS [변수의 선언] BEGIN --> 필수 [PL/SQL Block] -- SQL문장, PL/SQL제어 문장 [EXCEPTION] --> 선택 -- error가 발생할 때 수행하는 문장 END; --> 필수 ▷ CREATE OR REPLACE 구문을 사용하여 생성 합니다. ▷ IS 로 PL/SQL의 블록을 시작 합니다. ▷ LOCAL 변수는 IS 와 BEGIN 사이에 선언 합니다.
227
PL/SQL 기초 04 4. 프로시저(PROCEDURE) ◈ 프로시저 작성 예제
- 프로시저의 이름은 update_sal 입니다. - update_sal 프로시저는 사번을 입력받아 급여를 인상 합니다. - 프로시저를 끝마칠 때에는 항상 "/"를 지정 합니다. CREATE OR REPLACE PROCEDURE update_sal /* IN Parameter */ (v_empno IN NUMBER) IS BEGIN UPDATE emp SET sal = sal * 1.1 WHERE empno = v_empno; COMMIT; END update_sal; ◈ 프로시저 실행 예제 EXECUTE 문을 이용해 프로시저를 실행 합니다. EXECUTE update_sal(7369); PL/SQL 처리가 정상적으로 완료되었습니다.
228
PL/SQL 기초 04 5. 함수(FUNCTION) ◈ 함수(Function)란
▷ 보통 값을 계산하고 결과 값을 반환하기 위해서 함수를 많이 사용 합니다. ▷ 대부분 구성이 프로시저와 유사 하지만 IN 파라미터만 사용 할 수 있습니다. ▷ 반드시 반환 될 값의 데이터 타입을 RETURN문에 선언해야 합니다. ▷ 또한 PL/SQL블록 내에서 RETURN문을 통해서 반드시 값을 반환해야 합니다. ◈ 함수 문법 - PL/SQL 블록에는 적어도 한 개의 RETURN 문이 있어야 합니다. - PL/SQL Block은 함수가 수행 할 내용을 정의한 몸체부분입니다. CREATE OR REPLACE FUNCTION function name [(argument...)] RETURN datatype -- datatype은 반환되는 값의 datatype입니다. IS [변수 선언 부분] BEGIN [PL/SQL Block] RETURN 변수; -- 리턴문이 꼭 존재해야 합니다 END;
229
PL/SQL 기초 04 5. 함수(FUNCTION) ◈ 함수 작성 예제
CREATE OR REPLACE FUNCTION FC_update_sal (v_empno IN NUMBER) RETURN NUMBER -- 리턴되는 변수의 데이터타입을 꼭 정의해야 합니다 IS v_sal emp.sal%type; -- %type 변수가 사용(스칼라 데이터 타입 참고) BEGIN UPDATE emp SET sal = sal * 1.1 WHERE empno = v_empno; COMMIT; SELECT sal INTO v_sal FROM emp RETURN v_sal; -- 리턴문이 꼭 존재해야 합니다 END;
230
PL/SQL 기초 04 6. 스칼라 데이터 타입 ◈ 일반변수 선언 문법
▷ Identifier(변수)의 이름은 s ql의 object명과 동일한 규칙을 따른다. ▷ Identifier를 상수로 지정하고 싶은 경우는 CONSTANT라는 KEYWORD를 명시하고 반드시 초기 값을 할당 합니다. ▷ NOT NULL이 정의되어 있으면 초기값을 반드시 지정하고, 정의되어 있지 않을 때는 생략 가능합니다. ▷ 초기값은 할당 연산자(:=)를 사용하여 정의 합니다. ▷ 초기값을 정의하지 않으면 Identifier는 NULL값을 가지게 됩니다. ▷ 일반적으로 한 줄에 한 개의 Identifier를 정의 합니다. identifier [CONSTANT] 데이터 타입 [NOT NULL] [:= 상수 값이나 표현식] ; ◈ 일반변수 선언 예제 -- 숫자형 상수 선언(변할 수 없다) v_price CONTANT NUMBER(4,2) := ; v_name VARCHAR2(20) ; v_Bir_Type CHAR(1) ; -- NOT NULL의 TRUE로 초기화 v_flag BOOLEAN NOT NULL := TRUE ; v_birthday DATE;
231
PL/SQL 기초 04 6. 스칼라 데이터 타입 ◈ %TYPE데이터형
CREATE OR REPLACE PROCEDURE Emp_Info -- IN Parameter ( p_empno IN emp.empno%TYPE ) IS -- %TYPE 데이터형 변수 선언 v_empno emp.empno%TYPE; v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; BEGIN DBMS_OUTPUT.ENABLE; -- %TYPE 데이터형 변수 사용 SELECT empno, ename, sal INTO v_empno, v_ename, v_sal FROM emp WHERE empno = p_empno ; -- 결과값 출력 DBMS_OUTPUT.PUT_LINE( '사원번호 : ' || v_empno ); DBMS_OUTPUT.PUT_LINE( '사원이름 : ' || v_ename ); DBMS_OUTPUT.PUT_LINE( '사원급여 : ' || v_sal ); END; ▷ %TYPE 데이터형은 기술한 데이터베이스 테이블의 컬럼 데이터 타입을 모를 경우 사용할 수 있고, 코딩 이후 데이터 베이스 컬럼의 데이터 타입이 변경될 경우 다시 수정할 필요가 없습니다. ▷ 이미 선언된 다른 변수나 데이터베이스 컬럼의 데이터 타입을 이용하여 선언 합니다. ▷ 데이터베이스 테이블과 컬럼 그리고 이미 선언한 변수명이 %TYPE앞에 올 수 있습니다. ▷ %TYPE 속성을 이용하여 얻을 수 있는 장점 - DB column definition을 정확히 알지 못하는 경우에 사용 - DB column definition이 변경 되어도 다시 PL/SQL을 고칠 필요가 없습니다. -- DBMS_OUTPUT 결과값을 화면에 출력 하기위해 SET SERVEROUTPUT ON; -- 실행 결과 EXECUTE Emp_Info(7369); 사원번호 : 7369 사원이름 : SMITH 사원급여 : 880
232
PL/SQL 기초 04 7. 복합 데이터 타입 ◈ %ROWTYPE
CREATE OR REPLACE PROCEDURE RowType_Test ( p_empno IN emp.empno%TYPE ) IS -- %ROWTYPE 변수 선언, -- emp테이블의 속성을 그대로 사용할 수 있습니다. v_emp emp%ROWTYPE ; BEGIN DBMS_OUTPUT.ENABLE; -- %ROWTYPE 변수 사용 SELECT empno, ename, hiredate INTO v_emp.empno, v_emp.ename, v_emp.hiredate FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE( '사원번호 : ' || v_emp.empno ); DBMS_OUTPUT.PUT_LINE( '사원이름 : ' || v_emp.ename ); DBMS_OUTPUT.PUT_LINE( '입 사 일 : ' || v_emp.hiredate ); END; ▷ 하나 이상의 데이터값을 갖는 데이터 타입으로 배열과 비슷한 역할을 하고 재사용이 가능합니다. %ROWTYPE 데이터 형과, PL/SQL테이블과 레코드는 복합 데이터 타입에 속합니다. ▷ 테이블이나 뷰 내부의 컬럼 데이터형, 크기, 속석등을 그대로 사용 할 수 있습니다. ▷ %ROWTYPE 앞에 오는 것은 데이터베이스 테이블 이름입니다. ▷ 지정된 테이블의 구조와 동일한 구조를 갖는 변수를 선언 할 수 있습니다. ▷ 데이터베이스 컬럼들의 수나 DATATYPE을 알지 못할 때 편리 합니다. ▷ 테이블의 데이터 컬럼의 DATATYPE이 변경 될 경우 프로그램을 재 수정할 필요가 없습니다. -- DBMS_OUTPUT.PUT_LINE을 출력하기 위해 사용 SET SERVEROUTPUT ON ; -- 실행 결과 EXECUTE RowType_Test(7900); 사원번호 : 7900 사원이름 : JAMES 입 사 일 : 81/12/03
233
PL/SQL 기초 04 8. PL/SQL 테이블 ◈ PL/SQL 테이블
▷ PL/SQL 에서의 테이블은 오라클 SQL에서의 테이블과는 다릅니다. PL/SQL에서의 테이블은 일종의 일차원 배열이라고 생각하면 이해하기 쉬울 것입니다. ▷ 테이블은 크기에 제한이 없으면 그 ROW의 수는 데이터가 들어옴에 따라 자동 증가 합니다. ▷ BINARY_INTEGER 타입의 인덱스 번호로 순서가 정해집니다. ▷ 하나의 테이블에 한 개의 컬럼 데이터를 저장 합니다. ◈ PL/SQL 테이블 문법 -- 선언 예제 TYPE prdname_table IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER; -- prdname_table 테이블타입으로 prdname_tab변수를 선언해서 사용 prdname_tab prdname_table TYPE table_name IS TABLE OF datatype INDEX BY BINARY_INTEGER Identifier type_name;
234
PL/SQL 기초 04 8. PL/SQL 테이블 ◈ PL/SQL 테이블 예제 -- 테이블 변수에 검색된 결과를 넣는다
CREATE OR REPLACE PROCEDURE Table_Test (v_deptno IN emp.deptno%TYPE) IS -- 각 컬럼에서 사용할 테이블의 선언 TYPE empno_table IS TABLE OF emp.empno%TYPE INDEX BY BINARY_INTEGER; TYPE ename_table IS TABLE OF emp.ename%TYPE TYPE sal_table IS TABLE OF emp.sal%TYPE -- 테이블타입으로 변수를 선언해서 사용 empno_tab empno_table ; ename_tab ename_table ; sal_tab sal_table; i BINARY_INTEGER := 0; BEGIN DBMS_OUTPUT.ENABLE; FOR emp_list IN(SELECT empno, ename, sal FROM emp WHERE deptno = v_deptno) LOOP /* emp_list는 자동선언되는 BINARY_INTEGER형 변수로 1씩 증가합니다. emp_list대신 다른 문자열 사용가능 */ i := i + 1; -- 테이블 변수에 검색된 결과를 넣는다 empno_tab(i) := emp_list.empno ; ename_tab(i) := emp_list.ename ; sal_tab(i) := emp_list.sal ; END LOOP; -- 1부터 i까지 FOR 문을 실행 FOR cnt IN 1..i LOOP -- TABLE변수에 넣은 값을 뿌려줌 DBMS_OUTPUT.PUT_LINE( '사원번호 : ' || empno_tab(cnt) ); DBMS_OUTPUT.PUT_LINE( '사원이름 : ' || ename_tab(cnt) ); DBMS_OUTPUT.PUT_LINE( '사원급여 : ' || sal_tab(cnt)); END; -- (DBMS_OUTPUT.PUT_LINE을 출력하기 위해 사용) SET SERVEROUTPUT ON ; 실행 결과 EXECUTE Table_Test(10); 사원번호 : 7782 사원이름 : CLARK 사원급여 : 2450 사원번호 : 7839 사원이름 : KING 사원급여 : 5000 사원번호 : 7934 사원이름 : MILLER 사원급여 : 1300
235
PL/SQL 기초 04 9. PL/SQL 레코드 ◈ PL/SQL 레코드
▷ 스칼라, RECORD, 또는 PL/SQL TABLE datatype중 하나 이상의 요소로 구성 됩니다. ▷ 논리적 단위로서 필드 집합을 처리할 수 있도록 해 줍니다. ▷ PL/SQL 테이블과 다르게 개별 필드의 이름을 부여할 수 있고, 선언 시 초기화가 가능합니다. ◈ PL/SQL 레코드 문법 -- 선언 예제 TYPE record_test IS RECORD ( record_empno NUMBER, record_ename VARCHAR2(30), record_sal NUMBER); -- record_test 레코드 타입으로 prd_record변수를 선언해서 사용 prd_record record_test; TYPE record_name IS RECORD ( 필드이름1 필드유형1 [ NOT NULL {:= | DEFAULT} 식 ], 필드이름1 필드유형1 [ NOT NULL {:= | DEFAULT} 식 ], 필드이름1 필드유형1 [ NOT NULL {:= | DEFAULT} 식 ],); Identifier type_name;
236
PL/SQL 기초 04 9. PL/SQL 레코드 -- (DBMS_OUTPUT.PUT_LINE을 출력하기 위해 사용)
CREATE OR REPLACE PROCEDURE Record_Test (v_empno IN emp.empno%TYPE) IS -- 하나의 레코드의 세가지의 변수타입 선언 TYPE emp_record IS RECORD ( v_empno NUMBER, v_ename VARCHAR2(30), v_hiredate DATE ); emp_rec emp_record ; BEGIN DBMS_OUTPUT.ENABLE; -- 레코드의 사용 SELECT empno, ename, hiredate INTO emp_rec.v_empno , emp_rec.v_ename , emp_rec.v_hiredate FROM emp WHERE empno = p_empno; DBMS_OUTPUT.PUT_LINE( '사원번호 : ' || emp_rec.v_empno ); DBMS_OUTPUT.PUT_LINE( '사원이름 : ' || emp_rec.v_ename ); DBMS_OUTPUT.PUT_LINE( '입 사 일 : ' || emp_rec.v_hiredate); END; -- (DBMS_OUTPUT.PUT_LINE을 출력하기 위해 사용) SET SERVEROUTPUT ON ; -- 실행 결과 EXECUTE Record_Test(7369); 사원번호 : 7369 사원이름 : SMITH 입 사 일 : 80/12/17
237
PL/SQL 기초 04 10. PL/SQL Table Of Record ◈ PL/SQL Table Of Record
%ROWTYPE으로 선언하면 됩니다. ▷ PL/SQL TABLE과 RECORD의 복합 기능을 합니다. CREATE OR REPLACE PROCEDURE Table_Test IS i BINARY_INTEGER := 0; -- PL/SQL Table of Record의 선언 TYPE dept_table_type IS TABLE OF dept%ROWTYPE INDEX BY BINARY_INTEGER; dept_table dept_table_type; BEGIN FOR dept_list IN (SELECT * FROM dept) LOOP i:= i+1; -- TABLE OF RECORD에 데이터 보관 dept_table(i).deptno := dept_list.deptno ; dept_table(i).dname := dept_list.dname ; dept_table(i).loc := dept_list.loc ; END LOOP; FOR cnt IN 1..i LOOP -- 데이터 출력 DBMS_OUTPUT.PUT_LINE( '부서번호 : ' || dept_table(cnt).deptno || '부서명 : ' || dept_table(cnt).dname || '위치 : ' || dept_table(cnt).loc ); END; ◈ PL/SQL Table Of Record 문법 -- 선언 예제 TYPE dept_table_type IS TABLE OF dept%ROWTYPE INDEX BY BINARY_INTEGER; -- Each element of dept_table is a record dept_table dept_table_type; SET SERVEROUTPUT ON ; EXECUTE Table_test; 부서번호 : 10부서명 : ACCOUNTING위치 : NEW_YORK 부서번호 : 20부서명 : RESEARCH위치 : DALLAS 부서번호 : 30부서명 : 인사과위치 : CHICAGO 부서번호 : 40부서명 : OPERATIONS위치 : BOS%TON
238
PL/SQL 기초 04 11. 반복제어 ( FOR LOOP ) ◈ FOR LOOP 문법
▷ index 는 자동 선언되는 binary_integer형 변수이고, 1씩 증가 합니다. ▷ revers e 옵션이 사용 될 경우 index 는 upper_bound에서 lower_bound로 1씩 감소 합니다. ▷ IN 다음에는 coursor나 select 문이 올 수 있습니다. BEGIN DBMS_OUTPUT.ENABLE; FOR emp_list IN (SELECT ename, sal FROM emp WHERE deptno = 10) LOOP i := i +1 ; -- 테이블에 상품 이름을 저장 ename_tab(i) := emp_list.ename; -- 테이블에 상품 가격을 저장 sal_tab(i) := emp_list.sal; END LOOP; -- 화면에 출력 FOR cnt IN 1..i LOOP DBMS_OUTPUT.PUT_LINE('사원이름 : ' || ename_tab(cnt)); DBMS_OUTPUT.PUT_LINE('사원급여 : ' || sal_tab(cnt)); END; 사원이름 : CLARK 사원급여 : 2450 사원이름 : KING 사원급여 : 5000 사원이름 : MILLER 사원급여 : 1300 FOR index IN [REVERSE] 시작값 .. END값 LOOP statement 1 statement 2 …. END LOOP; DECLARE -- 사원 이름을 출력하기 위한 PL/SQL 테이블 선언 TYPE ename_table IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; -- 사원 급여를 출력하기 위한 PL/SQL 테이블 선언 TYPE sal_table IS TABLE OF emp.sal%TYPE ename_tab ename_table; sal_tab sal_table; i BINARY_INTEGER := 0;
239
PL/SQL 기초 04 12. LOOP문, WHILE문 ◈ LOOP 문법 LOOP PL/SQL statement
▷ EXIT 문이 사용되었을 경우, 무조건 LOOP문을 빠져나간다. ▷ EXITH WHEN 이 사용될 경우 WHEN 절에 LOOP를 빠져 나가는 조건을 제어 할 수 있습니다. END LOOP; DBMS_OUTPUT.PUT_LINE('데이터 입력 완료'); DBMS_OUTPUT.PUT_LINE(v_cnt-100 || '개의 데이터가 입력되었습니다'); END; LOOP PL/SQL statement 다른 LOOP를 포함하여 중첩으로 사용 가능 EXIT [WHEN condition] END LOOP; ◈ WHILE LOOP 문 DECLARE v_cnt NUMBER := 100; BEGIN DBMS_OUTPUT.ENABLE; WHILE v_cnt < 110 LOOP INSERT INTO emp(empno, ename , hiredate) VALUES (emp_seq.nextval, 'test', sysdate); v_cnt := v_cnt+1; EXIT WHEN v_cnt > 110; END LOOP; DBMS_OUTPUT.PUT_LINE('데이터 입력 완료'); DBMS_OUTPUT.PUT_LINE(v_cnt-100 || '개의 데이터가 입력되었습니다'); END; DECLARE v_cnt NUMBER := 100; BEGIN DBMS_OUTPUT.ENABLE ; LOOP INSERT INTO emp(empno, ename , hiredate) VALUES(v_cnt, 'test'||to_char(v_cnt), sysdate); v_cnt := v_cnt+1; EXIT WHEN v_cnt > 110;
240
PL/SQL 기초 04 13. 조건제어 ( IF ) ◈ IF 문법 IF 조건 THEN statement
IF v_deptno = 10 THEN DBMS_OUTPUT.PUT_LINE( ' ACCOUNTING 부서 사원입니다. ' ); ELSIF v_deptno = 20 THEN DBMS_OUTPUT.PUT_LINE( ' RESEARCH 부서 사원입니다. ' ); ELSIF v_deptno = 30 THEN DBMS_OUTPUT.PUT_LINE( ' SALES 부서 사원입니다. ' ); ELSIF v_deptno = 40 THEN DBMS_OUTPUT.PUT_LINE( ' OPERATIONS 부서 사원입니다. ' ); ELSE DBMS_OUTPUT.PUT_LINE( ' 부서가 이상해요... ' ); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE(' 부서가 없네요... '); END ; IF 조건 THEN statement ELSEIF 조건 THEN ELSE END; ◈ IF 문 예제 CREATE OR REPLACE PROCEDURE Dept_Search (p_empno IN emp.empno%TYPE ) IS v_deptno emp.deptno%type ; BEGIN DBMS_OUTPUT.ENABLE; SELECT deptno INTO v_deptno FROM emp WHERE empno = p_empno; -- 프로시저 실행 EXECUTE Dept_Search(7900); 부서가 없네요... EXECUTE Dept_Search(7369); RESEARCH 부서 사원입니다.
241
PL/SQL 기초 04 14. 암시적 커서 ( Implicit Cursor ) ◈ 암시적 커서(Implicit Cursor)
주소입니다. ▷ 오라클 데이터베이스에서 실행되는 모든 SQL문장은 암시적인 커서가 생성되며, 커서 속성을 사용 할 수 있습니다. ▷ 암시적 커서는 SQL 문이 실행되는 순간 자동으로 OPEN과 CLOSE를 실행 합니다. ▷ 암시적 커서의 속성 - SQL%ROWCOUNT : 해당 SQL 문에 영향을 받는 행의 수 - SQL%FOUND : 해당 SQL 영향을 받는 행의 수가 한 개 이상일 경우 TRUE - SQL%NOTFOUND : 해당 SQL 문에 영향을 받는 행의 수가 없을 경우 TRUE - SQL%ISOPEN : 항상 FALSE, 암시적 커서가 열려 있는지의 여부 검색 IS v_sal emp.sal%TYPE; v_update_row NUMBER; BEGIN SELECT sal INTO v_sal FROM emp WHERE empno = p_empno; -- 검색된 데이터가 있을경우 IF SQL%FOUND THEN DBMS_OUTPUT.PUT_LINE('검색한 데이터가 존재합니다 : '||v_sal); END IF; UPDATE emp SET sal = sal*1.1 -- 수정한 데이터의 카운트를 변수에 저장 v_update_row := SQL%ROWCOUNT; DBMS_OUTPUT.PUT_LINE('급여가 인상된 사원 수 : '|| v_update_row); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE(' 검색한 데이터가 없네요... '); END; ◈ 암시적 커서 예제 CREATE OR REPLACE PROCEDURE Implicit_Cursor (p_empno IN emp.empno%TYPE)
242
PL/SQL 기초 04 15. 명시적 커서 ( Explicit Cursor ) ◈ Explicit Cursor의 흐름도
문법(Syntax) ▷ 커서 열기(OPEN) - 커서의 열기는 OPEN문을 사용합니다. - 커서안의 검색이 실행되며 아무런 데이터행을 추출하지 못해도 에러가 발생하지 않습니다. - 문법 : OPEN cursor_name; ▷ 커서 패치(FETCH) - 커서의 FETCH는 현재 데이터 행을 OUTPUT변수에 반환 합니다. - 커서의 SELECT문의 컬럼의 수와 OUTPUT변수의 수가 동일해야 합니다. - 커서 컬럼의 변수의 타입과 OUTPUT변수의 데이터 타입도 동일해야 합니다. - 커서는 한 라인씩 데이터를 패치 합니다. - 문법 : FETCH cursor_name INTO variable1, variable2; ▷ 커서 닫기(CLOSE) - 사용을 맞친 커서는 반드시 닫아 주어야 합니다. - 필요하다면 커서를 다시 열 수 있습니다. - 커서를 닫은 상태에서 FETCH를 할 수 없습니다. - 문법 : CLOSE cursor_name; Declare Open FETCH EMPTY CLOSE 이름있는 SQL 영역 생성 CURSOR의 활성화 커서의 현재 데이터행을 해당 변수에 넘김 현재행의 존재 여부검사 레코드가 없으면 FETCH 하지 않음 커서가 사용한 자원을 해제
243
PL/SQL 기초 04 15. 명시적 커서 ( Explicit Cursor ) ◈ Explicit Cursor 예제
-- 특정 부서의 평균급여와 사원수를 출력.. CREATE OR REPLACE PROCEDURE ExpCursor_Test (v_deptno IN dept.deptno%TYPE) IS CURSOR dept_avg IS SELECT b.dname, COUNT(a.empno) cnt, ROUND(AVG(a.sal),3) salary FROM emp a, dept b WHERE a.deptno = b.deptno AND b.deptno = v_deptno GROUP BY b.dname ; -- 커서를 패치하기 위한 편수 선언 v_dname dept.dname%TYPE; emp_cnt NUMBER; sal_avg NUMBER; BEGIN -- 커서의 오픈 OPEN dept_avg; -- 커서의 패치 FETCH dept_avg INTO v_dname, emp_cnt, sal_avg; DBMS_OUTPUT.PUT_LINE('부서명 : ' || v_dname); DBMS_OUTPUT.PUT_LINE('사원수 : ' || emp_cnt); DBMS_OUTPUT.PUT_LINE('평균급여 : ' || sal_avg); -- 커서의 CLOSE CLOSE dept_avg; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM||'에러 발생 '); END; SET SERVEROUTPUT ON ; EXECUTE ExpCursor_Test(30); 부서명 : SALES 사원수 : 6 평균급여 :
244
PL/SQL 기초 04 16. FOR문에서 커서 사용 ( Cursor FOR Loops ) ◈ FOR문 커서 사용 문법
▷ FOR문을 사용하면 커서의 OPEN, FETCH, CLOSE가 자동 발생하므로 따로 기술할 필요가 없고, 레코드 이름도 자동 선언되므로 따로 선언할 필요가 없습니다. DBMS_OUTPUT.PUT_LINE('부서명 : ' || emp_list.dname); DBMS_OUTPUT.PUT_LINE('사원수 : ' || emp_list.cnt); DBMS_OUTPUT.PUT_LINE('급여합계 : ' || emp_list.salary); END LOOP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM||'에러 발생 '); END; FOR record_name IN cursor_name LOOP statement 1 ….. END LOOP; ◈ 예제 CREATE OR REPLACE PROCEDURE ForCursor_Test IS -- Cursor 선언 CURSOR dept_sum IS SELECT b.dname, COUNT(a.empno) cnt, SUM(a.sal) salary FROM emp a, dept b WHERE a.deptno = b.deptno GROUP BY b.dname; BEGIN -- Cursor를 FOR문에서 실행시킵니다. FOR emp_list IN dept_sum LOOP -- 프로시저 실행 EXECUTE ForCursor_Test; 부서명 : ACCOUNTING 사원수 : 3 급여합계 : 8750 부서명 : RESEARCH 사원수 : 6 급여합계 : 10875 부서명 : SALES 급여합계 : 9305
245
PL/SQL 기초 04 17. 명시적 커서의 속성(Explicit Cursor Attributes)
▷ %ISOPEN - 커서가 OPEN되어 있으면 TRUE - %ISOPEN속성을 이용하여 커서가 열려있는지 알 수 있습니다. ▷ %NOTFOUND - 패치한 데이터가 행을 반환하지 않으면 TRUE - %NOTFOUND속성을 이용하여 루프를 종료 할 시점을 찾습니다. ▷ %FOUND - 패치한 데이터가 행을 반환하면 TRUE ▷ %ROWCOUNT - 현재까지 반환 된 모든 데이터 행의 수 - %ROWCOUNT속성을 이용하여 정확한 숫자만큼의 행을 추출합니다. CURSOR emp_list IS SELECT empno, ename, sal FROM emp; BEGIN DBMS_OUTPUT.ENABLE; OPEN emp_list; LOOP FETCH emp_list INTO v_empno, v_ename, v_sal; -- 데이터를 찾지 못하면 빠져 나갑니다 EXIT WHEN emp_list%NOTFOUND; END LOOP; DBMS_OUTPUT.PUT_LINE('전체데이터 수 ' || emp_list%ROWCOUNT); CLOSE emp_list; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERR MESSAGE : ' || SQLERRM); END; ◈ 예제 CREATE OR REPLACE PROCEDURE AttrCursor_Test IS v_empno emp.empno%TYPE; v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; -- 실행 결과 EXECUTE AttrCursor_Test; 전체데이터 수 15
246
PL/SQL 기초 04 18. 파라미터가 있는 커서(Cursors with Parameters) ◈ 파라미터가 있는 커서
▷ 커서가 OPEN되고 질의가 실행되면 매개 변수 값을 커서에 전달할 수 있습니다. 다른 active set을 원할 때 마다 explicit 커서를 따로 선언해야 합니다. BEGIN DBMS_OUTPUT.ENABLE; DBMS_OUTPUT.PUT_LINE(' * 입력한 부서에 해당하는 사람들 * '); -- Parameter변수의 값을 전달(OPEN될 때 값을 전달한다) FOR emplst IN emp_list(param_deptno) LOOP DBMS_OUTPUT.PUT_LINE('이름 : ' || emplst.ename); END LOOP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERR MESSAGE : ' || SQLERRM); END; CORSOR cursor_name [( parameter_name datatype, …)] IS SELECT statement ◈ 예제 CREATE OR REPLACE PROCEDURE ParamCursor_Test (param_deptno emp.deptno%TYPE) IS v_ename emp.ename%TYPE; -- Parameter가 있는 커서의 선언 CURSOR emp_list(v_deptno emp.deptno%TYPE) IS SELECT ename FROM emp WHERE deptno = v_deptno; -- 실행 결과 EXECUTE ParamCursor_Test(10); * 입력한 부서에 해당하는 사람들 * 이름 : CLARK 이름 : KING 이름 : MILLER
247
PL/SQL 기초 04 19. The WHERE CURRENT OF Clause ◈ The WHERE CURRENT OF
▷ ROWID를 이용하지 않고도 현재 참조하는 행을 갱신하고 삭제할 수 있게 합니다. ▷ 추가적으로 FETCH문에 의해 가장 최근에 처리된 행을 참조하기 위해서 "WHERE CURRENT OF 커서이름 " 절로 DELETE나 UPDATE문 작성이 가능합니다. ▷ 이 절을 사용할 때 참조하는 커서가 있어야 하며, FOR UPDATE절이 커서 선언 query문장 안에 있어야 합니다. 그렇지 않으면 에러가 발생합니다. FOR emplst IN emp_list LOOP -- emp_list커서에 해당하는 사람의 직업을 SALESMAN으로 -- 업데이트 시킵니다. UPDATE emp SET job = 'SALESMAN' WHERE CURRENT OF emp_list; DBMS_OUTPUT.PUT_LINE('수정 성공'); END LOOP; EXCEPTION WHEN OTHERS THEN -- 에러 발생시 에러 메시지 출력 DBMS_OUTPUT.PUT_LINE('ERR MESSAGE : ' || SQLERRM); END; ◈ 예제 CREATE OR REPLACE PROCEDURE where_current IS CURSOR emp_list IS SELECT empno FROM emp WHERE empno = 7934 FOR UPDATE; BEGIN --DBMS_OUTPUT.PUT_LINE명령을 사용하기 위해서 DBMS_OUTPUT.ENABLE; --PLSQL을 실행시키고.. EXECUTE where_current; 수정 성공 -- 데이터를 확인하면 변경된 것을 확인 할 수 있습니다. SELECT job FROM emp WHERE empno = 7934; JOB SALESMAN
248
PL/SQL 기초 04 20. 예외(Exception) ◈ 예외(Exception)란? ◈ 예외처리 문법
구분 할 수 있습니다. 예 외 설 명 처 리 미리 정의된 오라클 서버 오류 (Predefined Oracle Server) PL/SQL에서 자주 발생하는 약20개의 오류 선언할 필요도 없고, 발생시에 예외 절로 자동 트랩(Trap) 됩니다. 미리 정의되지 않은 오라클 서버 오류 (Non-Predefined Oracle Server) 미리 정의된 오라클 서버 오 류를 제외한 모든 오류 선언부에서 선언해야 하고 발생시 자 동 트랩됩니다. 사용자 정의 오류 (User-Defined) 개발자가 정한 조건에 만족하 지 않을경우 발생하는 오류 선언부에서 선언하고 실행부에서 RAISE문을 사용하여 발생시켜야 한다 ◈ 예외처리 문법 - 예외 처리절은 EXCEPTION부터 시작 합니다. - 예외가 발생하면 여러 개의 예외 처리부 중에 하나의 예외 처리부에 트랩(Trap) 됩니다. - WHEN OTHERS절은 맨 마지막 온다. WHEN 예외1[OR 예외2] THEN statement 1 statement 2 …. [ WHEN 예외3[OR 예외4] THEN statement 1… ] [ WHEN OTHERS THEN
249
PL/SQL 기초 04 21. 미리 정의된 예외(Predefined Exceptions) ◈ 미리 정의된 예외 종류 ◈ 예제
▷ NO_DATA_FOUND : SELECT문이 아무런 데이터 행을 반환하지 못할 때 ▷ DUP_VAL_ON_INDEX : UNIQUE 제약을 갖는 컬럼에 중복되는 데이터가 INSERT 될 때 ▷ ZERO_DIVIDE : 0으로 나눌 때 ▷ INVALID_CURSOR : 잘못된 커서 연산 DBMS_OUTPUT.PUT_LINE('부서번호 : ' || v_emp.deptno); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.PUT_LINE('데이터가 존재 합니다.'); DBMS_OUTPUT.PUT_LINE('DUP_VAL_ON_INDEX 에러 발생'); WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('TOO_MANY_ROWS에러 발생'); WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND에러 발생'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('기타 에러 발생'); END; ◈ 예제 CREATE OR REPLACE PROCEDURE PreException_test (v_deptno IN emp.deptno%TYPE) IS v_emp emp%ROWTYPE; BEGIN DBMS_OUTPUT.ENABLE; SELECT empno, ename, deptno INTO v_emp.empno, v_emp.ename, v_emp.deptno FROM emp WHERE deptno = v_deptno ; DBMS_OUTPUT.PUT_LINE('사번 : ' || v_emp.empno); DBMS_OUTPUT.PUT_LINE('이름 : ' || v_emp.ename); -- 프로시저 실행 EXECUTE PreException_Test(20); TOO_MANY_ROWS에러 발생 - SELECT문의 결과가 1개 이상의 행을 리턴하기 때문입니다.. - TOO_MANY_ROWS를 피하기 위해서는 FOR문이나 LOOP문으로 SELECT문을 처리해야 합니다. --아래와 같이 변경하면 에러가 발생하지 않습니다. FOR emp_list IN (SELECT empno, ename, deptno FROM emp WHERE deptno = v_deptno) LOOP DBMS_OUTPUT.PUT_LINE('사번 : ' || emp_list.empno); DBMS_OUTPUT.PUT_LINE('이름 : ' || emp_list.ename); DBMS_OUTPUT.PUT_LINE('부서번호 : ' || emp_list.deptno); END LOOP;
250
PL/SQL 기초 04 22. 사용자 정의 예외(User-Defined Exceptions) ◈ 사용자 정의 예외 ◈ 예제
▷ 오라클 저장함수 RAISE_APPLICATION_ERROR를 사용하여 오류코드 부터 의 범위 내에서 사용자 정의 예외를 만들 수 있습니다. - STEP 1 : 예외의 이름을 선언 (선언절) - STEP 2 : RAISE문을 사용하여 직접적으로 예외를 발생(실행절) - STEP 3 : 예외가 발생할 경우 해당 예외를 참조한다(예외절) SELECT COUNT(empno) INTO cnt FROM emp WHERE deptno = v_deptno; IF cnt < 5 THEN -- RAISE문을 사용하여 직접적으로 예외를 발생시킵니다. RAISE user_define_error; -- STEP 2 END IF; EXCEPTION -- 예외가 발생할 경우 해당 예외를 참조합니다. WHEN user_define_error THEN -- STEP 3 RAISE_APPLICATION_ERROR(-20001, '부서에 사원이 몇명 안되네요..'); END; ◈ 예제 CREATE OR REPLACE PROCEDURE User_Exception (v_deptno IN emp.deptno%type ) IS -- 예외의 이름을 선언 user_define_error EXCEPTION; -- STEP 1 cnt NUMBER; BEGIN DBMS_OUTPUT.ENABLE; -- 10부서의 사원이 5보다 적기 때문에 사용자 정의 예외가 발생. EXECUTE user_exception(10); BEGIN user_exception(10); END; * 1행에 오류: ORA-20001: 부서에 사원이 몇명 안되네요.. ORA-06512: "SCOTT.USER_EXCEPTION", 줄 17에서 ORA-06512: 줄 1에서 -- 20부서로 실행을 하면 에러가 발생하지 않는 것 을 알 수 있습니다. EXECUTE user_exception(20); PL/SQL 처리가 정상적으로 완료되었습니다.
251
PL/SQL 기초 04 23. SQLCODE, SQLERRM ◈ 사용자 정의 예외
▷ SQLCODE, SQLERRM 구문을 사용해서 WHEN OTHERS문으로 트랩(Trap)되는 오류들의 실제 오류 코드와 설명을 볼 수 있습니다. ▷ SQLCODE : 실행된 프로그램이 성공적으로 종료 하였을 때는 오류번호 0을 포함하며, 그렇지 못할 경우에는 해당 오류코드 번호를 포함합니다. ▷ SQLERRM : SQLCODE에 포함된 오라클 오류 번호에 해당하는 메시지를 가집니다. CREATE OR REPLACE PROCEDURE Errcode_Exception (v_deptno IN emp.deptno%type ) IS v_emp emp%ROWTYPE ; BEGIN DBMS_OUTPUT.ENABLE; -- ERROR발생 for문을 돌려야 됨 SELECT * INTO v_emp FROM emp WHERE deptno = v_deptno; DBMS_OUTPUT.PUT_LINE('사번 : ' || v_emp.empno); DBMS_OUTPUT.PUT_LINE('이름 : ' || v_emp.ename); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERR CODE : ' || TO_CHAR(SQLCODE)); DBMS_OUTPUT.PUT_LINE('ERR MESSAGE : ' || SQLERRM); END; SQLCODE Value 설 명 오류 없이 성공적으로 종료 1 사용자 정의 예외 번호 +100 NO_DATA_FOUND 예외 번호 음수 위에 것을 제외한 오라클 서버 에러 번호 -- 실행예제 EXECUTE Errcode_Exception(30); RR CODE : -1422 ERR MESSAGE : ORA-01422: 실제 인출은 요구된 것보다 많은 수의 행을 추출합니다
252
SQL 성능향상 기초 05 1. SQL Processing 및 Optimizer의 이해 ◈ SQL 실행 단계
SQL 실행은 Parsing Execute Statement Fetch Rows 의 3 단계로 이루어집니다. ▷ Parsing Parsing 단계에서는 SQL문의 Syntax, 실행권한 확인이 이루어지고, 해당 SQL문이 Shared SQL Area에 존재하는지 확인합니다. 만약 동일한 SQL문이 존재한다면 Parsing작업은 일어나지 않게 되고, 동일 SQL이 존재하지 않으면 Oracle은 Share SQL Area를 할당하는 Parsing 작업을 하게 됩니다. 이 단계에서 SQL문의 최적화된 실행계획이 작성됩니다. ▷ Execute Statement 필요한 정보와 자원을 가지고 실제 SQL문이 실행됩니다. 이 단계에서 데이터베이스에 대한 Physical, Logical Read/Write 가 수행합니다. 최소한의 I/O로서 원하는 결과를 추출하는 것이 성능 향상의 요소가 됩니다. Bind Variable이 사용되었다면 Execution이 일어나기 전에 Binding이 먼저 일어나게 됩니다. ▷ Fetch Rows SQL문이 요청한 Row를 추출합니다.
253
SQL 성능향상 기초 05 1. SQL Processing 및 Optimizer의 이해 ◈ Optimizer
▷ 옵티마이저 (Optimizer) : SQL 을 가장 빠르고 효율적으로 수행할 최적의 처리 경로를 생성해 주는 DBMS 내부 핵심엔진 ▷ SQL 로 결과집합 요구하면, 옵티마이저가 자동으로 처리경로 (실행계획 : Execution Plan) 를 생성해줍니다. ▷ 옵티마이저의 SQL 최적화 과정 - 사용자 쿼리수행을 위해, 후보군이 될만한 실행계획을 찾습니다. - 데이터 딕셔너리에 미리 수집해 놓은 오브젝트 통계 및 시스템 통계정보를 이용하여 각 실행계획의 예상비용을 산정. - 각 실행계획을 비교하여 최저비용을 갖는 하나를 선택. - (위 과정은 비용기반 옵티마이저의 SQL 최적화 과정입니다) ◈ Optimizer 종류 ▷ Rule-Based Optimizer (RBO) : 규칙기반 옵티마이저 - 휴리스틱 옵티마이저라 불립니다. - 미리 정해놓은 규칙 (액세스 경로별 우선순위) 으로 액세스 경로 평가하여 실행계획 선택합니다. - 인덱스 구조, 연산자, 조건절 형태가 순위 결정짓는 주 요인입니다. ▷ Cost-Based Optimizer (CBO) : 비용기반 옵티마이저 - 비용을 기반으로 최적화 수행. - 비용(Cost) 이란 쿼리수행 시 소요되는 일량, 시간을 뜻하며, 이는 예상치 입니다. - 미리 구해둔 테이블, 인덱스에 대한 통계정보를 기초로 오퍼레이션 단계별 예상비용 산정, 이를 합한 총 비용이 가장 낮은 - 실행계획을 선택. - 오브젝트 통계 항목 : 레코드 개수, 블록 개수, 평균 행 길이, 컬럼 값의 수, 컬럼 값 분포, 인덱스 높이 (Height), 클러스터링 팩터, 하드웨어 특성을 반영한 시스템 정보(CPU 속도, 디스크 I/O 속도 등) - ORACLE 은 RBO에서 출발하였으나, 타 DBMS는 CBO채택. Oracle 도 10g 부터 RBO 지원 중단함.
254
SQL 성능향상 기초 05 1. SQL Processing 및 Optimizer의 이해 ◈ SQL 실행 PLAN 보는 법
어떤 방법과 어떤 순서로 실행되는지 살펴보아야 하는 데 이는 실행 PLAN(Execution Plan, 실행계획)을 통해 알 수 있습니다. ▷ 실행계획(Execution Plan)이란 SQL에서 요구한 사항을 처리하기 위한 절차와 방법을 의미합니다. ▷ 실행계획을 구성하는 요소에는 조인순서(Join Order), 조인기법(Join Method), 엑세스 기법(Access Method), 최적화 정보(Optimization Information), 연산(Operation) 등이 있습니다. ▷ SQL Developer 툴에서 F10버튼을 누르면 현재 SQL의 실행 PLAN이 아래 창에 나타납니다.
255
SQL 성능향상 기초 05 1. SQL Processing 및 Optimizer의 이해 ◈ SQL 실행 PLAN 보는 법
▷ 기본 환경은 실행 PLAN에서 술어(Predicate)를 보여 주는데 실행 PLAN이 길어질 경우 가독성이 떨어집니다. 가독성을 높이기 위해 술어를 옆으로 보여 줄 수 있는데 도구 > 환경설정에서 계획설명 Predicate Branch 부분을 체크 해제하면 됩니다. ▷실행 PLAN은 가장 Depth가 깊은 ①번부터 수행되고 동일한 Depth인 경우(②,④) 위쪽에 있는 ②번부터 수행됩니다.
256
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ 조인 시 성능 결정 요인
▷ 여러 테이블을 조인하는 경우에는 조인 방식과 조인 순서에 따라 성능 차이가 매우 클 수 있습니다. Oracle 에서는 기본적으로 3가지 조인 방식 (Nested Loop, Sort Merge, Hash)이 존재하며, 각 방식마다 장단점이 있으므로, 어떤 조인 방식이 어떤 경우에 효과적인지 이해하도록 합니다. ◈ 조인 시 성능 결정 요인 ▷ 조인의 방법에는 크게 Nested Loop Join과 Sort Merge Join, Hash Join이 있습니다. 조인이 적절하게 사용되지 않을 경우, 데이터가 늘어남에 따라 기하급수적으로 성능이 저하될 수 있으며 조인의 튜닝을 통하여 많은 성능 향상을 기대할 수 있습니다. 조인시의 성능 결정요인은 다음과 같습니다. - Driving Table : 조인시에 먼저 Access 되는 Table의 성격에 따라 성능이 결정됩니다. - 조인순서 : 어떤 순서로 조인할 것인가 하는 점이 처리량과 응답시간 결정에 영향을 미칩니다. - 조인컬럼의 인덱스 유무 : 조인컬럼에 인덱스가 없을 경우, 조인순서가 고정되며 Nested Loop Join의 경우 Full Scan 방식으로 테이블을 Access하여 성능저하의 원인이 됩니다. 따라서 조인대상 컬럼은 반드시 인덱스를 가져야 합니다. - 실행계획과 처리범위에 따라 조인의 성능이 달라지게 됩니다. - 조인의 튜닝절차는 다음과 같습니다. ① Nested Loop Join이 유리한지 Sort Merge Join 또는 Hash join이 유리한지를 판단합니다. ② 조인조건으로 사용된 컬럼의 인덱스 유무를 파악합니다. ③ 연산자와 인덱스의 상태를 비교하여 처리범위를 가장 많이 줄여주는 조건을 찾습니다. ④ 현재의 인덱스가 최소범위를 Access 할 수 있도록 구성되어 있는지 확인합니다.
257
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ Nested Loop Join
▷ 조인 대상인 두개의 테이블 중 하나를 기준(driving) 테이블로 잡고 이 테이블을 scan하면서 각 Row에 대한 조인 조건을 만족하는 Row를 찾기 위해 다른 테이블(inner table)을 scan하는 Loop 작업을 반복 수행하는 방법입니다. Nested Loop Join에서 중요한 부분은 기준 테이블 선정과 연결고리 역할을 하는 inner table 컬럼의 인덱스 존재 여부이며, 최종 추출건수가 많지 않은 OLTP 성격의 업무에 적합합니다. SELECT a.FLD1, ..., b.FLD1,... FROM TAB1 a, TAB2 b WHERE a.KEY1 = b.KEY2 AND a.FLD1 = 'AB' AND b.FLD2 = '10' TABLE ACCESS BY ROWID TABLE ACCESS BY ROWID KEY2= KEY1 FLD2 ='10' check FLD1='AB' o ①TAB1의 FLD1 인덱스 내용 중 FLD1='AB'를 만족하는 첫 번째 로우 액세스 ②FLD1 인덱스의 rowid를 통해 TAB1의 로우 액세스 ③TAB1의 key1 조건(상수)에 맞는 TAB2의 key2 인덱스 내용 액세스 ④TAB2의 인덱스의 rowid를 통해 TAB2의 로우 액세스 ⑤TAB2의 FLD='10'의 조건에 맞는 row가 운반 단위로 최종 리턴 - 사용된 인덱스: TAB1의 경우 FLD1 컬럼, TAB2의 경우 KEY2 컬럼 o o 운반 단위 x INDEX (FLD1) TAB TAB2 INDEX (KEY2)
258
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ Nested Loop Join 순차적 (부분범위처리 가능)
▷ 기준(driving) 테이블을 선정하기 위한 원칙 - 상수 값을 보유하는 테이블: 상수 값을 보유하지 않으면 보통 full scan으로 처리됩니다. Nested Loop Join을 효과적으로 사용하는 경우는 기준 테이블에서 최소 결과치를 추출되는 경우이므로 상수 값을 갖는 컬럼에 인덱스를 가져야 할 것입니다. 특히 여러 개의 상수 값을 갖는 테이블을 기준 테이블로 선택할 경우 여러 개의 상수 값을 갖는 컬럼들을 결합 인덱스로 묶어 처리하면 가장 뛰어난 성능을 보장할 수 있습니다. - Outer Join 대상이 아닌 테이블: Outer Join의 대상이 되는 테이블을 절대로 기준 테이블이 될 수 없습니다. 따라서 최상의 기준 테이블 조건을 갖는데도 불구하고 불필요한 Outer Join으로 인해 기준 테이블로 사용되지 못하는 경우를 피해야 합니다. 순차적 (부분범위처리 가능) 종속적 (먼저 처리되는 테이블의 처리범위에 따라 처리량 결정) 랜덤(Random) 액세스 위주 연결고리 상태에 따라 영향이 큼 주로 좁은 범위 처리에 유리
259
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ Sort Merge Join
방법입니다. SMJ에서 중요한 것은 (1)각 테이블에서 정렬이 발생하기 전에 가능한 범위를 줄여 주는 것과 (2)정렬 작업이 메모리에서 수행될 수 있도록 DB 파라미터를 적절히 설정해 주는 것입니다. 일반적으로 SMJ은 추출되는 데이터가 매우 많거나 범위를 줄여 줄 수 있는 인덱스를 생성할 수 없는 경우에 유리합니다. 따라서 OLTP에서는 가급적 사용하지 않는 것이 좋으며 배치 성격의 작업에서 주로 사용합니다. 다음 그림은 조인 방식을 도식화 한 것입니다. SELECT /*+ use_merge(a b) */ a.FLD1, ..., b.FLD2,... FROM TAB1 a, TAB2 b WHERE a.KEY1 = b.KEY2 AND a.FLD1 = 'AB' AND b.FLD2 = '10' TABLE ACCESS BY ROWID TABLE ACCESS BY ROWID FLD1='AB' a.KEY1= b.KEY2 를 조건으로 Merge FLD2='10' ①FLD1 인덱스를 통해 FLD1='AB' 조건을 만족하는 로우를 추출합니다. ②TAB1에서 추출한 모든 데이터를 정렬합니다. ③FLD2 인덱스를 통해 FLD2='10' 조건을 만족하는 로우를 추출합니다. ④TAB2에서 추출한 모든 데이터를 정렬합니다. ⑤FLD1과 FLD2에서 추출, 정렬한 결과를 스캔 하면서 key1=key2를 만족하는 로우를 추출해서 운반단위로 리턴 - 사용된 인덱스: TAB1의 경우 FLD1 컬럼, TAB2의 경우 FLD2 컬럼 S O R T S O R T . . . . . . 운반단위 INDEX (FLD1) TAB TAB2 INDEX (FLD2)
260
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ Sort Merge Join 동시적 (무조건 전체범위처리)
▷ 여기서 중요한 것은 SMJ에서 사용된 인덱스 컬럼 리스트와 NLJ에서 사용된 인덱스 컬럼 리스트가 다르다는 점입니다. 즉 NLJ에서 TAB2의 경우 정상적인 연결고리를 위해 KEY2 컬럼에 인덱스를 사용했고 SMJ은 연결고리에 별도 인덱스가 필요 없기 때문에 TAB2의 범위만 줄여주는 FLD2 컬럼에 인덱스가 필요합니다. 동시적 (무조건 전체범위처리) 독립적 (자기의 처리범위만으로 처리량 결정) 스캔(Scan) 액세스 위주 연결고리 상태에 영향이 없음 주로 넓은 범위 처리에 유리 Nested Loop Join Sort Merge Join 성능 관점 Response Time Throughput 부분범위처리 여부 부분범위처리 가능 무조건 전체범위처리 연결고리 상태 정상 여부에 큰 영향 상태 관계없음 access 방식 Index access 위주 Scan access 위주 기준 테이블 역할 절대적(access량 결정) 독립적(driving 의미 없음) 처리범위(WHERE 조건) 좁은 범위 처리에 유리 넓은 범위 처리에 유리 애플리케이션 성격 OLTP Batch
261
SQL 성능향상 기초 05 2. 조인 ( JOIN ) ◈ Hash Join
▷ 한쪽 테이블의 데이터가 작은 경우 이를 inner table로 선택하고 그 데이터를 해시 함수(hash function)를 이용해 메모리에 올려놓은 후, 다른 테이블을 기준 테이블로 선택해 해시 쿼리(hash query)로 조인하는 방법입니다. NLJ보다 SMJ이 유리한 경우라면 HJ을 이용하면 더 나은 성능향상을 꾀할 수 있습니다. 특히 조인이 필요한 두 개의 테이블 중 하나의 테이블이 다른 테이블보다 월등히 작거나 클 경우 HJ이 SMJ보다 훨씬 효과적입니다. 따라서 많은 양의 데이터 추출 및 조작이 필요한 OLAP, 배치 업무에서 주로 이용합니다. 2. 각 파티션 짝에 대해 작은 파티션을 메모리로 로드하여 해쉬 테이블로 생성 1. 양쪽 테이블 스캔하여 조인 컬럼에 대한 파티션 "짝"을 생성 3. 다른 파티션의 로우를 읽는다. 이 때 메모리내의 파티션에 대응되는 로우가 있는지를 검증하기 위해 해쉬 테이블을 이용 4. 작은 파티션을 찾아 메모리로 로딩하여 해쉬테이블을 생성하고 대응되는 로우를 찾는 작업 등을 계속해서 수행
262
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ B-Tree 인덱스
▷ 인덱스는 원하는 데이터를 쉽게 찾을 수 있도록 돕는 책의 찾아보기와 유사한 개념입니다. Insert, Update, Delete 등과 같은 DML 작업은 테이블과 인덱스를 함께 변경해야 하기 때문에 오히려 느려질 수 있다는 단점이 존재합니다. ▷ DBMS에서 가장 일반적인 인덱스는 B-트리 인덱스입니다. ▷ B-트리 인덱스 = 브랜치 블록(Branch Block)과 리프 블록(Leaf Block) - 브랜치 블록 중에서 가장 상위에서 있는 블록을 루트 블록(Root Block) - 브랜치 블록은 다음 단계의 블록을 가리키는 포인터를 가지고 있습니다. - 리프 블록은 트리의 가장 아래 단계에 존재합니다. - 리프 블록은 인덱스를 구성하는 칼럼의 데이터와 해당 데이터를 가지고 있는 행의 위치를 가리키는 레코드 식별자(RID, Record Identifier/Rowid)로 구성 - 인덱스 데이터는 인덱스를 구성하는 칼럼의 값으로 정렬됩니다. 만약 인덱스 데이터의 값이 동일하면 레코드 식별자의 순서로 저장됩니다. - 리프 블록은 양방향 링크(Double Link)를 가지고 있습니다. 이것을 통해서 오름 차순(Ascending Order)과 내림 차순(Descending Order) 검색을 쉽게 할 수 있습니다. - B-트리 인덱스는 ‘=’로 검색하는 일치(Exact Match) 검색과 ‘BETWEEN’, ‘>’ 등과 같은 연산자로 검색하는 범위(Range) 검색 모두에 적합한 구조
263
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ B-Tree 인덱스 예 SELECT ....
WHERE ENAME = ‘LOVE’ A - K L – Z INDEX ① ② A - D E – G H - K L - O P – R S - Z ③ ADAMS AAA ADAMS AAB ADAMS AAC DAVIS AAR EDAM AAH FARRA AAG GOUCH AAQ HARRI ABC JONES AAT KANE ABY LOVE ACD MILER ACR ODEN AAP PRINE ACE QUEEN AAM RICRD ACW SMITH ARR VADEZ ARQ WITON AAX ④ ROWID SEARCH TABLE ROWID AAH AAG AAC AAR AAA AAB AAQ ABC AAT ABY ACD ACR AAP .... ENAME EDAM FARRA ADAMS DAVIS GOUCH HARRI JONES KANE LOVE MILER ODEN ETC
264
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ B-Tree 인덱스 예 SELECT .... WHERE ENAME
BETWEEN ‘DAVIS’ AND ‘GOUCH’ A - K L – Z INDEX ① ② A - D E – G H - K L - O P – R S - Z ③ ADAMS AAA ADAMS AAB ADAMS AAC DAVIS AAR EDAM AAH FARRA AAG GOUCH AAQ HARRI ABC JONES AAT KANE ABY LOVE ACD MILER ACR ODEN AAP PRINE ACE QUEEN AAM RICRD ACW SMITH ARR VADEZ ARQ WITON AAX TABLE ④ ROWID SEARCH ROWID AAH AAG AAC AAR AAA AAB AAQ ABC AAT ABY ACD ACR AAP .... ENAME EDAM FARRA ADAMS DAVIS GOUCH HARRI JONES KANE LOVE MILER ODEN ETC
265
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ 인덱스 생성시 고려 사항 ◈ 결합 인덱스의 사용
▷ Query의 WHERE 절 조건에 빈번하게 사용되는 컬럼에 인덱스를 생성합니다. ▷ SQL문에서 테이블을 join하는데 자주 사용되는 컬럼에 인덱스를 생성합니다. ▷ 인덱스 컬럼 값의 분포도가 10~15%를 넘지 말아야 합니다. ( 분포도가 낮은 컬럼이란 반복되는 값이 적은 컬럼을 말합니다. ) ▷ 인덱스 컬럼에 조회보다 DML작업이 더 많이 일어나는 경우, 인덱스를 사용하는 효용성보다 컬럼 변경으로 인한 INDEX의 관리비용이 더 크게 되므로 인덱스를 만들면 안 됩니다. ▷ 테이블의 크기가 적은 것은 인덱스를 만들지 않는 것이 좋습니다. Full Table Scan의 경우 Oracle은 Multi Block Read를 하기 때문에 인덱스를 사용하는 경우보다 성능향상을 기할 수 있습니다. ◈ 결합 인덱스의 사용 ▷ 한 테이블에 여러 인덱스가 있더라도 여러 인덱스가 하나의 SQL에서 동시에 사용되지 않습니다. ▷ WHERE 절에 여러 개의 상수 조건을 갖는 경우, 한 컬럼에 인덱스를 생성하는 것보다 상주 조건을 갖는 여러 컬럼들을 하나의 인덱스로 만들면 효율적입니다.(결합 인덱스) ▷ 결합 인덱스를 구성하는 컬럼들 중 반드시 첫 번째 컬럼이 WHERE 조건에 지정되어야 해당 인덱스가 사용됩니다. ▷ 결합 인덱스의 첫 번째 컬럼을 조건에서 사용하지 않으면 그 인덱스는 사용되지 않으며 처리범위를 결정하는 데에도 큰 영향을 미칩니다. 그러므로 첫 번째 컬럼을 결정하는데 있어서 가장 중요한 기준은 그 조건에서의 사용 여부입니다. ▷ 인덱스를 생성하려는 대상 컬럼 중 분포도가 가장 좋은 컬럼을 leading 컬럼으로 선택하는 것이 유리합니다.
266
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ 인덱스가 사용되지 않는 경우
▷ 인덱스 컬럼에 외부적 변형이 가해질 때 - WHERE 절 구문에 있는 컬럼에 대하여 인위적인 함수를 사용할 경우 ▷ 인덱스 컬럼에 내부적 변형(Type conversion)이 가해질 때 - WHERE 절 구문에서 서로 다른 data 타입 비교할 경우 ▷ 부정형으로 비교된 조건을 사용할 때 ( !=, NOT IN ) ▷ IS (NOT) NULL 로 비교된 경우 - 인덱스에는 NULL에 대한 정보가 없으므로 full table scan이 발생하게 됩니다. char 형의 경우 컬럼명>‘ ‘를 사용하여 해당 컬럼의 인덱스가 사용되도록 할 수 있습니다. ▷ LIKE 가 date 또는 number type의 컬럼에 사용된 경우 - Like 연산자는 연산의 대상이 되는 컬럼이 character type이 아닌 경우 해당 컬럼을 conversion 하므로 인덱스를 사용할 수 없습니다. ▷ LIKE ‘%text%’ 또는 LIKE ‘%text’ 절 - Like 조건에 ‘%’로 시작하는 비교 값이 들어오면 인덱스를 사용할 수 없습니다. ▷ 레코드 필터링을 위해서는 having보다는 where를 사용합니다. 인덱스가 걸려있는 컬럼에 group by와 함께 having절을 사용하게 될 경우 having절의 컬럼에 대한 인덱스는 사용되지 않습니다. 즉, having절은 group by 절에 의하여 이미 grouping된 데이터를 줄여주는 역할만 수행하므로 인덱스를 사용하지 않으므로 where조건에 의해 인덱스를 사용하여 데이터를 가져온 후 grouping을 하도록 합니다. ▷ in (list) 연산자는 인덱스를 사용하기는 하나 or로 연결되는 구문이므로 list에 개수가 많으면 속도를 저하시킬 우려가 많습니다. ▷ A+B+C+D 로 구성된 결합 인덱스에서 WHERE A=:A AND B LIKE ‘:B%’ AND C=:C AND D=:D 와 같은 조건이 사용된 경우 LIKE이 사용된 컬럼까지(A+B 까지)만 인덱스가 유효합니다. ▷ A+B+C+D 로 구성된 결합 인덱스에서 WHERE A=:A AND B BETWEEN :B1 AND :B2 AND C=:C AND D:=D 와 같은 조건이 사용된 경우 BETWEEN 이 사용된 컬럼까지(A+B 까지)만 인덱스가 유효합니다.
267
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ 인덱스가 사용되지 않는 경우 인덱스를 사용하지 않는 경우
인덱스를 사용 하는 경우 SELECT DEPT, ENAME, SAL FROM EMP WHERE SAL * 12 < 5000; WHERE SAL < 5000 / 12; SELECT DEPT, ENAME, SAL FROM EMP WHERE SUBSTR(REGI_DTTM,1,8)>=‘ ’ AND SUBSTR(REGI_DTTM,1,8)<=‘ ’; WHERE REGI_DTTM >= ‘ ’ AND REGI_DTTM <= ’||’999999’ WHERE DEPT = 7788; SELECT DEPT, ENAME, SAL FROM EMP WHERE DEPT = TO_CHAR(7788) ; SELECT CHR, VAR, NUM, DATE FROM SAMPLE WHERE CHR = ; SELECT CHR, VAR, NUM, DATE FROM SAMPLE WHERE CHR = ‘971220’; WHERE EMPNO <> 123; SELECT DEPT, ENAME, SAL FROM EMP WHERE NOT EXISTS ( SELECT ‘X’ FROM EMP WHERE EMPNO = 123 ) ; WHERE DATE IS NOT NULL; WHERE DATE > 0; WHERE JOB LIKE ‘%ALE’; WHERE JOB LIKE ‘SALE%’; SELECT DEPT, SUM(SAL) FROM EMP GROUP BY DEPT HAVING DEPT = 100; WHERE DEPT = 100 GROUP BY DEPT;
268
SQL 성능향상 기초 05 3. 인덱스 ( INDEX ) ◈ NULL, NOT NULL ▷ NULL
기본적으로 인덱스를 구성한 column 값이 전부 NULL이라면 index는 이런 값을 저장하지 않습니다. 따라서 NULL인 값이 많지 않은 값을 index를 통해 액세스를 하고자 한다면 데이터 생성시 디폴트로 0과 같이 데이터를 만들어 주도록 하고, SQL은 다음과 같이 수정하면 유리합니다. - WHERE 연체금액 IS NULL => WHERE 연체금액 = 0 ▷ NOT NULL 반대로, 만약 대부분의 값이 NULL이고 NOT NULL인 경우가 검색 대상이라면 해당 column을 NULL 허용 설정하고 Index 컬럼으로 선정하는 것이 좋습니다. 이유는 Index에는 NULL인 값은 저장하지 않기 때문에 보다 빠른 검색이 가능해집니다. - WHERE 연체금액 IS NOT NULL => WHERE 연체금액 > 0
269
SQL 성능향상 기초 05 4. 부분범위 처리 ◈ Partial Range Scan ( 부분 범위 처리 )
▷ 부분 범위 처리는 정렬을 하지 않고 처리되는 순서로 데이터를 추출하다가 운반단위(array size)에 도달하면 멈추게 하는 처리방법을 말합니다. 전체 범위 처리는 전체 데이터를 access한 후 가공하여 운반단위만큼씩 반복 추출하는 처리방법이고 부분 범위 처리는 조건을 만족하는 Row 수가 운반단위에 도달하면 멈추게 하는 처리방법입니다. SUM, COUNT, MAX, MIN, AVG 등의 그룹 함수를 사용했거나 GROUP BY, UNION, MINUS, INTERSECT 등의 연산을 사용하면 부분범위 처리를 할 수 없습니다. 전체범위를 읽지 않고서는 도저히 결과를 도출할 수 없는 경우를 제외하고 대부분 부분범위 처리방법으로 처리할 수 있으며 전체범위 처리를 하는 경우보다 성능향상을 기대할 수 있습니다. 부분범위처리는 조건을 만족하는 전체집합이 아닌 일부분만을 access하기 때문에 데이터 량이 많아도 성능에 지장이 없습니다. 아래와 같은 경우에 부분 범위 처리를 함으로서 SQL문의 성능을 향상시킬 수 있습니다. 전 체 범 위 처 리 부 분 범 위 처 리 1 차 스 캔 2 차 가 공 1 차 스 캔 2 차 가 공 운반단위 운반단위 Full Range Scan 후 가공하여 Array Size 만큼 추출 조건을 만족하는 Row 수가 Array Size 에 도달되면 멈춤
270
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ SORT를 대신하는 INDEX
◈ Partial Range Scan ( 부분 범위 처리 ) ▷ SORT를 대신하는 INDEX SELECT * FROM PRODUCT WHERE YMD = '951023' AND ITEM LIKE 'AB%‘ ORDER BY YMD, ITEM SELECT * FROM PRODUCT WHERE YMD = '951023' AND ITEM LIKE 'AB%'; 부 분 스 캔 SORT 전 체 스 캔 운반단위 운반단위 . . INDEX(YMD) TABLE INDEX (YMD+ITEM) TABLE
271
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ SORT를 대신하는 INDEX
◈ Partial Range Scan ( 부분 범위 처리 ) ▷ SORT를 대신하는 INDEX SQL> SELECT ORDDATE, CUSTNO FROM ORDER1T WHERE ORDDATE between '940101' and '941130' ORDER BY ORDDATE DESC SQL> SELECT --+ INDEX_DESC(A orddate) ORDDATE, CUSTNO FROM ORDER1T A WHERE ORDDATE between '940101' and '941130' SORT ORDER BY TABLE ACCESS BY ROWID ORDER1T INDEX RANGE SCAN ORD_ORDDATE INDEX RANGE SCAN DESCENDING ORDDATE SQL> SELECT --+ INDEX_DESC(A orddate) ORDDATE, CUSTNO FROM ORDER1T A WHERE ORDDEPT LIKE '7%' AND ORDDATE <= '991231' SQL> SELECT ORDDATE, CUSTNO FROM ORDER1T WHERE ORDDEPT LIKE '7%' ORDER BY ORDDATE DESC SORT ORDER BY TABLE ACCESS BY ROWID ORDER1T INDEX RANGE SCAN ORD_ORDDATE INDEX RANGE SCAN DESCENDING ORDDATE
272
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ INDEX 만 처리
◈ Partial Range Scan ( 부분 범위 처리 ) ▷ INDEX 만 처리 SELECT DEPT, SUM(QTY) FROM PRODUCT WHERE DEPT LIKE '12%‘ GROUP BY DEPT; SELECT DEPT, SUM(QTY) FROM PRODUCT WHERE DEPT LIKE '12%‘ GROUP BY DEPT; GROU P B Y GROU P B Y 운반단위 운반단위 INDEX (DEPT) TABLE INDEX (DEPT+QTY)
273
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ MAX 처리 ◈ Partial Range Scan ( 부분 범위 처리 ) S
SELECT /*+ INDEX_DESC( A INDEX1) */ SEQ FROM PRODUCT A WHERE DEPT = '12300' AND ROWNUM = 1; SELECT MAX(SEQ) + 1 FROM PRODUCT WHERE DEPT = '12300'; S O R T 운반단위 운반단위 MAX(SEQ)+1 SEQ + 1 INDEX ( DEPT ) TABLE INDEX 1 ( DEPT+SEQ )
274
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ MAX 처리 예제 ▷ INDEX만 처리 예제
◈ Partial Range Scan ( 부분 범위 처리 ) ▷ MAX 처리 예제 SQL> SELECT --+ INDEX_DESC(A dept_date) ORDDATE FROM ORDER1T A WHERE ORDDEPT = '430' AND STATUS='30' AND ROWNUM = 1 SQL> SELECT MAX(ORDDATE) FROM ORDER1T WHERE ORDDEPT = '430' AND STATUS = '30' SORT AGGREGATE TABLE ACCESS BY ROWID ORDER1T INDEX RANGE SCAN DEPT_DATE 1 COUNT STOPKEY TABLE ACCESS BY ROWID ORDER1T INDEX RANGE SCAN DESCENDING DEPT_DATE ▷ INDEX만 처리 예제 SQL> SELECT TYPE, COUNT(*) FROM ORDER2T WHERE ITEM LIKE 'HJ%' GROUP BY TYPE SQL> SELECT STATUS, COUNT(*) FROM ORDER2T WHERE ITEM LIKE 'HJ%' GROUP BY STATUS SORT GROUP BY TABLE ACCESS BY ROWID ORDER2T INDEX RANGE SCAN ITEM_STATUS SORT GROUP BY INDEX RANGE SCAN ITEM_STATUS
275
SQL 성능향상 기초 05 4. 부분범위 처리 ▷ EXISTS 예제 ▷ ROWNUM 예제
◈ Partial Range Scan ( 부분 범위 처리 ) ▷ EXISTS 예제 SELECT 1 INTO :CNT FROM DUAL WHERE EXISTS (SELECT 'X' FROM ITEM_TAB WHERE DEPT = '101' AND SEQ > 100 ) IF CNT > 0 SELECT COUNT(*) INTO :CNT FROM ITEM_TAB WHERE DEPT = '101' AND SEQ > 100 IF CNT > ▷ ROWNUM 예제 SELECT 1 INTO :CNT FROM ITEM_TAB WHERE DEPT = '101' AND SEQ > 100 AND ROWNUM = 1 IF CNT > 0 SELECT COUNT(*) INTO :CNT FROM ITEM_TAB WHERE DEPT = '101' AND SEQ > 100 IF CNT > 0
Similar presentations