<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bebeco_o.log</title>
        <link>https://velog.io/</link>
        <description>블로그 이사 중 ⭐️ || https://bebeco.tistory.com/</description>
        <lastBuildDate>Mon, 05 Dec 2022 18:29:45 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. bebeco_o.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bebeco_o" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[sql-study-day29]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day29</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day29</guid>
            <pubDate>Mon, 05 Dec 2022 18:29:45 GMT</pubDate>
            <description><![CDATA[<h2 id="19---5-트리거">19 - 5 트리거</h2>
<br/>

<blockquote>
<p>트리거란?</p>
</blockquote>
<ul>
<li><p>오라클에서 트리거(trigger)는 데이터베이스 안의 특정 상황이나 동작, 즉 이벤트가 발생할 경우에 자동으로 실행되는 기능을 정의하는 PL/SQL 서브프로그램이다.</p>
</li>
<li><p>트리거를 통해 연관 데이터 작업을 잘 정의해 두면 좋은 장점</p>
<ol>
<li><p>데이터와 연관된 여러 작업을 수행하기 위해 여러 PL/SQL문 또는 서브프로그램을 일일이 실행해야 하는 번거로움을 줄일 수 있습니다. 즉 데이터 관련 작업을 좀 더 간편하게 수행할 수 있습니다.</p>
</li>
<li><p>제약 조건(constraints)만으로 구현이 어렵거나 불가능한 좀 더 복잡한 데이터 규칙을 정할 수 있어 더 수준 높은 데이터 정의가 가능합니다.</p>
</li>
<li><p>데이터 변경과 관련된 일련의 정보를 기록해 둘 수 있으므로 여러 사용자가 공유하는 데이터 보안성과 안정성 그리고 문제가 발생했을 때 대처 능력을 높일 수 있습니다.</p>
</li>
</ol>
</li>
<li><p>하지만 트리거는 특정 작업 또는 이벤트 발생으로 다른 데이터 작업을 추가로 실행하기 때문에 무분별하게 사용하면 데이터베이스 성능을 떨어뜨리는 원인이 되므로 주의가 필요하다.</p>
</li>
<li><p>트리거는 테이블∙뷰∙스키마∙데이터베이스 수준에서 이벤트 동작을 지정할 수 있다.</p>
<ol>
<li>데이터 조작어(DML) : INSERT, UPDATE, DELETE</li>
<li>데이터 정의어(DDL) : CREATE, ALTER, DROP</li>
<li>데이터베이스 동작 : SERVERERROR, LOGON, LOGOFF, STARTUP, SHUTDOWN</li>
</ol>
</li>
<li><p>트리거가 발생할 수 있는 이벤트 종류에 따라 오라클은 다음과 같이 구분한다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th align="center">종류</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">DML트리거</td>
<td align="center">INSERT, UPDATE, DELETE와 같은 DML 명령어를 기점으로 동작함</td>
</tr>
<tr>
<td align="center">DDL트리거</td>
<td align="center">CREATE, ALTER, DROP과 같은 DDL 명령어를 기점으로 동작함</td>
</tr>
<tr>
<td align="center">INSTEAD OF 트리거</td>
<td align="center">뷰(View)에 사용하는 DML 명령어를 기점으로 동작함</td>
</tr>
<tr>
<td align="center">시스템(system) 트리거</td>
<td align="center">데이터베이스나 스키마 이벤트로 동작함</td>
</tr>
<tr>
<td align="center">단순(simple) 트리거</td>
<td align="center">다음 각 시점(timing point)에 동작함<br/> ∙ 트리거를 작동시킬 문장이 실행되기 전 시점<br/> ∙ 트리거를 작동시킬 문장이 실행된 후 시점<br/> ∙ 트리거를 작동시킬 문장이 행에 영향을 미치기 전 시점<br/> ∙ 트리거를 작동시킬 문장이 행에 영향을 준 후 시점</td>
</tr>
<tr>
<td align="center">복합(compound) 트리거</td>
<td align="center">단순 트리거의 여러 시점에 동작함</td>
</tr>
</tbody></table>
<br/>

<blockquote>
<p>DML 트리거</p>
</blockquote>
<ul>
<li>DML 트리거 형식<ul>
<li>DML 트리거는 특정 테이블에 DML 명령어는 실행했을 때 작동하는 트리거이다.</li>
</ul>
</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE [OR REPLACE] TRIGGER 트리거 이름 1.
BEFORE | AFTER 2.
INSERT | UPDATE | DELETE ON 테이블 이름 3.
REFERENCING OLD as old | New as new 4.
FOR EACH ROW WHEN 조건식 5.
FOLLOWS 트리거 이름2, 트리거 이름3 ... 6.
ENABLE | DISABLE 7.

DECLARE
  선언부
BEGIN
  실행부
EXCEPTION
  예외 처리부
END;</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">트리거 이름을 명시하고 트리거를 생성합니다. 트리거 내용을 갱신하려면 OR REPLACE 키워드를 함께 명시합니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">트리거가 작동할 타이밍을 지정합니다. BEFORE는 DML 명령어가 실행되기 전 시점, AFTER는 DML 명령어가 실행된 후 시점에 트리거가 작동합니다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">지정한 테이블에 트리거가 작동할 DML 명령어를 작성합니다. 여러 종류의 DML 명령어를 지정할 경우에는 OR로 구분합니다.</td>
</tr>
<tr>
<td align="center">4.</td>
<td align="center">DML로 변경되는 행의 변경 전 값과 변경 후 값을 참조하는 데 사용합니다(생략 가능).</td>
</tr>
<tr>
<td align="center">5.</td>
<td align="center">트리거를 실행하는 DML 문장에 한 번만 실행할지 DML 문장에 의해 영향받는 행별로 실행할지를 지정합니다. 생략하면 트리거는 DML 명령어가 실행할 때 한 번만 실행합니다. 생략하지 않고 사용할 경우, DML 명령어에 영향받는 행별로 트리거를 작동하되 WHEN 키워드를 함께 사용하면 DML 명령어에 영향받는 행 중 트리거를 작동시킬 행을 조건식으로 지정할 수 있습니다.</td>
</tr>
<tr>
<td align="center">6.</td>
<td align="center">오라클 11g부터 사용 가능한 키워드로서 여러 관련 트리거의 실행 순서를 지정합니다(생략 가능).</td>
</tr>
<tr>
<td align="center">7.</td>
<td align="center">오라클 11g부터 사용 가능한 키워드로서 트리거의 활성화∙비활성화를 지정합니다(생략 가능).</td>
</tr>
</tbody></table>
<br/>

<blockquote>
<p>트리거 관리</p>
</blockquote>
<h3 id="트리거-정보-조회">트리거 정보 조회</h3>
<ul>
<li>트리거 정보를 확인하려면 USER_TRIGGERS 데이터 사전을 조회한다.</li>
</ul>
<pre><code class="language-sql">// USER_TRIGGERS로 트리거 정보 조회하기
SELECT TRIGGER_NAME, TRIGGER_TYPE, TRIGGERING_EVENT, TABLE_NAME, STATUS
  FROM USER_TRIGGERS;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco/post/2cb7cd47-ee61-468c-9c2d-86ee9a5a08b2/image.png" alt=""></p>
<br/>

<blockquote>
<p>트리거 변경</p>
</blockquote>
<ul>
<li>ALTER TRIGGER 명령어로 트리거 상태를 변경할 수 있다.</li>
<li>특정 트리거를 활성화 또는 비활성화하려면 ALTER TRIGGER 명령어에 ENABLE 또는 DISABLE 옵션을 지정한다.</li>
</ul>
<pre><code class="language-sql">ALTER TRIGGER 트리거 이름 ENABLE | DISABLE;</code></pre>
<ul>
<li>특정 테이블과 관련된 모든 트리거의 상태를 활성화하거나 비활성화하기</li>
</ul>
<pre><code class="language-sql">특정 테이블과 관련된 모든 트리거의 상태 활성화
ALTER TABLE 테이블 이름 ENABLE ALL TRIGGERS;

특정 테이블과 관련된 모든 트리거의 상태 비활성화
ALTER TABLE 테이블 이름 DISABLE ALL TRIGGERS;</code></pre>
<br/>

<blockquote>
<p>트리거 삭제</p>
</blockquote>
<pre><code class="language-sql">DROP TRIGGER 트리거 이름;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day28]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day28</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day28</guid>
            <pubDate>Mon, 05 Dec 2022 18:29:19 GMT</pubDate>
            <description><![CDATA[<h2 id="19---3-함수">19 - 3 함수</h2>
<ul>
<li>프로시저와 함수의 차이점</li>
</ul>
<table>
<thead>
<tr>
<th align="center">특징</th>
<th align="center">프로시저</th>
<th align="center">함수</th>
</tr>
</thead>
<tbody><tr>
<td align="center">실행</td>
<td align="center">EXECUTE 명령어 또는 다른 PL/SQL 서브프로그램 내에서 호출하여 실행</td>
<td align="center">변수를 사용한 EXECUTE 명령어 또는 다른 PL/SQL 서브프로그램에서 호출하여 실행하거나 SQL문에서 직접 실행 가능</td>
</tr>
<tr>
<td align="center">파라미터 지정</td>
<td align="center">필요에 따라 지정하지 않을 수도 있고 여러 개 지정할 수도 있으며 IN, OUT, IN OUT 세 가지 모드를 사용할 수 있음</td>
<td align="center">프로시저와 같게 지정하지 않을 수도 있고 여러 개 지정할 수 있지만 IN 모드(또는 생략)만 사용</td>
</tr>
<tr>
<td align="center">값의 반환</td>
<td align="center">실행 후 값의 반환이 없을 수도 있고 OUT, IN OUT 모드의 파라미터 수에 따라 여러 개 값을 반환할 수 있음</td>
<td align="center">반드시 하나의 값을 반환해야 하며 값의 반환은 프로시저와 달리 OUT, IN OUT 모드의 파라미터를 사용하는 것이 아니라 RETURN절과 RETURN문을 통해 반환</td>
</tr>
</tbody></table>
<br/>

<blockquote>
<p>함수 생성하기</p>
</blockquote>
<ul>
<li>함수는 반환 값의 자료형과 실행부에서 반환할 값을 RETURN절 및 RETURN문으로 명시해야 한다.</li>
<li>실행부의 RETURN문이 실행되면 함수 실행은 즉시 종료된다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE [OR REPLACE] FUNCTION 함수 이름
[(파라미터 이름1 [IN] 자료형1, 1.
  파라미터 이름2 [IN] 자료형2,
  ...
  파라미터 이름N [IN] 자료형N
)]
RETURN 자료형 2.
IS | AS
  선언부
BEGIN
  실행부
 RETURN (반환 값); 3.
EXCEPTION
  예외 처리부
END [함수 이름];</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">함수 실행에 사용할 입력 값이 필요하면 파라미터를 지정합니다. 파라미터 지정은 생략 가능하며 필요에 따라 여러 개 정의할 수 있습니다. 프로시저와 달리 IN 모드만 지정합니다. :=, DEFAUTL 옵션으로 기본값을 지정할 수도 있습니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">함수의 실행 후 반환 값의 자료형을 정의합니다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">함수의 반환 값을 지정합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">// 함수 생성하기
CREATE OR REPLACE FUNCTION func_aftertax(
   sal IN NUMBER
)
RETURN NUMBER
IS
   tax NUMBER := 0.05;
BEGIN
   RETURN (ROUND(sal - (sal * tax)));
END func_aftertax;
/</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco/post/9c5f1f3a-3fc7-44f2-b999-cfa80a61abd8/image.png" alt=""></p>
<br/>

<blockquote>
<p>함수 실행하기</p>
</blockquote>
<ul>
<li>PL/SQL로 실행할 때는 함수 반환 값을 대입받을 변수가 필요하다.</li>
</ul>
<h3 id="plsql로-함수-실행하기">PL/SQL로 함수 실행하기</h3>
<p><img src="https://velog.velcdn.com/images/bebeco/post/4a0812bf-77cd-4905-9e3f-221329ac6282/image.png" alt=""></p>
<h3 id="sql문에서-함수-실행하기">SQL문에서 함수 실행하기</h3>
<p><img src="https://velog.velcdn.com/images/bebeco/post/6b0b7ace-3e25-40a7-badf-d64e8190529c/image.png" alt=""></p>
<ul>
<li>함수에 정의한 파라미터와 자료형이 일치한다면 내장 함수와 마찬가지로 특정 열 또는 열 데이터 간에 연산 가공된 데이터를 입력하는 것도 가능하다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco/post/814eb6d8-f45b-4764-a877-2d652e89aa9e/image.png" alt=""></p>
<br/>

<blockquote>
<p>함수 삭제하기</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/bebeco/post/2ca138a7-c165-4cd9-9dc5-36f7b741d0fc/image.png" alt=""></p>
<br/>

<h2 id="19---4-패키지">19 - 4 패키지</h2>
<br/>

<ul>
<li>패키지(package는 업무나 기능 면에서 연관성이 높은 프로시저, 함수 등 여러 개의 PL/SQL 서브프로그램을 하나의 논리 그룹으로 묶어 통합∙관리하는 데 사용하는 객체를 뜻한다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">장점</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">모듈성</td>
<td align="center">서브프로그램을 포함한 여러 PL/SQL 구성 요소를 모듈화할 수 있습니다. 모듈성은 잘 묶어 둔다는 뜻으로 프로그램의 이해를 쉽게 하고 패키지 사이의 상호 작용을 더 간편하고 명료하게 해 주는 역할을 합니다. 즉 PL/SQL로 제작한 프로그램의 사용 및 관리에 큰 도움을 줍니다.</td>
</tr>
<tr>
<td align="center">쉬운 응용 프로그램 설계</td>
<td align="center">패키지에 포함할 서브프로그램은 완벽하게 완성되지 않아도 정의가 가능합니다.<br/> 이 때문에 전체 소스 코드를 다 작성하기 전에 미리 패키지에 저장할 서브프로그램을 지정할 수 있으므로 설계가 수월해집니다.</td>
</tr>
<tr>
<td align="center">정보 은닉</td>
<td align="center">제작 방식에 따라 패키지에 포함하는 서브프로그램의 외부 노출 여부 또는 접근 여부를 지정할 수 있습니다. 즉 서브프로그램을 사용할 때 보안을 강화할 수 있습니다.</td>
</tr>
<tr>
<td align="center">기능성 향상</td>
<td align="center">패키지 내부에는 서브프로그램 외에 변수∙커서∙예외 등도 각 세션이 유지되는 동안 선언해서 공용(public)으로 사용할 수 있습니다. 예를 들어 특정 커서 데이터는 세션이 종료되기 전까지 보존되므로 여러 서브프로그램에서 사용할 수 있습니다.</td>
</tr>
<tr>
<td align="center">성능 향상</td>
<td align="center">패키지를 사용할 때 패키지에 포함한 모든 서브프로그램이 메모리에 한 번에 로딩되는데 메모리에 로딩된 후의 호출은 디스크 I/O를 일으키지 않으므로 성능이 향상됩니다.</td>
</tr>
</tbody></table>
<p>▶︎ PL/SQL 서브프로그램의 제작∙사용∙관리∙보안∙서능 등에 좋은 영향을 끼친다.</p>
<br/>

<blockquote>
<p>패키지 구조와 생성</p>
</blockquote>
<ul>
<li>패키지는 프로시저, 함수와 달리 보통 두 부분으로 나누어 제작한다. 하나는 명세(specification) 또 하나는 본문(body)이라고 부른다.</li>
</ul>
<h3 id="패키지-명세">패키지 명세</h3>
<ul>
<li>패키지 명세는 패키지에 포함할 변수, 상수, 예외, 커서 그리고 PL/SQL 서브프로그램을 선언하는 용도로 작성한다.</li>
<li>패키지 명세에 선언한 여러 객체는 패키지 내부뿐만 아니라 외부에서도 참조할 수 있다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE [OR REPLACE] PACKAGE 패키지 이름
IS | AS
  서브프로그램을 포함한 다양한 객체 선언
END [패키지 이름];</code></pre>
<br/>

<p>패키지 생성하기
<img src="https://velog.velcdn.com/images/bebeco/post/5d985c21-9651-4e7a-a986-ef3d2ccfae76/image.png" alt=""></p>
<p>패키지 명세 확인하기(USER_SOURCE 데이터 사전으로 조회)<img src="https://velog.velcdn.com/images/bebeco/post/bdb2f55b-7d29-4f37-8a7e-66dae1bc1546/image.png" alt=""></p>
<p>패키지 명세 확인하기(DESC 명령어로 조회)
<img src="https://velog.velcdn.com/images/bebeco/post/dcd17299-b924-4b6f-9794-06c15a7664c5/image.png" alt=""></p>
<h3 id="패키지-본문">패키지 본문</h3>
<ul>
<li>패키지 본문에는 패키지 명세에서 선언한 서브프로그램 코드를 작성한다.</li>
<li>패키지 명세에 선언하지 않은 객체나 서브프로그램을 정의하는 것도 가능하다.</li>
<li>패키지 본문에만 존재하는 프로그램은 패키지 내부에서만 사용할 수 있다.</li>
<li>패키지 본문 이름은 패키지 명세 이름과 같게 지정해야 한다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE [OR REPLACE] PACKAGE BODY 패키지 이름
IS | AS
  패키지 명세에서 선언한 서브프로그램을 포함한 여러 객체를 정의
  경우에 따라 패키지 명세에 존재하지 않는 객체 및 서브프로그램도 정의 가능
END [패키지 이름];</code></pre>
<br/>

<p>패키지 본문 생성하기
<img src="https://velog.velcdn.com/images/bebeco/post/be46e372-3e4e-4f30-8219-7b6133f28989/image.png" alt=""></p>
<br/>

<h3 id="서브프로그램-오버로드">서브프로그램 오버로드</h3>
<ul>
<li>서브프로그램 이름은 중복될 수 없다. 하지만 같은 패키지에서 사용하는 파라미터의 개수, 자료형, 순서가 다를 경우에 한해서만 이름이 같은 서브프로그램을 정의할 수 있다. 이를 서브프로그램 오버로드(subprogram overload)라고 한다.</li>
<li>서브프로그램 오버로드는 보통 같은 기능을 수행하는 여러 서브프로그램이 입력 데이터를 각각 다르게 정의할 때 사용한다. 또한 서브프로그램 종류가 같아야 오버로드가 가능하다.</li>
<li>프로시저와 이름이 같은 함수를 정의할 수는 없다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE [OR REPLACE] PACKAGE 패키지 이름
IS | AS
  서브프로그램 종류 서브프로그램 이름(파라미터 정의);
  서브프로그램 종류 서브프로그램 이름(개수나 자료형, 순서가 다른 파라미터 정의);
END [패키지 이름];</code></pre>
<br/>

<p>프로시저 오버로드하기
<img src="https://velog.velcdn.com/images/bebeco/post/0b1651e5-9635-4cec-9f82-21eaf968bf95/image.png" alt=""></p>
<p>패키지 본문에서 오버로드된 프로시저 작성하기
<img src="https://velog.velcdn.com/images/bebeco/post/c5ffcc64-dc36-4022-82cc-999f6472a2c4/image.png" alt=""></p>
<br/>


<blockquote>
<p>패키지 사용하기</p>
</blockquote>
<ul>
<li>패키지를 통해 그룹화된 변수, 상수, 예외, 커서 그리고 PL/SQL 서브프로그램은 패키지 이름과 마침표(.)와 사용할 객체 이름으로 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">패키지 이름.객체 이름;</code></pre>
<br/>

<p>패키지에 포함된 서브프로그램 실행하기
<img src="https://velog.velcdn.com/images/bebeco/post/d59ac33a-08a3-43fa-9ae7-312b576bcef3/image.png" alt=""></p>
<br/>

<blockquote>
<p>패키지 삭제하기</p>
</blockquote>
<ul>
<li>패키지 명세와 본문을 한 번에 삭제하거나 패키지 본문만 삭제할 수도 있다. 하지만 패키지에 포함된 서브프로그램을 따로 삭제하는 것은 불가능하다.</li>
</ul>
<pre><code class="language-sql">// 패키지 명세와 본문을 한 번에 삭제하기
DROP PACKAGE 패지키 이름;

// 패키지의 본문만을 삭제
DROP PACKAGE BODY 패키지 이름;</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day27]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day27</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day27</guid>
            <pubDate>Mon, 05 Dec 2022 18:28:50 GMT</pubDate>
            <description><![CDATA[<h2 id="19---1-저장-서브프로그램">19 - 1 저장 서브프로그램</h2>
<br/>

<ul>
<li><p>여러번 사용할 목적으로 이름을 지정하여 오라클에 저장해 두는 PL/SQL 프로그램을 저장 서브프로그램(stored subprogram)이라고 한다.</p>
</li>
<li><p>익명 블록과 달리 저장 서브프로그램은 오라클에 저장하여 공유할 수 있으므로 메모리∙성능∙재사용성 등 여러 면에서 장점이 있다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">익명 블록</th>
<th align="center">저장 서브프로그램</th>
</tr>
</thead>
<tbody><tr>
<td align="center">이름</td>
<td align="center">이름 없음</td>
<td align="center">이름 지정</td>
</tr>
<tr>
<td align="center">오라클 저장</td>
<td align="center">저장할 수 없음</td>
<td align="center">저장함</td>
</tr>
<tr>
<td align="center">컴파일</td>
<td align="center">실행할 때마다 컴파일</td>
<td align="center">저장할 때 한 번 컴파일</td>
</tr>
<tr>
<td align="center">공유</td>
<td align="center">공유할 수 없음</td>
<td align="center">공유하여 사용 가능</td>
</tr>
<tr>
<td align="center">다른 응용 프로그램에서의<br/> 호출 가능 여부</td>
<td align="center">호출할 수 없음</td>
<td align="center">호출 가능</td>
</tr>
</tbody></table>
<br/>

<ul>
<li>오라클에서 저장 서브프로그램을 구현할 수 있는데 대표적인 구현 방식은 프로시저∙함수∙패키지∙트리거이다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">서브프로그램</th>
<th align="center">용도</th>
</tr>
</thead>
<tbody><tr>
<td align="center">저장 프로시저<br/> (stored procedure)</td>
<td align="center">일반적으로 특정 처리 작업 수행을 위한 서브프로그램으로 SQL문에서는 사용할 수 없습니다.</td>
</tr>
<tr>
<td align="center">저장 함수<br/> (stored function)</td>
<td align="center">일반적으로 특정 연산을 거친 결과 값을 반환하는 서브프로그램으로 SQL문에서 사용할 수 있습니다.</td>
</tr>
<tr>
<td align="center">패키지<br/> (package)</td>
<td align="center">저장 서브프로그램을 그룹화하는 데 사용합니다.</td>
</tr>
<tr>
<td align="center">트리거<br/> (trigger)</td>
<td align="center">특정 상황(이벤트)이 발생할 때 자동으로 연달아 수행할 기능을 구현하는 데 사용합니다.</td>
</tr>
</tbody></table>
<br/>

<h2 id="19---2-프로시저">19 - 2 프로시저</h2>
<br/>

<ul>
<li>저장 프로시저(stored procedure)는 특정 처리 작업을 수행하는 데 사용하는 저장 서브프로그램으로 용도에 따라 파라미터를 사용할 수 있고 사용하지 않을 수도 있다.</li>
</ul>
<br/>

<blockquote>
<p>파라미터를 사용하지 않는 프로시저</p>
</blockquote>
<h3 id="프로시저-생성하기">프로시저 생성하기</h3>
<ul>
<li>작업 수행에 별다른 입력 데이터가 필요하지 않을 경우에 파라미터를 사용하지 않는 프로시저를 사용한다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE 1.[OR REPLACE] PROCEDURE 2.프로시저 이름
IS | AS 3.
  선언부
BEGIN
  실행부
EXCEPTION 4.
  예외 처리부
END [프로시저 이름]; 5.</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">지정한 프로시저 이름을 가진 프로시저가 이미 존재하는 경우에 현재 작성한 내용으로 대체합니다. 즉 덮어 쓴다는 뜻이며 생략 가능한 옵션입니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">저장할 프로시저의 고유 이름을 지정합니다. 같은 스키마 내에서 중복될 수 없습니다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">선언부를 시작하기 위해 IS 또는 AS 키워드를 사용합니다. 선언부가 존재하지 않더라도 반드시 명시합니다. DECLARE 키워드는 사용하지 않습니다.</td>
</tr>
<tr>
<td align="center">4.</td>
<td align="center">예외 처리부는 생략 가능합니다.</td>
</tr>
<tr>
<td align="center">5.</td>
<td align="center">프로지서 생성의 종료를 뜻하며 프로시저 이름은 생략 가능합니다.</td>
</tr>
</tbody></table>
<br/>

<ul>
<li><p>프로시저 생성하기
<img src="https://velog.velcdn.com/images/bebeco/post/96a46de4-d157-4cea-ad95-68579d839a2d/image.png" alt=""></p>
</li>
<li><p>프로시저 실행하기</p>
<pre><code class="language-sql">EXECUTE 프로시저 이름;</code></pre>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco/post/6817d682-0b45-4f20-916d-be0bd09f9b67/image.png" alt=""></p>
<br/>

<h3 id="프로시저-내용-확인하기">프로시저 내용 확인하기</h3>
<ul>
<li>이미 저장되어 있는 프로시저를 포함하여 서브프로그램의 소스 코드 내용을 확인하려면 USER_SOURCE 데이터 사전에서 조회한다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">USER_SOURCE의 열</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">NAME</td>
<td align="center">서브프로그램(생성 객체) 이름</td>
</tr>
<tr>
<td align="center">TYPE</td>
<td align="center">서브프로그램 종류(PROCEDURE, FUNCTION 등)</td>
</tr>
<tr>
<td align="center">LINE</td>
<td align="center">서브프로그램에 작성한 줄 번호</td>
</tr>
<tr>
<td align="center">TEXT</td>
<td align="center">서브프로그램에 작성한 소스 코드</td>
</tr>
</tbody></table>
<pre><code class="language-sql">// USER_SOURCE를 통해 프로시저 확인하기
SELECT *
FROM USER_SOURCE
WHERE NAME = &#39;PRO_NOPARAM&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco/post/ac7109d3-7cc9-49c8-bc5d-c9fb793636cb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco/post/bf6306a7-b4f8-4bd9-86eb-57d07b1bc7b1/image.png" alt=""></p>
<br/>

<h3 id="프로시저-삭제하기">프로시저 삭제하기</h3>
<ul>
<li>DROP PROCEDURE 명령어로 프로시저를 삭제할 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco/post/22741944-01f9-4fc2-bf6e-fe5af3a756ab/image.png" alt=""></p>
<br/>

<blockquote>
<p>파라미터를 사용하는 프로시저</p>
</blockquote>
<ul>
<li>프로시저를 실행하기 위해 입력 데이터가 필요한 경우에 파라미터를 정의할 수 있다. 파라미터는 여러 개 작성할 수 있으며 다음과 같은 형식으로 사용한다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CREATE 1.[OR REPLACE] PROCEDURE 2.프로시저 이름
[(파라미터 이름1 [modes] 자료형 [ := | DEFAULT 기본값], 3.
  파라미터 이름2 [modes] 자료형 [ := | DEFAULT 기본값],
  ...
  파라미터 이름N [modes] 자료형 [ := | DEFAULT 기본값]
)]
IS | AS 4.
   선언부
BEGIN
   실행부
EXCEPTION 5.
   예외 처리부
END [프로시저 이름]; 6.</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">지정한 프로시저 이름을 가진 프로시저가 이미 존재하는 경우에 현재 작성한 내용으로 대체합니다. 즉 덮어 쓴다는 뜻이며 생략 가능한 옵션입니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">저장할 프로시저의 고유 이름을 지정합니다. 같은 스키마 내에서 중복될 수 없습니다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">실행에 필요한 파라미터를 정의합니다. 파라미터는 쉼표(,)로 구분하여 여러 개 지정할 수 있습니다. 기본값과 모드(modes)는 생략 가능합니다. 자료형은 자리수 지정 및 NOT NULL 제약 조건 사용이 불가능합니다.</td>
</tr>
<tr>
<td align="center">4.</td>
<td align="center">선언부를 시작하기 위해 IS 또는 AS 키워드를 사용합니다. 선언부가 존재하지 않더라도 반드시 명시합니다. DECLARE 키워드는 사용하지 않습니다.</td>
</tr>
<tr>
<td align="center">5.</td>
<td align="center">예외 처리부는 생략 가능합니다.</td>
</tr>
<tr>
<td align="center">6.</td>
<td align="center">프로시저 생성의 종료를 뜻하며 프로시저 이름은 생략 가능합니다.</td>
</tr>
</tbody></table>
<br/>

<table>
<thead>
<tr>
<th align="center">파라미터 모드</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">IN</td>
<td align="center">지정하지 않으면 기본값으로 프로시저를 호출할 때 값을 입력받습니다.</td>
</tr>
<tr>
<td align="center">OUT</td>
<td align="center">호출할 때 값을 반환합니다.</td>
</tr>
<tr>
<td align="center">IN OUT</td>
<td align="center">호출할 때 값을 입력받은 후 실행 결과 값을 반환합니다.</td>
</tr>
</tbody></table>
<h3 id="in-모드-파라미터">IN 모드 파라미터</h3>
<ul>
<li>프로시저 실행에 필요한 값을 직접 입력받는 형식의 파라미터를 지정할 때 IN을 사용한다.</li>
<li>IN은 기본값이기 때문에 생략 가능하다.</li>
</ul>
<p>프로시저에 파라미터 지정하기
<img src="https://velog.velcdn.com/images/bebeco/post/7e0ce48d-c896-4942-a665-32fe52174485/image.png" alt=""></p>
<p>파라미터를 입력하여 프로시저 사용하기
<img src="https://velog.velcdn.com/images/bebeco/post/10419db1-492a-4925-b281-8a4f46ad9170/image.png" alt=""></p>
<p>기본값이 지정된 파라미터 입력을 제외하고 프로시저 사용하기
<img src="https://velog.velcdn.com/images/bebeco/post/7532f0dd-79c5-4171-bbee-e80fa691bd78/image.png" alt=""></p>
<p>실행에 필요한 개수보다 적은 파라미터를 입력하여 프로시저 실행하기
<img src="https://velog.velcdn.com/images/bebeco/post/189858bf-d117-4ff0-bcee-a8ea214ef1ac/image.png" alt=""></p>
<p>파라미터 이름을 활용하여 프로시저에 값 입력하기
<img src="https://velog.velcdn.com/images/bebeco/post/ccb4d66e-12a3-4e8c-b999-cda5806c7d21/image.png" alt=""></p>
<table>
<thead>
<tr>
<th align="center">종류</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">위치 지정</td>
<td align="center">지정한 파라미터 순서대로 값을 지정하는 방식</td>
</tr>
<tr>
<td align="center">이름 지정</td>
<td align="center">=&gt; 연산자로 파라미터 이름을 명시하여 값을 지정하는 방식</td>
</tr>
<tr>
<td align="center">혼합 지정</td>
<td align="center">일부 파라미터는 순서대로 값만 지정하고 일부 파라미터는 =&gt; 연산자로 값을 지정하는 방식(11g부터 사용 가능)</td>
</tr>
</tbody></table>
<br/>

<h3 id="out-모드-파라미터">OUT 모드 파라미터</h3>
<ul>
<li>OUT 모드를 사용한 파라미터는 프로시저 실행 후 호출한 프로그램으로 값을 반환한다.</li>
</ul>
<p>OUT 모드 파라미터 정의하기
<img src="https://velog.velcdn.com/images/bebeco/post/b8e4ade1-aa84-4fa3-8e07-45462451d42f/image.png" alt=""></p>
<p>OUT 모드 파라미터 사용하기
<img src="https://velog.velcdn.com/images/bebeco/post/06bea861-80fd-4ba1-91b8-221161d2cd3f/image.png" alt=""></p>
<br/>

<h3 id="in-out-모드-파라미터">IN OUT 모드 파라미터</h3>
<ul>
<li>IN OUT 모드로 선언한 파라미터는 IN, OUT으로 선언한 파라미터 기능을 동시에 수행한다.</li>
</ul>
<p>IN OUT 모드 파라미터 정의하기
<img src="https://velog.velcdn.com/images/bebeco/post/0f0492fa-a735-4b12-8b81-ccdbd549054b/image.png" alt=""></p>
<p>IN OUT 모드 파라미터 사용하기
<img src="https://velog.velcdn.com/images/bebeco/post/be71a779-210d-43aa-b932-7bc7cae1453b/image.png" alt=""></p>
<br/>

<blockquote>
<p>프로시저 오류 정보 확인하기</p>
</blockquote>
<p>생성할 때 오류가 발생하는 프로시저 알아보기
<img src="https://velog.velcdn.com/images/bebeco/post/e75eb70a-c107-430d-ad5b-cbc0b70fad20/image.png" alt=""></p>
<p>▶︎ 서브프로그램을 만들 때 발생한 오류는 SHOW ERRORS 명령어와 USER_ERRORS 데이터 사전을 조회하여 확인할 수 있다.</p>
<h3 id="show-errors로-오류-확인">SHOW ERRORS로 오류 확인</h3>
<ul>
<li>SHOW ERRORS 명령어는 가장 최근에 생성되거나 변경된 서브프로그램의 오류 정보를 출력한다.</li>
</ul>
<p>SHOW ERRORS 명령어로 오류 확인하기
<img src="https://velog.velcdn.com/images/bebeco/post/1ec831d2-cfb2-4737-a784-86a6e98b5324/image.png" alt=""></p>
<p>▶︎ SHOW ERRORS 명령어는 줄여서 SHOW ERR로 사용할 수도 있다.</p>
<pre><code class="language-sql">// 최근에 발생한 프로그램 오류가 아니라 특정 프로그램의 오류 정보를 확인하기
SHOW ERR 프로그램 종류 프로그램 이름;
SHOW ERR PROCEDURE pro_err;</code></pre>
<h3 id="user_errors로-오류-확인">USER_ERRORS로 오류 확인</h3>
<pre><code class="language-sql">// USER_ERRORS로 오류 확인하기
SELECT *
  FROM USER_ERRORS
 WHERE NAME = &#39;PRO_ERR&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco/post/fdc23673-8c4c-4dad-871f-9d7a60cc225a/image.png" alt=""></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day26]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day26</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day26</guid>
            <pubDate>Mon, 05 Dec 2022 18:28:21 GMT</pubDate>
            <description><![CDATA[<h2 id="18---2-오류가-발생해도-프로그램이-비정상-종료되지-않도록-하는-예외-처리">18 - 2 오류가 발생해도 프로그램이 비정상 종료되지 않도록 하는 예외 처리</h2>
<br/>

<blockquote>
<p>오류란?</p>
</blockquote>
<ul>
<li><p>오라클에서 SQL 또는 PL/SQL이 정상 수행되지 못하는 상황을 오류(error)라고 한다. 이 오류는 크게 두 가지로 구분된다.</p>
<ol>
<li><p>문법이 잘못되었거나 오타로 인한 오류로 컴파일 오류(compile Error), 문법 오류(syntax error)라고 한다.</p>
</li>
<li><p>명령문의 실행 중 발생한 오류를 런타임 오류(runtime error) 또는 실행 오류(execute error)라고 부른다.</p>
</li>
</ol>
</li>
<li><p>오라클에서는 이 두 가지 오류 중 후자, 즉 프로그램이 실행되는 도중 발생하는 오류를 예외(exception)라고 한다.</p>
</li>
</ul>
<br/>

<blockquote>
<p>예외 종류</p>
</blockquote>
<ul>
<li><p>오라클에서 예외는 크게 내부 예외(internal exceptions)와 사용자 정의 예외(user-defined exceptions)로 나뉜다.</p>
<ol>
<li><p>내부예외 : 오라클에서 미리 정의한 예외를 뜻하며 내부 예외는 이름이 정의되어 있는 예외인 사전 정의된 예외(predefined name exceptions)와 이름이 정해지지 않은 예외로 다시 나뉜다.</p>
</li>
<li><p>사용자 정의 예외 : 사용자가 필요에 따라 추가로 정의한 예외를 의미한다.</p>
</li>
</ol>
</li>
</ul>
<p>| 예외 종류 | 설명 | 
|:-----:|:--------:|:------------|
| 내부 예외<br/> (internal<br/> exceptions) | 사전 정의된 예외<br/> (predefined name exceptions) | 내부 예외 중 예외 번호에 해당하는 이름이 존재하는 예외 |
| | 이름이 없는 예외<br/> (unnames exceptions) | 내부 예외 중 이름이 존재하지 않는 예외(사용자가 필요에 따라 이름을 지정할 수 있음) |
| 사용자 정의 예외(user-defined exceptions) | | 사용자가 필요에 따라 직접 정의한 예외 |</p>
<br/>

<blockquote>
<p>예외 처리부 작성</p>
</blockquote>
<ul>
<li>예외 처리부는 EXCEPTION절에 필요한 코드를 사용하여 작성한다.</li>
<li>여러 예외를 명시하여 작성할 수 있다.</li>
<li>WHEN으로 시작하는 절을 예외 핸들러(exception handler)라고 하며, 발생한 예외 이름과 일치하는 WHEN절의 명령어를 수행한다.</li>
<li>수행할 명령어는 PL/SQL 실행부와 마찬가지로 여러 문법을 사용할 수 있다.</li>
<li>OTHERS는 먼저 작성한 어느 예외와도 일치하는 예외가 없을 경우에 처리할 내용을 작성한다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
EXCEPTION
  WHEN 예외 이름1 [OR 예외 이름2 - ] THEN
    예외 처리에 사용할 명령어;
  WHEN 예외 이름3 [OR 예외 이름4 - ] THEN
    예외 처리에 사용할 명령어;
  ...
  WHEN OTHERS THEN
    예외 처리에 사용할 명렁어;</code></pre>
<br/>

<h3 id="이름-없는-예외-사용">이름 없는 예외 사용</h3>
<ul>
<li>이름이 없는 내부 예외를 사용해야 한다면 이름을 직접 지정해 주어야 예외 처리부에서 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
DECLARE
  예외 이름1 EXCEPTION;
  PRAGMA EXCEPTION_INIT(예외 이름1, 예외 번호);
.
.
.
EXCEPTION
  WHEN 예외 이름1 THEN
    예외 처리에 사용할 명령어;
  ...
END;</code></pre>
<br/>

<h3 id="사용자-정의-예외-사용">사용자 정의 예외 사용</h3>
<ul>
<li>사용자 정의 예외는 오라클에 정의되어 있지 않은 특정 상황을 직접 오류로 정의하는 방식이다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
DECLARE
  사용자 예외 이름 EXCEPTION;
  ...
BEGIN
  IF 사용자 예외를 발생시킬 조건 THEN
    RAISE 사용자 예외 이름
  ...
  END IF;
EXCEPTION
  WHEN 사용자 예외 이름 THEN
    예외 처리에 사용할 명령어;
  ...
END;</code></pre>
<br/>

<h3 id="오류-코드와-오류-메시지-사용">오류 코드와 오류 메시지 사용</h3>
<ul>
<li>오류 처리부가 잘 작성되어 있다면 오류가 발생해도 PL/SQL은 정상 종료된다. PL/SQL문의 정상 종료 여부와 상관없이 발생한 오류 내역을 알고 싶을 때 SQLCODE, SQLERRM 함수를 사용한다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">함수</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">SQLCODE</td>
<td align="center">오류 번호를 반환하는 함수</td>
</tr>
<tr>
<td align="center">SQLERRM</td>
<td align="center">오류 메시지를 반환하는 함수</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day25]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day25</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day25</guid>
            <pubDate>Mon, 05 Dec 2022 18:27:55 GMT</pubDate>
            <description><![CDATA[<h2 id="18---1-특정-열을-선택하여-처리하는-커서">18 - 1 특정 열을 선택하여 처리하는 커서</h2>
<br/>

<blockquote>
<p>커서란?</p>
</blockquote>
<ul>
<li>커서(cursor)는 SELECT문 또는 데이터 조작어 같은 SQL문을 실행했을 때 해당 SQL문을 처리하는 정보를 저장한 메모리 공간을 뜻한다.<br/>

</li>
</ul>
<blockquote>
<p>SELECT INTO 방식</p>
</blockquote>
<ul>
<li>SELECT INTO문은 조회되는 데이터가 단 하나의 행일 때 사용 가능한 방식이다. </li>
<li>커서는 결과 행이 하나이든 여러 개이든 상관없이 사용할 수 있다.</li>
<li>SELECT INTO문은 SELECT절에 명시한 각 열의 결과 값을 다음과 같이 변수에 대입해 준다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
SELECT 열1, 열2, ..., 열n INTO 변수1, 변수2, ..., 변수n
FROM ...
///

```sql
// SELECT INTO를 사용한 단일행 데이터 저장하기
DECLARE
V_DEPT_ROW DEPT%ROWTYPE;
BEGIN
SELECT DEPTNO, DNAME, LOC INTO V_DEPT_ROW
FROM DEPT
WHERE DEPTNO = 40;
DBMS_OUTPUT.PUT_LINE(&#39;DEPTNO : &#39; || V_DEPT_ROW.DEPTNO);
DBMS_OUTPUT.PUT_LINE(&#39;DNAME : &#39; || V_DEPT_ROW.DNAME);
DBMS_OUTPUT.PUT_LINE(&#39;LOC : &#39; || V_DEPT_ROW.LOC);
END;
/</code></pre>
<br/>

<blockquote>
<p>명시적 커서</p>
</blockquote>
<ul>
<li>명시적 커서는 사용자가 직접 커서를 선언하고 사용하는 커서를 뜻한다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">단계</th>
<th align="center">명칭</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1단계</td>
<td align="center">커서 선언<br/> (declaration)</td>
<td align="center">사용자가 직접 이름을 지정하여 사용할 커서를 SQL문과 함께 선언합니다.</td>
</tr>
<tr>
<td align="center">2단계</td>
<td align="center">커서 열기<br/> (open)</td>
<td align="center">커서를 선언할 때 작성한 SQL문을 실행합니다. 이때 실행한 SQL문에 영향을 받는 행을 active set라 합니다.</td>
</tr>
<tr>
<td align="center">3단계</td>
<td align="center">커서에서 읽어온<br/> 데이터 사용<br/> (fetch)</td>
<td align="center">실행된 SQL문의 결과 행 정보를 하나씩 읽어 와서 변수에 저장한 후 필요한 작업을 수행합니다. 각 행별로 공통 작업을 반복해서 실행하기 위해 여러 종류의 LOOP문을 함께 사용할 수 있습니다.</td>
</tr>
<tr>
<td align="center">4단계</td>
<td align="center">커서 닫기<br/> (close)</td>
<td align="center">모든 행의 사용이 끝나고 커서를 종료합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">// 기본 형식
DECLARE
    CURSOR 커서 이름 IS SQL문; -- 커서 선언(Declaration)
BEGIN
    OPEN 커서 이름;              -- 커서 열기(Open)
    FETCH 커서이름 INTO 변수     -- 커서로부터 읽어온 데이터 사용(Fetch)
    CLOSE 커서이름;              -- 커서 닫기(Close)
END;</code></pre>
<br/>

<h3 id="하나의-행만-조회되는-경우">하나의 행만 조회되는 경우</h3>
<ul>
<li>하나의 행만 조회되는 SELECT문을 커서로 지정하여 사용할 경우 SELECT INTO문을 사용할 때보다 복잡한 여러 단계를 작성해여 하므로 다소 번거롭다. 커서의 효용성은 조회되는 행이 여러 개일 때 극대화된다.</li>
</ul>
<br/>

<h3 id="여러-행이-조회되는-경우-사용하는-loop문">여러 행이 조회되는 경우 사용하는 LOOP문</h3>
<ul>
<li><p>커서에 지정한 SELECT문이 여러 행을 결과 값을 가질 경우에 여러 방식의 LOOP문을 사용할 수 있다.</p>
</li>
<li><p>%NOTFOUND는 실행된 FETCH문에서 행을 추출했으면 false, 추출하지 않았으면 true를 반환한다.</p>
</li>
<li><p>FETCH문을 통해 더 이상 추출한 데이터가 없을 경우에 LOOP 반복이 끝난다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th align="center">속성</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">커서 이름%NOTFOUND</td>
<td align="center">수행된 FETCH문을 통해 추출된 행이 있으면 false, 없으면 true를 반환합니다.</td>
</tr>
<tr>
<td align="center">커서 이름%FOUND</td>
<td align="center">수행된 FETCH문을 통해 추출된 행이 있으면 true, 없으면 false를 반환합니다.</td>
</tr>
<tr>
<td align="center">커서 이름%ROWCOUNT</td>
<td align="center">현재까지 추출된 행 수를 반환합니다.</td>
</tr>
<tr>
<td align="center">커서 이름%ISOPEN</td>
<td align="center">커서가 열려(open) 있으면 true, 닫혀(close) 있으면 false를 반환합니다.</td>
</tr>
</tbody></table>
<br/>

<h3 id="여러-개의-행이-조회되는-경우for-loop문">여러 개의 행이 조회되는 경우(FOR LOOP문)</h3>
<ul>
<li>커서에 FOR LOOP문을 사용하면 좀 더 간편하게 여러 행을 다룰 수 있다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
FOR 루프 인덱스 이름 IN 커서 이름 LOOP
   결과 행별로 반복 수행할 작업;
END LOOP;</code></pre>
<br/>

<h3 id="커서에-파라미터-사용하기">커서에 파라미터 사용하기</h3>
<ul>
<li>고정 값이 아닌 직접 입력한 값 또는 상황에 따라 여러 값을 번갈아 사용하려면 다음과 같이 커서에 파라미터를 지정할 수 있다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
CURSOR 커서 이름(파라미터 이름 자료형, ...) IS
SELECT ...</code></pre>
<br/>

<blockquote>
<p>묵시적 커서</p>
</blockquote>
<ul>
<li>묵시적 커서는 별다른 선언 없이 SQL문을 사용했을 때 오라클에서 자동으로 선언되는 커서를 뜻한다.</li>
<li>자동으로 생성되어 실행되는 묵시적 커서는 별다른 PL/SQL문을 작성하지 않아도 되지만, 다음 묵시적 커서의 속성을 사용하면 현재 커서의 정보를 확인할 수 있다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">속성</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">SQL%NOTFOUND</td>
<td align="center">묵시적 커서 안에 추출한 행이 있으면 false, 없으면 true를 반환합니다. DML 명령어로 영향을 받는 행이 없을 경우에도 true를 반환합니다.</td>
</tr>
<tr>
<td align="center">SQL%FOUND</td>
<td align="center">묵시적 커서 안에 추출한 행이 있으면 true, 없으면 false를 반환합니다. DML 명령어로 영향을 받는 행이 있다면 true를 반환합니다.</td>
</tr>
<tr>
<td align="center">SQL%ROWCOUNT</td>
<td align="center">묵시적 커서에 현재까지 추출한 행 수 또는 DML 명령어로 영향받는 행 수를 반환합니다.</td>
</tr>
<tr>
<td align="center">SQL%ISOPEN</td>
<td align="center">묵시적 커서는 자동으로 SQL문을 실행한 후 CLOSE되므로 이 속성은 항상 false를 반환합니다.</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day24]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day24</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day24</guid>
            <pubDate>Mon, 05 Dec 2022 18:27:29 GMT</pubDate>
            <description><![CDATA[<h2 id="17---1-자료형이-다른-여러-데이터를-저장하는-레코드">17 - 1 자료형이 다른 여러 데이터를 저장하는 레코드</h2>
<br/>

<blockquote>
<p>레코드란?</p>
</blockquote>
<ul>
<li>레코드(record)는 자료형이 각기 다른 데이터를 하나의 변수에 저장하는 데 사용한다.</li>
</ul>
<pre><code class="language-sql">// 기본 형식
TYPE 레코드 이름 IS RECORD(
변수 이름 자료형 NOT NULL := (또는 DEFAULT) 값 또는 값이 도출되는 여러 표현식
)
// 1. 레코드 이름
// 2. 변수 이름
// 3. 자료형
// 4. NOT NULL
// 5. := (또는 DEFAULT) 값 또는 값이 도출되는 여러 표현식</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">저장할 레코드 이름을 지정합니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">레코드 안에 포함할 변수를 지정합니다. 변수는 여러 개 지정할 수 있으며 각 변수는 쉼표(,)로 구분합니다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">지정한 변수의 자료형을 지정합니다. 이 자료형 역시 %TYPE, %ROWTYPE 지정이 가능합니다.</td>
</tr>
<tr>
<td align="center">4.</td>
<td align="center">지정한 변수에 NOT NULL 제약 조건을 지정합니다(생략 가능).</td>
</tr>
<tr>
<td align="center">5.</td>
<td align="center">기본값을 지정합니다(생략 가능).</td>
</tr>
</tbody></table>
<ul>
<li>정의한 레코드는 지금까지 다룬 변수와 마찬가지로 기존 자료형처럼 사용할 수 있다. 레코드에 포함된 변수는 레코드 이름과 마침표(.)로 사용할 수 있다.</li>
</ul>
<br/>

<blockquote>
<p>레코드를 사용한 INSERT</p>
</blockquote>
<ul>
<li>PL/SQL문에서는 테이블에 데이터를 삽입하거나 수정하는 INSERT, UPDATE문에도 레코드를 사용할 수 있다.</li>
</ul>
<br/>

<blockquote>
<p>레코드를 사용한 UPDATE</p>
</blockquote>
<ul>
<li>레코드는 UPDATE문에도 사용할 수 있다. 이 경우에 SET절은 ROW 키워드와 함께 레코드 이름을 명시한다. 기존 UPDATE문에서는 SET절을 통해 변경할 열을 하나하나 지정한 것과 달리 레코드에 저장된 데이터를 사용하여 행 전체의 데이터를 바꿔 준다.</li>
</ul>
<br/>

<h2 id="17---2-자료형이-같은-여러-데이터를-저장하는-컬렉션">17 - 2 자료형이 같은 여러 데이터를 저장하는 컬렉션</h2>
<br/>

<ul>
<li><p>컬렉션은 특정 자료형의 데이터를 여러 개 저장하는 복합 자료형이다. 여러 종류의 데이터를 하나로 묶어 사용하는 레코드를 테이블의 한 행처럼 사용한다면, 컬렉션은 열 또는 테이블과 같은 형태로 사용할 수 있다.</p>
</li>
<li><p>PL/SQL에서 사용할 수 있는 컬렉션은 다음과 같이 세 가지 종류가 있다.</p>
<ol>
<li><p>연관 배열(associative array (or index by table)</p>
</li>
<li><p>중첩 테이블(nested table)</p>
</li>
<li><p>VARRAY(variable-size array)</p>
</li>
</ol>
<br/>

</li>
</ul>
<blockquote>
<p>연관 배열</p>
</blockquote>
<ul>
<li><p>연관 배열은 인덱스라고도 불리는 키(key), 값(value)으로 구성되는 컬렉션이다.</p>
</li>
<li><p>중복되지 않은 유일한 키를 통해 값을 저장하고 불러오는 방식을 사용한다.</p>
</li>
<li><p>연관 배열을 정의할 때 자료형이 TABLE인 변수를 다음과 같이 작성한다.</p>
</li>
</ul>
<pre><code class="language-sql">// 기본 형식
TYPE 연관 배열 이름 IS TABLE OF 자료형[NOT NULL]
INDEX BY 인덱스형;
// 1. 연관 배열 이름
// 2. 자료형 [NOT NULL]
// 3. 인덱스형</code></pre>
<table>
<thead>
<tr>
<th align="center">번호</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1.</td>
<td align="center">작성할 연관 배열 이름을 지정합니다.</td>
</tr>
<tr>
<td align="center">2.</td>
<td align="center">연관 배열 열에 사용할 자료형을 지정합니다. 이 자료형에는 VARCHAR2, DATE, NUMBER와 같은 단일 자료형을 지정할 수 있고 %TYPE, %ROWTYPE 같은 참조 자료형도 사용할 수 있다. NOT NULL 옵션을 사용할 수 있으며 생략 가능하다.</td>
</tr>
<tr>
<td align="center">3.</td>
<td align="center">키로 사용할 인덱스의 자료형을 지정합니다. BINARY_INTEGER, PLS_INTEGER 같은 정수 또는 VARCHAR2 같은 문자 자료형도 사용할 수 있습니다.</td>
</tr>
</tbody></table>
<br/>

<blockquote>
<p>컬렉션 메서드</p>
</blockquote>
<ul>
<li><p>오라클에서는 켈렉션 사용상의 편의를 위해 몇 가지 서브프로그램을 제공하고 있다. 이를 컬렉션 메서드라고 한다.</p>
</li>
<li><p>컬렉션 메서드는 컬렉션과 관련된 다양한 정보 조회 기능을 제공한다. 이와 더불어 컬렉션 내의 데이터 삭제나 컬렉션 크기 조절을 위한 특정 조작도 가능하다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th align="center">메서드</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">EXISTS(n)</td>
<td align="center">컬렉션에서 n인덱스의 데이터 존재 여부를 true/false로 반환합니다.</td>
</tr>
<tr>
<td align="center">COUNT</td>
<td align="center">컬렉션에 포함되어 있는 요소 개수를 반환합니다.</td>
</tr>
<tr>
<td align="center">LIMIT</td>
<td align="center">현재 컬렉션의 최대 크기를 반환합니다. 최대 크기가 없으면 NULL을 반환합니다.</td>
</tr>
<tr>
<td align="center">FIRST</td>
<td align="center">컬렉션의 첫 번째 인덱스 번호를 반환합니다.</td>
</tr>
<tr>
<td align="center">LAST</td>
<td align="center">컬렉션의 마지막 인덱스 번호를 반환합니다.</td>
</tr>
<tr>
<td align="center">PRIOR(n)</td>
<td align="center">컬렉션에서 n인덱스 바로 앞 인덱스 값을 반환합니다. 대상 인덱스 값이 존재하지 않는다면 NULL을 반환합니다.</td>
</tr>
<tr>
<td align="center">NEXT(n)</td>
<td align="center">컬렉션에서 n인덱스 바로 다음 인덱스 값을 반환합니다. 대상 인덱스 값이 존재하지 않는다면 NULL을 반환합니다.</td>
</tr>
<tr>
<td align="center">DELETE</td>
<td align="center">컬렉션에 저장된 요소를 지우는 데 사용합니다. 다음 세 가지 방식으로 사용합니다.<br/> • DELETE : 컬렉션에 저장되어 있는 모든 요소를 삭제합니다.<br/> • DELETE(n) : n인덱스의 컬렉션 요소를 삭제합니다.<br/> • DELETE(n,m) : n인덱스부터 m인덱스까지 요소를 삭제합니다.</td>
</tr>
<tr>
<td align="center">EXTEND</td>
<td align="center">컬렉션 크기를 증가시킵니다. 연관 배열을 제외한 중첩 테이블과 VARRAY에서 사용합니다.</td>
</tr>
<tr>
<td align="center">TRIM</td>
<td align="center">컬렉션 크기를 감소시킵니다. 연관 배열을 제외한 중첩 테이블과 VARRAY에서 사용합니다.</td>
</tr>
</tbody></table>
<ul>
<li>컬렉션 메서드는 컬렉션형으로 선언한 변수에 마침표(.)와 함께 작성하여 사용할 수 있다.</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day13]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day13</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day13</guid>
            <pubDate>Mon, 05 Dec 2022 18:17:10 GMT</pubDate>
            <description><![CDATA[<h2 id="09---1-서브쿼리">09 - 1 서브쿼리</h2>
<ul>
<li>서브쿼리는 SQL문을 실행하는 데 필요한 데이터를 추가로 조회하기 위해 SQL문 내부에서 사용하는 SELECT문을 의미한다.</li>
<li>서브퀴리의 결과 값을 사용하여 기능을 수행하는 영역은메인쿼리라고 부른다.</li>
</ul>
<pre><code class="language-sql">// 메인쿼리
SELECT 조회할 열
FROM 조회할 테이블
WHERE 조건식 ( SELECT 조회할 열 // 서브쿼리
                               FROM 조회할 테이블
                                WHERE 조건식 )</code></pre>
<ul>
<li>서브쿼리 작성의 핵심은 주어진 문제를 어떻게 SELECT문으로 나누어 처리할지를 결정하는 데에 있다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL &gt; (SELECT SAL
                             FROM EMP
                            WHERE ENAME = &#39;JONES&#39;);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/2c6d8d50-c4ca-4e4f-8b9a-2b2459cb9811/image.png" alt=""></p>
<blockquote>
<p>서브쿼리의 특징</p>
</blockquote>
<ol>
<li>서브쿼리는 연산자와 같은 비교 또는 조회 대상의 오른쪽에 놓이면 괄호 ()로 묶어서 사용한다.</li>
<li>특수한 몇몇 경우를 제외한 대부분의 서브쿼리에서는 ORDER BY절을 사용할 수 없다.</li>
<li>서브쿼리의 SELECT절에 명시한 열은 메인쿼리의 비교 대상과 같은 자료형과 같은 개수로 지정해야 한다. 즉 메인쿼리의 비교 대상 데이터가 하나라면 서브쿼리의 SELECT절 역시 같은 자료형인 열을 하나 지정해야 한다.</li>
<li>서브쿼리에 있는 SELECT문의 결과 행 수는 함께 사용하는 메인쿼리의 연산자 종류와 호환 가능해야 한다. 예를 들어 메인쿼리에 사용한 연산자가 단 하나의 데이터로만 연산이 가능한 연산자라면 서브쿼리의 결과 행 수는 반드시 하나여야 한다. 이 내용은 ‘단일행 서브쿼리 및 다중행 서브쿼리’에서 자세히 살펴보겠다.</li>
</ol>
<h2 id="09---2-실행-결과가-하나인-단일행-서브쿼리">09 - 2 실행 결과가 하나인 단일행 서브쿼리</h2>
<ul>
<li>단일행 서브쿼리는 실행 결과가 단 하나의 행으로 나오는 서브쿼리를 뜻한다. 서브쿼리에서 출력되는 결과가 하나이므로 메인쿼리와 서브쿼리 결과는 다음과 같이 단일행 연산자를 사용하여 비교한다.</li>
</ul>
<table>
<thead>
<tr>
<th>단일행 연산자</th>
</tr>
</thead>
<tbody><tr>
<td>&gt;          ≥         =          ≤         &lt;         &lt;&gt; ^= ! =</td>
</tr>
<tr>
<td>초과     이상     같음     이하     미만     같지 않음</td>
</tr>
<tr>
<td>- 이름으로 단일행 서브쿼리를 사용하는 것은 나중에 문제가 될 수 있다. 사람 이름뿐만 아니라 같은 데이터가 여러 개 존재하는 열의 경우에는 중복이 가능하기 때문에 주의해야 한다.</td>
</tr>
<tr>
<td>- 이름을 가진 사원이 여러 명 있었다면 대소 비교 연산자를 사용한 서브쿼리는 오류가 발생하고 실행되지 못한다. 이와 같이 서브쿼리의 결과로 여러 행을 반환할 때에는 다중행 서브쿼리를 사용해야 한다.</td>
</tr>
</tbody></table>
<blockquote>
<p>단일행 서브쿼리와 날짜형 데이터</p>
</blockquote>
<ul>
<li>단일행 서브쿼리는 서브쿼리 결과 값이 날짜(DATE) 자료형일 때도 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE HIREDATE &lt; (SELECT HIREDATE
                                        FROM EMP
                                     WHERE ENAME = &#39;SCOTT&#39;);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/b92be037-1666-4061-a4d6-41032f6553ec/image.png" alt=""></p>
<blockquote>
<p>단일행 서브쿼리와 함수</p>
</blockquote>
<ul>
<li>서브쿼리에서 특정 함수를 사용한 결과 값이 하나일 때 역시 단일행 서브쿼리로서 사용 가능하다.</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, E.JOB, E.SAL, D.DEPTNO, D.DNAME, D.LOC
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND E.DEPTNO = 20
AND E.SAL &gt; (SELECT AVG(SAL)
                            FROM EMP);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/aca17dd8-e939-418e-941f-991d18687397/image.png" alt=""></p>
<h2 id="09---3-실행-결과가-여러-개인-다중행-서브쿼리">09 - 3 실행 결과가 여러 개인 다중행 서브쿼리</h2>
<ul>
<li>다중행 서브쿼리는 실행 결과 행이 여러 개로 나오는 서브쿼리를 가리킨다.</li>
</ul>
<table>
<thead>
<tr>
<th>다중행 연산자</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>IN</td>
<td>메인쿼리의 데이터가 서브쿼리의 결과 중 하나라도 일치한 데이터가 있다면 true</td>
</tr>
<tr>
<td>ANY, SOME</td>
<td>메인쿼리의 조건식을 만족하는 서브쿼리의 결과가 하나 이상이면 true</td>
</tr>
<tr>
<td>ALL</td>
<td>메인쿼리의 조건식을 서브쿼리의 결과 모두가 만족하면 true</td>
</tr>
<tr>
<td>EXISTS</td>
<td>서브쿼리의 결과가 존재하면(즉, 행이 1개 이상일 경우) true</td>
</tr>
</tbody></table>
<blockquote>
<p>IN</p>
</blockquote>
<ul>
<li>부서별 최고 급여 데이터를 먼저 구하고, 이 데이터와 일치하는 메인쿼리 데이터를 IN 연산자를 통해 선별해 낼 수 있다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL IN (SELECT MAX(SAL)
                FROM EMP
              GROUP BY DEPTNO);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/a0fd5e70-3e0d-4657-a838-e87c4994177e/image.png" alt=""></p>
<ul>
<li>다중행 연산자 중 IN 연산자는 가장 자주 사용하는 연산자이므로 사용법을 반드시 기억해 두자.</li>
</ul>
<blockquote>
<p>ANY, SOME 연산자</p>
</blockquote>
<ul>
<li>ANY, SOME 연산자는 서브쿼리가 반환한 여러 결과 값 중 메인쿼리와 조건식을 사용한 결과가 하나라도 true라면 메인쿼리 조건식을 true로 반환해 주는 연산자이다.</li>
<li>메인쿼리와 값을 비교할 때 ANY 및 SOME 연산자를 등가 비교 연산자(=)와 함께 사용하면 IN 연산자와 정확히 같은 기능을 수행한다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL = ANY (SELECT MAX(SAL)
                                    FROM EMP
                                    GROUP BY DEPTNO);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/f1f8362a-b385-4709-9543-b6691ceadf6a/image.png" alt=""></p>
<ul>
<li>등가 비교 연산자가 아닌 대소 비교 연산자를 ANY 연산자와 함께 사용하는 경우는 조금 생각을 해야 한다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL &lt; ANY (SELECT SAL
                                    FROM EMP
                                    WHERE DEPTNO = 30)
ORDER BY SAL, EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/c4be5539-ecfc-4ae3-91b8-653cbf1e4690/image.png" alt=""></p>
<pre><code class="language-sql">// &lt; ANY 연산자를 사용한 경우
SELECT *
FROM EMP
WHERE SAL &lt; ANY (SELECT SAL
                                FROM EMP
                                WHERE DEPTNO = 30)
ORDER BY SAL, EMPNO;</code></pre>
<pre><code class="language-sql">// 서브쿼리에 MAX 함수를 사용한 경우
SELECT *
FROM EMP
WHERE SAL &lt; (SELECT MAX(SAL)
                            FROM EMP
                            WHERE DEPTNO = 30)
ORDER BY SAL, EMPNO;</code></pre>
<blockquote>
<p>ALL 연산자</p>
</blockquote>
<p>ANY 및 SOME과 달리 ALL 연산자는 서브쿼리의 모든 결과가 조건식에 맞아떨어져야만 메인쿼리의 조건식이 true가 되는 연산자이다.</p>
<pre><code class="language-sql">// 부서 번호가 30번인 사원들의 최소 급여보다 더 적은 급여를 받는 사원 출력하기
SELECT *
FROM EMP
WHERE SAL &lt; ALL (SELECT SAL
                                    FROM EMP
                                WHERE DEPTNO = 30);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/5e6e5b80-be3d-4924-82a8-c7c67cd0bbb0/image.png" alt=""></p>
<blockquote>
<p>EXISTS 연산자</p>
</blockquote>
<p>EXISTS 연산자는 조금 특이한 연산자인데 서브쿼리에 값이 하나 이상 존재하면 조건식이 모두 true, 존재하지 않으면 false가 되는 연산자이다.</p>
<pre><code class="language-sql">// 서브쿼리 결과 값이 존재하는 경우
SELECT *
FROM EMP
WHERE EXISTS (SELECT DNAME
                FROM DEPT
                WHERE DEPTNO = 10);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/ddac60fe-73d6-4bc4-ad6a-0948057c1929/image.png" alt=""></p>
<pre><code class="language-sql">// 서브쿼리 결과 값이 존재하지 않는 경우
SELECT *
FROM EMP
WHERE EXISTS (SELECT DNAME
                FROM DEPT
                WHERE DEPTNO = 50);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/807ecd2d-962e-458a-967f-fcdb1c040964/image.png" alt=""></p>
<ul>
<li>EXISTS 연산자는 다른 다중행 연산자에 비해 그리 자주 사용하는 편은 아니지만, 특정 서브쿼리 결과 값의 존재 유무를 통해 메인쿼리의 데이터 노출 여부를 결정해야 할 때 간혹 사용한다.</li>
</ul>
<h2 id="09---4-비교할-열이-여러-개인-다중열-서브쿼리">09 - 4 비교할 열이 여러 개인 다중열 서브쿼리</h2>
<ul>
<li>다중열 서브쿼리는 서브쿼리의 SELECT절에 비교할 데이터를 여러 개 지정하는 방식이다.</li>
<li>메인쿼리에 비교할 열을 묶어 명시하고, 서브쿼리에서는 괄호로 묶은 데이터와 같은 자료형 데이터를 SELECT절에 명시하여 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">// 다중열 서브쿼리 사용하기
SELECT *
FROM EMP
WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL)
                                FROM EMP
                                GROUP BY DEPTNO);</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/f56c58e4-e8fa-4d19-8e98-e0552cce21a8/image.png" alt=""></p>
<h2 id="09---5-from절에-사용하는-서브쿼리와-with절">09 - 5 FROM절에 사용하는 서브쿼리와 WITH절</h2>
<ul>
<li>FROM절에 사용하는 서브쿼리는 인라인 뷰라고도 부른다.</li>
<li>인라인 뷰는 특정 테이블 전체가 아닌 SELECT문을 통해 일부 데이터를 먼저 추출해 온 후 별칭을 주어 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">// 인라인 뷰 사용하기
SELECT E10.EMPNO, E10.ENAME, E10.DEPTNO, D.DNAME, D.LOC
FROM (SELECT * FROM EMP WHERE DEPTNO = 10) E10,
    (SELECT * FROM DEPT) D
    WHERE E10.DEPTNO = D.DEPTNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/1a2826b7-99d8-4d22-8db9-6a6076ce0216/image.png" alt=""></p>
<p>하지만 FROM절에 너무 많은 서브쿼리를 지정하면 가독성이나 성능이 떨어질 수 있기 때문에 경우에 따라 WITH절을 사용하기도 한다.</p>
<p>WITH절은 메인쿼리가 될 SELECT문 안에서 사용할 서브쿼리와 별칭을 먼저 지정한 후 메인쿼리에서 사용한다.</p>
<pre><code class="language-sql">// 기본 형식
WITH
[별칭1] AS (SELECT문 1),
[별칭2] AS (SELECT문 2),
...
[별칭n] AS (SELECT문 n)
SELECT
FROM 별칭1, 별칭2, 별칭3
...</code></pre>
<pre><code class="language-sql">// WITH절 사용하기
WITH
E10 AS (SELECT * FROM EMP WHERE DEPTNO = 10),
D   AS (SELECT * FROM DEPT)
SELECT E10.EMPNO, E10.ENAME, E10.DEPTNO, D.DNAME, D.LOC
FROM E10, D
WHERE E10.DEPTNO = D.DEPTNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/83df2f3d-eeb9-469f-880c-6897852aa598/image.png" alt=""></p>
<h2 id="09---6-select절에-사용하는-서브쿼리">09 - 6 SELECT절에 사용하는 서브쿼리</h2>
<ul>
<li>서브쿼리는 SELECT절에도 사용할 수 있다. 흔히 스칼라 서브쿼리라고 부르는 이 서브쿼리는 SELECT절에 하나의 열 영역으로서 결과를 출력할 수 있다.</li>
</ul>
<pre><code class="language-sql">// SELECT절에 서브쿼리 사용하기
SELECT EMPNO, ENAME, JOB, SAL,
        (SELECT GRADE
            FROM SALGRADE
            WHERE E.SAL BETWEEN LOSAL AND HISAL) AS SALGRADE,
            DEPTNO,
            (SELECT DNAME
            FROM DEPT
            WHERE E.DEPTNO = DEPT.DEPTNO) AS DNAME
            FROM EMP E;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/8488068f-4c4f-4303-bd21-b8e0ddacf5a0/image.png" alt=""></p>
<p>SELECT절에 명시하는 서브쿼리는 반드시 하나의 결과만 반환하도록 작성해 주어야 한다는 것도 꼭 기억하자.</p>
<h1 id="잊기-전에-한-번-더">잊기 전에 한 번 더!</h1>
<ul>
<li>Q1.  전체 사원 중 ALLEN과 같은 직책(JOB)인 사원들의 사원 정보, 부서 정보를 다음과 같이 출력하는 SQL문을 작성하세요.</li>
</ul>
<pre><code class="language-sql">SELECT E.JOB, E.EMPNO, E.ENAME, E.SAL, E.DEPTNO, D.DNAME
  FROM EMP E, DEPT D
 WHERE E.DEPTNO = D.DEPTNO
   AND JOB = (SELECT JOB
                FROM EMP
               WHERE ENAME = &#39;ALLEN&#39;);</code></pre>
<ul>
<li>Q2. 전체 사원의 평균 급여(SAL)보다 높은 급여를 받는 사원들의 사원 정보, 부서 정보, 급여 등급 정보를 출력하는 SQL문을 작성하세요(단 출력할 때 급여가 많은 순으로 정렬하되 급여가 같을 경우에는 사원 번호를 기준으로 오름차순으로 정렬하세요).</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, D.DNAME, E.HIREDATE, D.LOC, E.SAL, S.GRADE
  FROM EMP E, DEPT D, SALGRADE S
 WHERE E.DEPTNO = D.DEPTNO
   AND E.SAL BETWEEN S.LOSAL AND S.HISAL
   AND SAL &gt; (SELECT AVG(SAL)
                FROM EMP)
ORDER BY E.SAL DESC, E.EMPNO;</code></pre>
<ul>
<li>Q3. 10번 부서에 근무하는 사원 중 30번 부서에는 존재하지 않는 직책을 가진 사원들의 사원 정보, 부서 정보를 다음과 같이 출력하는 SQL문을 작성하세요.</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, E.JOB, E.DEPTNO, D.DNAME, D.LOC
  FROM EMP E, DEPT D
 WHERE E.DEPTNO = D.DEPTNO
   AND E.DEPTNO = 10
   AND JOB NOT IN (SELECT DISTINCT JOB
                     FROM EMP
                    WHERE DEPTNO = 30);</code></pre>
<ul>
<li>Q4. 직책인 SALESMAN인 사람들의 최고 급여보다 높은 급여를 받는 사원들의 사원 정보, 급여 등급 정보를 다음과 같이 출력하는 SQL문을 작성하세요(단 서브쿼리를 활욜할 때 다중행 함수를 사용하는 방법과 사용하지 않는 방법을 통해 사원 번호를 기준으로 오름차순으로 정렬하세요).</li>
</ul>
<pre><code class="language-sql">-- 다중행 함수 사용하지 않는 방법
SELECT E.EMPNO, E.ENAME, E.SAL, S.GRADE
  FROM EMP E, SALGRADE S
 WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
   AND SAL &gt; (SELECT MAX(SAL)
                FROM EMP
               WHERE JOB = &#39;SALESMAN&#39;)
ORDER BY E.EMPNO; 

--다중행 함수 사용하는 방법
SELECT E.EMPNO, E.ENAME, E.SAL, S.GRADE
  FROM EMP E, SALGRADE S
 WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
   AND SAL &gt; ALL (SELECT DISTINCT SAL
                    FROM EMP
                   WHERE JOB = &#39;SALESMAN&#39;)
ORDER BY E.EMPNO; </code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[20220726 스터디 발표]]></title>
            <link>https://velog.io/@bebeco_o/20220726-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%9C%ED%91%9C</link>
            <guid>https://velog.io/@bebeco_o/20220726-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%9C%ED%91%9C</guid>
            <pubDate>Mon, 05 Dec 2022 18:14:33 GMT</pubDate>
            <description><![CDATA[<h1 id="08-여러-테이블을-하나의-테이블처럼-사용하는-조인">08. 여러 테이블을 하나의 테이블처럼 사용하는 조인</h1>
<h2 id="08---1-조인">08 - 1 조인</h2>
<blockquote>
<p>집합 연산자와 조인의 차이점</p>
</blockquote>
<ul>
<li>조인은 두 개 이상의 테이블 데이터를 가로로 연결하여 하나의 테이블처럼 출력할 때 사용하는 방식이다.</li>
<li>집합 연산자를 사용한 결과는 두 개 이상의 SELECT문의 결과 값을 세로로 연결한 것이다.</li>
</ul>
<blockquote>
<p>여러 테이블을 사용할 때의 FROM절</p>
</blockquote>
<ul>
<li>꼭 테이블이 아니더라도 테이블 형태, 즉 열과 행으로 구성된 데이터 집합이면 모두 FROM절에 지정 가능하다. SELECT절의 여러 열을 구분할 때와 마찬가지로 FROM절에 여러 테이블을 명시할 때 쉼표(,)를 구분자로 사용하여 지정한다. 그리고 WHERE, GROUP BY, ORDER BY절 등 다른 절도 그대로 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">SELECT
FROM 테이블1, 테이블2, ..., 테이블N</code></pre>
<ul>
<li>FROM절에 여러 테이블 선언하기</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP, DEPT
ORDER BY EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/1e803564-7ead-451e-8022-67650e091ab2/image.png" alt=""></p>
<p>이렇게 EMP, DEPT 테이블을 FROM절에 함께 명시하여 출력하면 생각보다 많은 양의 데이터가 FROM절에 명시학 각 테이블을 구성하는 행이 모든 경우의 수로 조합되어 출력되기 때문이다.</p>
<p>위 이미지와 같이 각 집합을 이루는 모든 원소의 순서쌍을 데카르트 곱이라고 한다. 조인 이름으로는 크로스 조인 또는 교차 조인이라고도 한다.</p>
<blockquote>
<p>조인 조건이 없을 때의 문제점</p>
</blockquote>
<ul>
<li><p>EMP 테이블 SMITH 사원이 있는 행을 보면 DEPTNO가 20이고 DEPT 테이블의 DEPTNO 열 값이 20인 행이 된다. 하지만 조건 없이 결과를 출력하면 사원 데이터와 부서 데이터가 정확히 맞아떨어지지 않는 데이터도 함께 출력된다.</p>
</li>
<li><p>그러므로 출력 행을 선정하는 조건식을 명시하는 WHERE절이 중요한 역할을 한다. 따라서 서로 다른 테이블인 EMP 테이블과 DEPT 테이블에 같은 이름의 DEPTNO 열을 구별하는 방법이 필요하다.</p>
</li>
<li><p>이 때 사용하는 것이 바로 열 앞에 테이블 이름을 명시하여 특정 열이 어느 테이블에 속한 열인지를 구별하는 방식이다.</p>
</li>
</ul>
<aside>
🍟 테이블 이름.열 이름

</aside>

<hr>
<pre><code class="language-sql">SELECT *
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
ORDER BY EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/83e73aab-cd34-4049-bedb-de9ef158b8d2/image.png" alt=""></p>
<p>FROM절에 WHERE절을 사용해 출력하려는 조건을 걸어 두 테이블의 DEPTNO 열 값이 같은 14개 행만 출력된다. 그리고 각 행별 부서 정보도 정확하게 연결되었음을 확인할 수 있다.</p>
<blockquote>
<p>테이블 별칭 설정</p>
</blockquote>
<ul>
<li>FROM절에 지정한 테이블에는 SELECT절의 열에 사용한 것처럼 별칭을 지정할 수 있다.</li>
</ul>
<pre><code class="language-sql">FROM 테이블 이름1 별칭1, 테이블 이름2 별칭2 ...</code></pre>
<p>지정한 별칭은 테이블의 열을 지칭하는 데 사용할 수 있다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
ORDER BY EMPNO;</code></pre>
<hr>
<h2 id="08---2-조인-종류">08 - 2 조인 종류</h2>
<ul>
<li>두 개 이상의 테이블을 하나의 테이블처럼 가로로 늘어뜨려 출력하기 위해 사용하는 조인은 대상 데이터를 어떻게 연결하느냐에 따라 등가 조인, 비등가 조인, 자체 조인, 외부 조인 등으로 구분한다.</li>
</ul>
<blockquote>
<p>등가 조인</p>
</blockquote>
<ul>
<li><p>등가 조인은 테이블을 연결한 후에 출력 행을 각 테이블의 특정 열에 일치한 데이터를 기준으로 선정하는 방식이다. 등가 조인은 내부 조인 또는 단순 조인으로 부르기도 한다.</p>
</li>
<li><p>등가 조인은 일반적으로 가장 많이 사용되는 조인 방식이다.</p>
</li>
<li><p>여러 테이블의 열 이름이 같을 때 유의점</p>
</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, DEPTNO, DNAME, LOC
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/9ce06134-3945-463c-8bd3-86b81c3b01eb/image.png" alt=""></p>
<p>DEPTNO처럼 등가 조인을 사용할 때 조인 조건이 되는 각 테이블의 열 이름이 같을 경우에 해당 열 이름을 테이블 구분 없이 명시하면 오류가 발생하여 실행되지 못합니다.</p>
<ul>
<li>열 이름에 각각의 테이블 이름도 함께 명시할 때</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME, D.LOC // D.DEPTNO -&gt; E.DEPTNO 가능
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
ORDER BY D.DEPTNO, E.EMPNO;</code></pre>
<ul>
<li>조인 테이블 개수와 조건식 개수의 관계</li>
</ul>
<p>기본적으로 데카르트 곱 현상이 일어나지 않게 하는 데 필요한 조건식의 최소 개수는 조인 테이블 개수에서 하나를 뺀 값이다.</p>
<blockquote>
<p>비등가 조인</p>
</blockquote>
<p>사원 정보와 더불어 사원의 급여 등급 정보를 함께 출력하고자 한다면 EMP 테이블과 SALGRADE 테이블을 조인해야 한다. 하지만 사용하는 열의 일치 여부를 기준으로 테이블을 조인하는 등가 조인 방식은 이 두 테이블의 연결에 적합하지 않다. 왜냐하면 급여 등급을 맞춰 주려면 사원의 급여 금액이 일치하는 것이 아니라 최소 급여(LOSAL)와 최대 급여(HISAL) 사이에 있어야 하기 때문이다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP E, SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/b26a07a1-e447-4140-bc98-ffdd08b08d3d/image.png" alt=""></p>
<ul>
<li>비등가 조인 방식은 등가 조인 방식에 비해 그리 자주 사용하는 방식은 아니다.</li>
</ul>
<hr>
<blockquote>
<p>자체 조인</p>
</blockquote>
<ul>
<li><p>자체 조인은 하나의 테이블을 여러 개의 테이블처럼 활용하여 조인하는 방식이고 FROM절에 같은 테이블을 여러 번 명시하되 테이블의 별칭만 다르게 지정하는 방식으로 사용한다.</p>
</li>
<li><p>EMP테이블을 자체 조인을 사용하여 E1.MGR = E2.EMPNO를 나란히 출력한다. 하나의 테이블 이지만 SELECT문 내부에서 별칭을 각각 달리주어 논리적으로 다른 테이블인 것처럼 명시하여 두 테이블을 조인하는 방식이다.</p>
</li>
</ul>
<pre><code class="language-sql">SELECT E1.EMPNO, E1.ENAME, E1.MGR,
E2.EMPNO AS MGR_EMPNO,
E2.ENAME AS MGR_ENAME
FROM EMP E1, EMP E2
WHERE E1.MGR = E2.EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/fb68f181-644c-4778-8a8e-4fb8c1f5e70e/image.png" alt=""></p>
<blockquote>
<p>외부 조인 설명좀</p>
</blockquote>
<ul>
<li>조인 조건 데이터 중 어느 한쪽이 NULL임에도 결과를 출력할 때 포함시켜야 하는 경우가 종종 있다. 두 테이블ㄱ간 조인 수행에서 조인 기준 열의 어느 한쪽이 NULL이어도 강제로 출력하는 방식을 외부 조인이라고 한다.</li>
<li>외부 조인은 좌우를 따로 나누어 지정하는데 WHERE절에 조인 기준 열 중 한쪽에(+) 기호를 붙여 준다.</li>
</ul>
<table>
<thead>
<tr>
<th>왼쪽 외부 조인(Left Outer Join)</th>
<th>WHERE TABLE1.COL1 = TABLE2.COL1(+)</th>
</tr>
</thead>
<tbody><tr>
<td>오른쪽 외부 조인(Right Outer Join)</td>
<td>WHERE TABLE1.CON1(+) = TABLE2.COL1</td>
</tr>
</tbody></table>
<ul>
<li>왼쪽 외부 조인 사용하기</li>
</ul>
<pre><code class="language-sql">SELECT E1.EMPNO, E1.ENAME, E1.MGR,
E2.EMPNO AS MGR_EMPNO,
E2.ENAME AS MGR_ENAME
FROM EMP E1, EMP E2
WHERE E1.MGR = E2.EMPNO(+)
ORDER BY E1.EMPNO;</code></pre>
<ul>
<li>오른쪽 외부 조인 사용하기</li>
</ul>
<pre><code class="language-sql">SELECT E1.EMPNO, E1.ENAME, E1.MGR,
E2.EMPNO AS MGR_EMPNO,
E2.ENAME AS MGR_ENAME
FROM EMP E1, EMP E2
WHERE E1.MGR(+) = E2.EMPNO
ORDER BY E1.EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/d98b9baa-910b-4de1-ab6d-e33b9acfe9b4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/046faa23-e78b-42f7-a8b3-c2aae78e288e/image.png" alt=""></p>
<ul>
<li>왼쪽 외부 조인은 간단히 말해서 왼쪽 열을 기준으로 오른쪽 열의 데이터 존재 여부에 상관없이 출력하라는 뜻이다.</li>
<li>오른쪽 외부 조인은 오른쪽 열을 기준으로 왼쪽 열 데이터의 존재와 상관없이 데이터를 출력하라는 뜻이다.</li>
</ul>
<hr>
<h2 id="08---3-sql-99-표준-문법으로-배우는-조인">08 - 3 SQL-99 표준 문법으로 배우는 조인</h2>
<ul>
<li>오라클은 9i 버전부터 SQL-99 방식의 문법을 지원한다.</li>
<li>앞에서 배운 조인 방식과 기능은 같지만 조인을 사용하는 문법에서 다소 차이가 난다. 그리고 다른 DBMS 제품에서도 사용할 수 있다.</li>
</ul>
<blockquote>
<p>NATURAL JOIN</p>
</blockquote>
<ul>
<li>등가 조인을 대신해 사용할 수 있는 조인 방식으로 조인 대상이 되는 두 테이블에 이름과 자료형이 같은 열을 찾은 후 그 열을 기준으로 등가 조인을 해 주는 방식이다.</li>
<li>EMP 테이블과 DEPT 테이블은 공통 열 DEPTNO를 가지고 있으므로 NATURAL JOIN을 사용할 때 <strong>자동으로</strong> DEPTNO 열을 기준으로 등가 조인된다.</li>
<li>기존 등가 조인과 다르게 조인 기준 열인 DEPTNO를 SELECT절에 명시할 때 테이블 이름을 붙이면 안 되는 특성이 있다.</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, E.JOB, E.MGR, E.HIREDATE, E.SAL, E.COMM,
DEPTNO, D.DNAME, D.LOC
FROM EMP E NATURAL JOIN DEPT D
ORDER BY DEPTNO, E.EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/c231a1a2-5e39-42c7-9496-754e63122371/image.png" alt=""></p>
<blockquote>
<p>JOIN ~ USING</p>
</blockquote>
<ul>
<li>이 조인 역시 등가 조인을 대신하는 방식이다. USING 키워드에 조인 기준으로 사용할 열을 명시하여 사용한다.</li>
</ul>
<pre><code class="language-sql">FROM TABLE1 JOIN TABLE2 USING (조인에 사용한 기준열)</code></pre>
<ul>
<li>다른 조인 방식과 마찬가지로 조인된 결과 행을 추가로 제한할 때 WHERE절에 조건식을 추가하여 함께 사용할 수 있다.</li>
<li>조인 기준 열로 명시된 열은 SELECT절에서 테이블 이름을 붙이지 않고 작성한다.</li>
</ul>
<blockquote>
<p>JOIN ~ ON</p>
</blockquote>
<ul>
<li>가장 범용성 있는 조인 방식이다.</li>
<li>기존 WHERE절에 있는 조인 조건식을 ON 키워드 옆에 작성한다.</li>
<li>조인 기준 조건식은 ON에 명시하고 그 밖의 출력행을 걸러 내기 위해 WHERE 조건식을 따로 사용하는 방식이다.</li>
</ul>
<pre><code class="language-sql">SELECT E.EMPNO, E.ENAME, E.JOB, E.MGR, E.HIREDATE, E.SAL, E.COMM,
E.DEPTNO, 
D.DNAME, D.LOC
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO)
WHERE SAL &lt;= 3000
ORDER BY E.DEPTNO, EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/10abc3c7-92da-4cc3-8f5c-b3503eb2c859/image.png" alt=""></p>
<blockquote>
<p>OUTER JOIN</p>
</blockquote>
<ul>
<li>OUTER JOIN 키워드는 외부 조인에 사용한다.</li>
</ul>
<table>
<thead>
<tr>
<th>왼쪽 외부 조인 (Left Outer Join)</th>
<th>기존</th>
<th>WHERE TABLE1.COL1 = TABLE2.COL1(+)</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 LEFT OUTER JOIN TABLE2 ON (조인 조건식)</td>
</tr>
<tr>
<td>오른쪽 외부 조인 (Right Outer Join)</td>
<td>기존</td>
<td>WHERE TABLE1.COL1(+) = TABLE2.COL1</td>
</tr>
<tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 RIGHT OUTER JOIN TABLE2.ON (조인 조건식)</td>
</tr>
<tr>
<td>전체 외부 조인 (Full Outer Join)</td>
<td>기존</td>
<td>기본 문법은 없음 (UNION 집합 연산자를 활용)</td>
</tr>
<tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 FULL OUTER JOIN TABLE2 ON (조인 조건식)</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT E1.EMPNO, E1.ENAME, E1.MGR,
E2.EMPNO AS MGR_EMPNO,
E2.ENAME AS MGR_ENAME
FROM EMP E1 LEFT OUTER JOIN EMP E2 ON (E1.MGR = E2.EMPNO)
ORDER BY E1.EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/c6221a3b-617b-42f2-a059-68b668bc3961/image.png" alt=""></p>
<ul>
<li>전체 외부 조인은 왼쪽 · 오른쪽 외부 조인을 모두 적용한, 즉 왼쪽 열이 NULL인 경우와 오른쪽 열이 NULL인 경우를 모두 출력하는 방식이다.</li>
<li>SQL-99 방식의 외부 조인은 FULL OUTER JOIN ~ ON 키워드로 양쪽 모두 외부 조인된 결과 값을 출력할 수 있다.</li>
</ul>
<pre><code class="language-sql">SELECT E1.EMPNO, E1.ENAME, E1.MGR,
E2.EMPNO AS MGR_EMPNO,
E2.ENAME AS MGR_ENAME
FROM EMP E1 FULL OUTER JOIN EMP E2 ON (E1.MGR = E2.EMPNO)
ORDER BY E1.EMPNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e4f08ed1-409e-43cd-a6b5-7981c5dd95b9/image.png" alt=""></p>
<ul>
<li>SQL-99 조인은 FROM절에 특정 키워드를 사용함으로써 기존 WHERE절에 조건식으로 조인하는 조인 방식보다 더 간략하고 명시적으로 어떤 방식의 조인을 사용하고 있는지 알 수 있다.</li>
<li>조인 조건식과 출력 행을 선정하는 조건식을 구별할 수 있으므로 여러 테이블을 조인해야 하는 복잡한 SELECT문에서 SQL-99 조인의 장점이 드러난다.</li>
</ul>
<blockquote>
<p>SQL-99 조인 방식에서 세 개 이상의 테이블을 조인할 때</p>
</blockquote>
<p>기존 조인 방식은 FROM절에 조인 테이블을 명시하고 조인 관련 조건식을 WHERE절에 명시하기 때문에 테이블 수가 두 개를 넘더라도 다음과 같이 작성하면 아무 문제가 없다</p>
<pre><code class="language-sql">FROM TABLE1, TABLE2 TABLE3
WHERE TABLE1.COL = TABLE2.COL
AND TABLE2.COL = TABLE3.COM</code></pre>
<p>하지만 FROM절에 조인 관련 내용을 작성해야 하는 SQL-99 방식에서는 FROM절에 두 개 테이블을 키워드로 조인한 바로 옆에 SQL-99 방식의 조인 내용을 추가로 작성하면 세 개 이상의 테이블도 조인할 수 있다.</p>
<pre><code class="language-sql">FROM TABLE1 JOIN TABLE2 ON (조인 조건식)
JOIN TABLE3 ON (조건식)</code></pre>
<h2 id="잊기-전에-한-번-더">잊기 전에 한 번 더!</h2>
<ul>
<li>Q1. 급여(SAL)가 2000 초과인 사원들의 부서 정보, 사원 정보를 오른쪽과 같이 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND SAL &gt; 2000;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.SAL
FROM EMP E JOIN DEPT D USING (DEPTNO)
WHERE SAL &gt; 2000;</code></pre>
<ul>
<li>Q2. 오른쪽과 같이 각 부서별 평균 급여, 최대 급여, 최소 급여, 사원수를 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME,
TRUNC(AVG(E.SAL)) AS AVG_SAL,
MAX(E.SAL) AS MAX_SAL,
MIN(E.SAL) AS MIN_SAL,
COUNT(*) AS CNT
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
GROUP BY D.DEPTNO, D.DNAME;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT DEPTNO, D.DNAME, TRUNC(AVG(E.SAL)) AS AVG_SAL,
MAX(E.SAL) AS MAX_SAL,
MIN(E.SAL) AS MIN_SAL,
COUNT(*) AS CNT
FROM EMP E JOIN DEPT D USING (DEPTNO)
GROUP BY DEPTNO, D.DNAME;</code></pre>
<ul>
<li>Q3. 모든 부서 정보와 사원 정보를 오른쪽과 같이 부서 번호, 사원 이름순으로 정렬하여 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.JOB, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
ORDER BY D.DEPTNO, E.ENAME; </code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.JOB, E.SAL
FROM EMP E RIGHT OUTER JOIN DEPT D ON (D.DEPTNO = E.DEPTNO)
ORDER BY DEPTNO, E.ENAME;

// DEPTNO, D.DEPTNO ㅠㅠ ?</code></pre>
<ul>
<li>Q4. 다음과 같이 모든 부서 정보, 사원 정보, 급여 등급 정보, 각 사원의 직속 상관의 정보를 부서 번호, 사원 번호 순서로 정렬하여 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME,
       E.EMPNO, E.ENAME, E.MGR, E.SAL, E.DEPTNO,
       S.LOSAL, S.HISAL, S.GRADE,
       E2.EMPNO AS MGR_EMPNO, E2.ENAME AS MGR_ENAME
  FROM EMP E, DEPT D, SALGRADE S, EMP E2
 WHERE E.DEPTNO(+) = D.DEPTNO
   AND E.SAL BETWEEN S.LOSAL(+) AND S.HISAL(+)
   AND E.MGR = E2.EMPNO(+)
ORDER BY D.DEPTNO, E.EMPNO;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT D.DEPTNO, D.DNAME,
       E.EMPNO, E.ENAME, E.MGR, E.SAL, E.DEPTNO,
       S.LOSAL, S.HISAL, S.GRADE,
       E2.EMPNO AS MGR_EMPNO, E2.ENAME AS MGR_ENAME
  FROM EMP E RIGHT OUTER JOIN DEPT D
                ON (E.DEPTNO = D.DEPTNO)
              LEFT OUTER JOIN SALGRADE S
                ON (E.SAL BETWEEN S.LOSAL AND S.HISAL)
              LEFT OUTER JOIN EMP E2
                ON (E.MGR = E2.EMPNO)
ORDER BY D.DEPTNO, E.EMPNO;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day12]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day12</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day12</guid>
            <pubDate>Mon, 05 Dec 2022 18:12:04 GMT</pubDate>
            <description><![CDATA[<h2 id="08---3-sql-99-표준-문법으로-배우는-조인">08 - 3 SQL-99 표준 문법으로 배우는 조인</h2>
<blockquote>
<p>NATURAL JOIN</p>
</blockquote>
<ul>
<li>NATURAL JOIN은 등가 조인을 대신해 사용할 수 있는 조인 방식으로 조인대상이 되는 두 테이블에 이름과 자료형이 같은 열을 찾은 후 그열을 기준으로 등가 조인을 해 주는 방식이다.</li>
</ul>
<blockquote>
<p>JOIN ~ USING</p>
</blockquote>
<p>JOIN ~ USING 키워드를 사용한 조인 역시 기존 등가 조인을 대신하는 조인 방식이다. </p>
<pre><code class="language-sql">FROM TABLE1 JOIN TABLE2 USING (조인에 사용한 기준열)</code></pre>
<p>다른 조인 방식과 마찬가지로 조인된 결과 행을 추가로 제한할 때 WHERE절에 조건식을 추가하여 함께 사용할 수 있다.</p>
<blockquote>
<p>JOIN ~ ON</p>
</blockquote>
<p>가장 범용성 있는 JOIN ~ ON 키워드를 사용한 조인 방식에서는 기존 WHERE절에 있는 조인 조건식을 ON 키워드 옆에 작성한다. 조인 기준 조건식은 ON에 명시하고 그 밖의 출력 행을 걸러 내기 위해 WHERE 조건식을 따로 사용하는 방식이다.</p>
<pre><code class="language-sql">FROM TABLE JOIN TABLE2 ON (조인 조건식)</code></pre>
<blockquote>
<p>OUTER JOIN</p>
</blockquote>
<p>OUTER JOIN 키워드는 외부 조인에 사용한다. WHERE절이 아닌 FROM절에서 외부 조인을 선언한다.</p>
<table>
<thead>
<tr>
<th>왼쪽 외부 조인 (Left Outer Join)</th>
<th>기존</th>
<th>WHERE TABLE1.COL1 = TABLE2.COL1(+)</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 LEFT OUTER JOIN TABLE2 ON (조인 조건식)</td>
</tr>
<tr>
<td>오른쪽 외부 조인 (Right Outer Join)</td>
<td>기존</td>
<td>WHERE TABLE1.COL1(+) = TABLE2.COL1</td>
</tr>
<tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 RIGHT OUTER JOIN TABLE2.ON (조인 조건식)</td>
</tr>
<tr>
<td>전체 외부 조인 (Full Outer Join)</td>
<td>기존</td>
<td>기본 문법은 없음 (UNION 집합 연산자를 활용)</td>
</tr>
<tr>
<td></td>
<td>SQL-99</td>
<td>FROM TABLE1 FULL OUTER JOIN TABLE2 ON (조인 조건식)</td>
</tr>
</tbody></table>
<blockquote>
<p>SQL-99 조인 방식에서 세 개 이상의 테이블을 조인할 때</p>
</blockquote>
<p>기존 조인 방식은 FROM절에 조인 테이블을 명시하고 조인 관련 조건식을 WHERE절에 명시하기 때문에 테이블 수가 두 개를 넘더라도 다음과 같이 작성하면 아무 문제가 없다</p>
<pre><code class="language-sql">FROM TABLE1, TABLE2 TABLE3
WHERE TABLE1.COL = TABLE2.COL
ABD TABLE2.COL = TABLE3.COM</code></pre>
<p>하지만 FROM절에 조인 관련 내용을 작성해야 하는 SQL-99 방식에서는 FROM절에 두 개 테이블을 키워드로 조인한 바로 옆에 SQL-99 방식의 조인 내용을 추가로 작성하면 세 개 이상의 테이블도 조인할 수 있다.</p>
<pre><code class="language-sql">FROM TABLE1 JOIN TABLE2 ON (조인 조건식)
JOIN TABLE3 ON (조건식)</code></pre>
<h2 id="잊기-전에-한-번-더">잊기 전에 한 번 더!</h2>
<ul>
<li>Q1. 급여(SAL)가 2000 초과인 사원들의 부서 정보, 사원 정보를 오른쪽과 같이 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND SAL &gt; 2000;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.SAL
FROM EMP E JOIN DEPT D USING (DEPTNO)
WHERE SAL &gt; 2000;</code></pre>
<ul>
<li>Q2. 오른쪽과 같이 각 부서별 평균 급여, 최대 급여, 최소 급여, 사원수를 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME,
TRUNC(AVG(E.SAL)) AS AVG_SAL,
MAX(E.SAL) AS MAX_SAL,
MIN(E.SAL) AS MIN_SAL,
COUNT(*) AS CNT
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
GROUP BY D.DEPTNO, D.DNAME;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT DEPTNO, D.DNAME, TRUNC(AVG(E.SAL)) AS AVG_SAL,
MAX(E.SAL) AS MAX_SAL,
MIN(E.SAL) AS MIN_SAL,
COUNT(*) AS CNT
FROM EMP E JOIN DEPT D USING (DEPTNO)
GROUP BY DEPTNO, D.DNAME;</code></pre>
<ul>
<li>Q3. 모든 부서 정보와 사원 정보를 오른쪽과 같이 부서 번호, 사원 이름순으로 정렬하여 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.JOB, E.SAL
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
ORDER BY D.DEPTNO, E.ENAME;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT D.DEPTNO, D.DNAME, E.EMPNO, E.ENAME, E.JOB, E.SAL
FROM EMP E RIGHT OUTER JOIN DEPT D ON (D.DEPTNO = E.DEPTNO)
ORDER BY DEPTNO, E.ENAME;

// DEPTNO, D.DEPTNO ㅠㅠ ?</code></pre>
<ul>
<li>Q4. 다음과 같이 모든 부서 정보, 사원 정보, 급여 등급 정보, 각 사원의 직속 상관의 정보를 부서 번호, 사원 번호 순서로 정렬하여 출력해 보세요. (단 SQL-99 이전 방식과 SQL-99 방식을 각각 사용하여 작성하세요.)</li>
</ul>
<pre><code class="language-sql">// SQL-99 이전 방식
SELECT D.DEPTNO, D.DNAME,
       E.EMPNO, E.ENAME, E.MGR, E.SAL, E.DEPTNO,
       S.LOSAL, S.HISAL, S.GRADE,
       E2.EMPNO AS MGR_EMPNO, E2.ENAME AS MGR_ENAME
  FROM EMP E, DEPT D, SALGRADE S, EMP E2
 WHERE E.DEPTNO(+) = D.DEPTNO
   AND E.SAL BETWEEN S.LOSAL(+) AND S.HISAL(+)
   AND E.MGR = E2.EMPNO(+)
ORDER BY D.DEPTNO, E.EMPNO;</code></pre>
<pre><code class="language-sql">// SQL-99 방식
SELECT D.DEPTNO, D.DNAME,
       E.EMPNO, E.ENAME, E.MGR, E.SAL, E.DEPTNO,
       S.LOSAL, S.HISAL, S.GRADE,
       E2.EMPNO AS MGR_EMPNO, E2.ENAME AS MGR_ENAME
  FROM EMP E RIGHT OUTER JOIN DEPT D
                ON (E.DEPTNO = D.DEPTNO)
              LEFT OUTER JOIN SALGRADE S
                ON (E.SAL BETWEEN S.LOSAL AND S.HISAL)
              LEFT OUTER JOIN EMP E2
                ON (E.MGR = E2.EMPNO)
ORDER BY D.DEPTNO, E.EMPNO;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day11]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day11</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day11</guid>
            <pubDate>Mon, 05 Dec 2022 18:11:31 GMT</pubDate>
            <description><![CDATA[<h2 id="08---1-조인">08 - 1 조인</h2>
<blockquote>
<p>집합 연산자와 조인의 차이점</p>
</blockquote>
<ul>
<li>조인은 두 개 이상의 테이블을 연결하여 하나의 테이블처럼 출력할 때 사용하는 방식이다.</li>
<li>차이점은 집합 연산자를 사용한 결과는 두 개 이상 SELECT문의 결과 값을 세로로 연결한 것이고, 조인을 사용한 결과는 두 개 이상의 테이블 데이터를 가로로 연결한 것이라고 볼 수 있다.</li>
</ul>
<blockquote>
<p>여러 테이블을 사용할 때의 FROM절</p>
</blockquote>
<ul>
<li>지금까지 사용한 SELECT문은 다음과 같이 FROM절에 EMP 테이블을 하나만 명시했다. 하지만 FROM절에는 여러 개 테이블을 지정하는 것이 가능하다. 조금 더 정확하게는 꼭 테이블이 아니더라도 테이블 형태, 즉 열과 행으로 구성된 데이터 집합이면 모두 FROM절에 지정 가능하다.</li>
</ul>
<pre><code class="language-sql">SELECT 열1, 열2, ..., 열N
FROM EMP
WHERE 조건식
GROUP BY 그룹식
HAVING 그룹조건식
ORDER BY 정렬식</code></pre>
<ul>
<li>SELECT절의 여러 열을 구분할 때와 마찬가지로 FROM절에 여러 테이블을 명시할 때 쉼표를 구분자로 사용하여 지정한다. 그리고 WHERE, GROUP BY, ORDER BY절 등 다른 절도 그대로 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">SELECT
FROM 테이블1, 테이블2, ..., 테이블N</code></pre>
<blockquote>
<p>조인 조건이 없을 때의 문제점</p>
</blockquote>
<ul>
<li>조인을 통한 출력은 결과로 나올 수 있는 모든 행을 조합하기 때문에 정확히 맞아떨어지지 않는 데이터도 함께 출력된다. 명시한 테이블의 데이터를 가로로 연결하기 위해 조인을 사용하지만, 어떤 데이터를 가로로 정확히 연결해야 하는지의 기준은 데이터베이스가 아닌 SQL문을 작성하는 프로그래머가 정해 주어야한다. 이때 출력 행을 선정하는 조건식을 명시하는 WHERE절이 중요한 역을을 한다. 따라서 서로 다른 테이블에서 같은 이름의 열을 구별하는 방법은 열 앞에 테이블 이름을 명시하여 특정 열이 어느 테이블에 속한 열인지를 구별하는 방식이다.</li>
</ul>
<aside>
⭐ 테이블 이름.열 이름

</aside>

<blockquote>
<p>테이블의 별칭 설정</p>
</blockquote>
<ul>
<li>FROM절에 지정한 테이블에는 SELECT절의 열에 사용한 것처럼 별칭을 지정할 수 있다. 테이블에 병칠을 지정할 때는 명시한 테이블 이름에서 한 칸 띄운 후에 지정한다.</li>
</ul>
<pre><code class="language-sql">FROM 테이블 이름1 별칭1, 테이블 이름2 별칭 2 ...</code></pre>
<h2 id="08---2-조인-종류">08 - 2 조인 종류</h2>
<ul>
<li>두 개 이상의 테이블을 하나의 테이블처럼 가로로 늘어뜨려 출력하기 위해 사용하는 조인은 대상 데이터를 어떻게 연결하느냐에 따라 등가 조인, 비등가 조인, 자체 조인, 외부 조인 등으로 구분한다.</li>
</ul>
<blockquote>
<p>등가 조인</p>
</blockquote>
<ul>
<li><p>등가 조인(equi join)은 테이블을 연결한 후에 출력 행을 각 테이블의 특정 열에 일치한 데이터를 기준으로 선정하는 방식이다. 등가 조인은 내부 조인(inner join) 또는 단순 조인(simple join)으로 부르기도 한다.</p>
<p>  등가 조인은 일반적으로 가장 많이 사용되는 조인 방식이다. 따라서 외부 조인(outer join)과 같이 이름을 특별히 명시하지 않으면 ‘조인을 사용한다’는 것은 대부분 등가 조인, 즉 특정 열 값이 일치한 출력 결과를 사용하는 방식이라고 보면 된다.</p>
</li>
</ul>
<blockquote>
<p>비등가 조인</p>
</blockquote>
<ul>
<li>비등가 조인(non-equi join)은 등가 조인 방식 외의 방식을 의미한다. 비등가 조인 방식은 등가 조인 방식에 비해 그리 자주 사용하는 방식은 아니다. 하지만 조인 조건이 특정 열의 일치 여부를 검사하는 방식 외에 다른 방식도 사용할 수 있음을 기억해라.</li>
</ul>
<blockquote>
<p>자체 조인</p>
</blockquote>
<ul>
<li>자체 조인(self join)은 하나의 테이블을 여러 개의 테이블처럼 활용하여 조인하는 방시긍로 앞에서 물리적으로 동일한 테이블 여러 개를 사용할 때 발생할 수 있는 문제점을 해결한다. 자체 조인은 FROM절에 같은 테이블을 여러 번 명시하되 테이블의 별칭만 다르게 지정하는 방식으로 사용한다.</li>
</ul>
<blockquote>
<p>외부 조인</p>
</blockquote>
<ul>
<li><p>두 테이블간 조인 수행에서 조인 기준 열의 어느 한쪽이 NULL이어도 강제로 출력하는 방식을 외부 조인(outer join)이라고 한다.</p>
<p>  외부 조인은 좌우를 따로 나누어 지정하는데 WHERE절에 조인 기준 열 중 한쪽에(+) 기호를 붙여 준다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>왼쪽 외부 조인(Left Outer Join)</th>
<th>WHERE TABLE1.COL1 = TABLE2.COL1(+)</th>
</tr>
</thead>
<tbody><tr>
<td>오른쪽 외부 조인(Right Outer Join)</td>
<td>WHERE TABLE1.CON1(+) = TABLE2.COL1</td>
</tr>
</tbody></table>
<ul>
<li>외부 조인은 조인 기준 열의 NULL을 처리하는 것을 목적으로 자주 사용하는 조인 방식이다. 하지만 (+) 기호를 붙이는 외부 조인 방식으로는 양쪽 모든 열이 외부 조인되는 ‘전체 외부 조인(full outer join)’ 사용은 불가능하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day10]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day10</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day10</guid>
            <pubDate>Mon, 05 Dec 2022 18:10:54 GMT</pubDate>
            <description><![CDATA[<h2 id="07---4-그룹화와-관련된-여러-함수">07 - 4 그룹화와 관련된 여러 함수</h2>
<blockquote>
<p>ROLLUP, CUBE, GROUPING SETS 함수</p>
</blockquote>
<p>ROLLUP, CUBE, GROUPING SETS 함수는 GROUP BY절에 지정할 수 있는 특수 함수이다. ROLLUP함수와 CUBE함수는 그룹화 데이터의 합계를 출력할 때 유용하게 사용할 수 있다.</p>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식]
GROUP BY ROLLUP [그룹화 열 지정(여러 개 지정 가능)]; // 1.</code></pre>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식]
GROUP BY CUBE [그룹화 열 지정(여러 개 지정 가능)]; // 2.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1, 2</td>
<td>ROLLUP, CUBE</td>
<td>그룹화 열 지정</td>
<td>-</td>
<td>그룹화 데이터의 합계를 함께 출력하는 데 사용합니다.</td>
</tr>
</tbody></table>
<ul>
<li>GROUPING SETS 함수</li>
</ul>
<p>GROUPING SETS 함수는 같은 수준의 그룹화 열이 여러 개일 때 각 열별 그룹화를 통해 결과 값을 출력하는 데 사용한다.</p>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식]
GROUP BY GROUPING SETS [그룹화 열 지정(여러 개 지정 가능)]; // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>GROUPING SETS</td>
<td>그룹화 열</td>
<td>-</td>
<td>여러 그룹화 대상 열의 결과 값을 각각 같은 수준으로 출력합니다.</td>
</tr>
</tbody></table>
<blockquote>
<p>그룹화 함수</p>
</blockquote>
<p>그룹화 함수는 데이터 자체의 가공이나 특별한 연산 기능을 수행하지는 않지만 그룹화 데이터의 식별이 쉽고 가독성을 높이기 위한 목적으로 사용한다.</p>
<ul>
<li>GROUPING 함수</li>
</ul>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
GROUPING [GROUP BY절에 ROLLUP 또는 CUBE에 명시한 그룹화 할 열 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식]
GROUP BY ROLLUP 또는 CUBE [그룹화 열]; // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>GROUPING</td>
<td>그룹화 여부를 확인할 열</td>
<td>-</td>
<td>현재 결과가 그룹화 대상 열의 그룹화가 이루어진 상태의 집계인지 여부를 출력합니다.</td>
</tr>
</tbody></table>
<ul>
<li>GROUPING_ID 함수</li>
</ul>
<p>GROUPING_ID 함수는 GROUPING 함수와 마찬가지로 ROLLUP 또는 CUBE 함수로 연살할 때 특정 열이 그룹화되었는지를 출력하는 함수이다.</p>
<p>그룹화 여부를 검사할 열을 하나씩 지정하는 GROUPING 함수와 달리 GROUPING_ID 함수는 한 번에 여러 열을 지정할 수 있다.</p>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
GROUPING_ID [그룹화 여부를 확인할 열(여러 개 지정 가능)]
FROM [조회할 테이블 이름] WHERE [조회할 행을 선별하는 조건식]
GROUP BY ROLLUP 또는 CUBE [그룹화 할 열]; // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>GROUPING_ID</td>
<td>그룹화 여부를 확인할 열</td>
<td>-</td>
<td>GROUPING 함수처럼 특정 열의 그룹화 여부를 출력할 수 있으며, 검사할 열을 여러 개 지정할 수 있습니다.</td>
</tr>
</tbody></table>
<blockquote>
<p>LISTAGG 함수</p>
</blockquote>
<p>LISTAGG 함수는 오라클 11g 버전부터 사용할 수 있는 함수이다. 그룹에 속해 있는 데이터를 가로로 나열할 때 사용한다.</p>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
LISTAGG([나열할 열(필수)], [각 데이터를 구분하는 구분자(선택)])
WITHIN GROUP(ORDER BY 나열할 열의 정렬 기준 열 (선택)) // 1.
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식];</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>LISTAGG ~ WITHIN GROUP</td>
<td>나열할 열</td>
<td>각 데이터를 구분하는 구분자, 지정하지 않을 경우 NULL이 기본값이 됩니다.</td>
<td>그룹화 데이터를 하나의 열에 가로로 나열하여 출력하는 데 사용합니다.</td>
</tr>
</tbody></table>
<blockquote>
<p>PIVOT, UNPIVOT 함수</p>
</blockquote>
<p>PIVOT, UNPIVOT 함수는 오라클 11g부터 제공하면 PIVOT함수는 기존 테이블 행을 열로 바꾸고 UNPIVOT 함수는 기존 테이블 열을 행으로 바꿔서 출력한다.</p>
<pre><code class="language-sql">SELECT *
FROM(SELECT DEPTNO, JOB, SAL
FROM EMP)
PIVOT(MAX(SAL)
FOR DEPTNO IN (10, 20, 30)
)
ORDER BY JOB;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/5299ecb9-901a-47f0-8c5a-8e604ea8b568/image.png" alt=""></p>
<pre><code class="language-sql">SELECT *
FROM(SELECT DEPTNO,
MAX(DECPDE(JOB, &#39;CLERK&#39; , SAL)) AS &quot;CLERK&quot;,
MAX(DECODE(JOB, &#39;SALESMAN&#39;, SAL)) AS &quot;SALESMAN&quot;,
MAX(DECODE(JOB, &#39;PRESIDENT&#39;, SAL)) AS &quot;PRESIDENT&quot;,
MAX(DECODE(JOB, &#39;MNAGER&#39;, SAL)) AS &quot;MANAGER&quot;,
MAX(DECODE(JOB, &#39;ANALYST&#39;, SAL)) AS &quot;ANALYST&quot;
FROM EMP
GROUP BY DEPTNO
ORDER BY DEEPTNO)
UNPIVOT(
SAL FOR JOB IN (CLERK, SALESMAN, PRESIDENT, MANAGER, ANALYST))
ORDER BY DEPTNO, JOB;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e0a6cd42-cbba-41c9-9361-54470d4f9d70/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day9]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day9</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day9</guid>
            <pubDate>Mon, 05 Dec 2022 18:09:25 GMT</pubDate>
            <description><![CDATA[<h2 id="07---1-하나의-열에-출력-결과를-담는-다중행-함수">07 - 1 하나의 열에 출력 결과를 담는 다중행 함수</h2>
<ul>
<li>다중행 함수는 여러 행을 바탕으로 하나의 결과 값을 도출해내기 위해 사용하는 함수이다.</li>
</ul>
<pre><code class="language-sql">SELECT SAL
FROM EMP;</code></pre>
<pre><code class="language-sql">SELECT SUM(SAL)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/4502ccec-56bc-4f33-bf64-49a40871114e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/30eb8b53-54bc-4879-afcc-f82ababb6f9f/image.png" alt=""></p>
<p>SUM 함수는 SELECT문으로 조회된 행에 지정한 열 값을 모두 더한 값을 반환해 주는 함수이다.</p>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>SUM</td>
<td>지정한 데이터의 합 반환</td>
</tr>
<tr>
<td>COUNT</td>
<td>지정한 데이터의 개수 반환</td>
</tr>
<tr>
<td>MAX</td>
<td>지정한 데이터 중 최댓값 반환</td>
</tr>
<tr>
<td>MIN</td>
<td>지정한 데이터 중 최솟값 반환</td>
</tr>
<tr>
<td>AVG</td>
<td>지정한 데이터의 평균값 반환</td>
</tr>
</tbody></table>
<blockquote>
<p>합계를 구하는 SUM함수</p>
</blockquote>
<pre><code class="language-sql">SUM([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
    [합계를 구할 열이나 연산자, 함수를 사용한 데이터(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>합계를 구할 데이터를 지정합니다.</td>
</tr>
</tbody></table>
<hr>
<p>SUM함수를 분석하는 용도로 사용한다면 다음과 같이 함수를 작성한 후 OVER절을 사용할 수도 있다.</p>
<pre><code class="language-sql">SUM([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
    [합계를 구할 열이나 연산자, 함수를 사용한 데이터(필수)])
OVER(분석을 위한 여러 문법을 지정)(선택)</code></pre>
<blockquote>
<p>데이터 개수를 구해 주는 COUNT 함수</p>
</blockquote>
<ul>
<li>COUNT 함수는 데이터 개수를 출력하는 데 사용한다.</li>
</ul>
<pre><code class="language-sql">COUNT([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
      [개수를 구할 열이나 연산자, 함수를 사용한 데이터(필수)])
OVER(분석을 위한 여러 문법 지정)(선택) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>결과 행의 개수를 출렵합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT *
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/ad0e6eff-d6f1-4bed-8878-52ee3f093d33/image.png" alt=""></p>
<pre><code class="language-sql">SELECT COUNT(*)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/76eec372-7f25-4b77-9470-6c9e87ee2cb4/image.png" alt=""></p>
<blockquote>
<p>최댓값과 최솟값을 구하는 MAX, MIN 함수</p>
</blockquote>
<p>MAX 함수와 MIN 함수는 단어 의미 그대로 입력 데이터 중 최댓값과 최솟값을 반환하는 함수이다.</p>
<pre><code class="language-sql">MAX([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
    [최댓값을 구할 열이나 연산자, 함수를 사용한 데이터(필수)])
OVER(분석을 위한 여러 문법 지정)(선택) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>결과 행에서 최댓값을 출력합니다.</td>
</tr>
</tbody></table>
<hr>
<pre><code class="language-sql">MIN([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
        [최솟값을 구할 열이나 연산자, 함수를 사용한 데이터(필수)])
OVER(분석을 위한 여러 문법을 지정)(선택) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>결과 행에서 최솟값을 출력합니다.</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>평균 값을 구하는 AVG 함수</p>
</blockquote>
<p>AVG 함수는 입력 데이터의 평균 값을 구하는 함수이다.</p>
<pre><code class="language-sql">AVG([DISTINCT, ALL 중 하나를 선택하거나 아무 값도 지정하지 않음(선택)]
        [평균 값을 구할 열이나 연산자, 함수를 사용한 데이터(필수)])
OVER(분석을 위한 여러 문법을 지정)(선택) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>결과 행의 평균 값을 반환합니다.</td>
</tr>
</tbody></table>
<h2 id="07---2-결과-값을-원하는-열로-묶어-출력하는-group-by-절">07 - 2 결과 값을 원하는 열로 묶어 출력하는 GROUP BY 절</h2>
<blockquote>
<p>GROUP BY절의 기본 사용법</p>
</blockquote>
<p>SELECT문에서는 GROUP BY절을 작성하여 데이터를 그룹화할 수 있다.</p>
<pre><code class="language-sql">SELECT  [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM    [조회할 테이블 이름]
WHERE   [조회할 행을 선별하는 조건식]
GROUP BY[그룹화할 열을 지정(여러 개 지정 가능)] // 1.
ORDER BY[정렬하려는 열 지정]</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>GROUP BY</td>
<td>그룹화할 열 또는 데이터 지정</td>
<td>-</td>
<td>특정 열 또는 데이터를 기준으로 데이터를 그룹으로 묶습니다.</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>GROUP BY절을 사용할 때 유의점</p>
</blockquote>
<p>GROUP BY절을 사용하여 출력 데이터를 그룹화할 경우 유의해야 할 점이 있는데 바로 다중행 함수를 사용하지 않은 일반 열은 GROUP BY절에 명시하지 않으면 SELECT절에서 사용할 수 없다는 것이다.</p>
<pre><code class="language-sql">SELECT ENAME, DEPTNO, AVG(SAL)
FROM EMP
GROUP BY DEPTNO;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/40cdab9e-f8ca-4753-a44b-24993ccdfe2d/image.png" alt=""></p>
<hr>
<h2 id="07---3-group-by절에-조건을-줄-때-사용하는-having절">07 - 3 GROUP BY절에 조건을 줄 때 사용하는 HAVING절</h2>
<ul>
<li>HAVING절은 SELECT문에 GROUP BY절이 존재할 때만 사용할 수 있다. 그리고 GROUP BY절을 통해 그룹화된 결과 값의 범위를 제한하는 데 사용한다.</li>
</ul>
<blockquote>
<p>HAVING절의 기본 사용법</p>
</blockquote>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하는 조건식]
GROUP BY [그룹화할 열 지정(여러 개 지정 가능)]
HAVING[출력 그룹을 제한하는 조건식] // 1.
ORDER BY [정렬하려는 열 지정];</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>키워드</th>
<th>필수 요소</th>
<th>선택 요소</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>HAVING</td>
<td>조건식</td>
<td>-</td>
<td>GROUP BY절을 사용해 그룹화된 결과 중 출력 그룹을 선별하는 조건식을 지정합니다.</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<blockquote>
<p>HAVING절을 사용할 때 유의점</p>
</blockquote>
<p>조건식을 지정한다는 점에서 HVING절이 WHERE절과 비슷하다고 생각할 수도 있다. 하지만 WHERE절은 출력 대상 행을 제한하고, HAVING절은 그룹화된 대상을 출력에서 제한하므로 쓰임새는 전혀 다르다.</p>
<blockquote>
<p>WHERE절과 HAVING절의 차이점</p>
</blockquote>
<ul>
<li>WHERE절을 사용하지 않고 HAVING절만 사용한 경우</li>
<li>WHERE절과 HAVING절을 모두 사용한 경우</li>
</ul>
<pre><code class="language-sql">SELECT DEPTNO, JOB, AVG(SAL)
FROM EMP
GROUP BY DEPTNO, JOB
HAVING AVG(SAL) &gt;= 2000
ORDER BY DEPTNO, JOB;</code></pre>
<pre><code class="language-sql">SELECT DEPTNO, JOB, AVG(SAL)
FROM EMP
WHERE SAL &lt;= 3000
GROUP BY DEPTNO, JOB
HAVING AVG(SAL) &gt;= 2000
ORDER BY DEPTNO, JOB;
</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/23db6805-3a5d-4c0e-8734-e464c0c4f8cb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/be8d6c1f-1643-4d09-a665-d48fa2802cc1/image.png" alt=""></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day8]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day8</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day8</guid>
            <pubDate>Mon, 05 Dec 2022 18:07:52 GMT</pubDate>
            <description><![CDATA[<h2 id="06---4-날짜-데이터를-다루는-날짜-함수">06 - 4 날짜 데이터를 다루는 날짜 함수</h2>
<ul>
<li>오라클에서 날짜 데이터, 즉 DATE형 데이터는 다음과 같이 간단한 연산이 가능하다.</li>
</ul>
<table>
<thead>
<tr>
<th>연산</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>날짜 데이터 + 숫자</td>
<td>날짜 데이터보다 숫자만큼 일수 이후의 날짜</td>
</tr>
<tr>
<td>날짜 데이터 - 숫자</td>
<td>날짜 데이터보다 숫자만큼 일수 이전의 날짜</td>
</tr>
<tr>
<td>날짜 데이터 - 날짜 데이터</td>
<td>두 날짜 데이터 간의 일수 차이</td>
</tr>
<tr>
<td>날짜 데이터 + 날짜 데이터</td>
<td>연산 불가, 지원하지 않음</td>
</tr>
<tr>
<td>- 오라클에서 제공하는 날짜 함수 중 가장 대표 함수는 SYSDATE 함수이다.</td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT SYSDATE AS NOW,
SYSDATE-1 AS YESTERDAY,
SYSDATE+1 AS TOMORROW
FROM DUAL;</code></pre>
<p>1을 빼거나 더했을 때 결과 날짜가 하루 이전이나 이후 날짜로 출력된다.</p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/d1f90202-20f2-42cf-b0e6-a4e9042896f2/image.png" alt=""></p>
<blockquote>
<p>몇 개월 이후 날짜를 구하는 AD_MONTHS 함수</p>
</blockquote>
<ul>
<li>특정 날짜에 지정한 개월 수 이후 날짜 데이터를 반환하는 함수이다.</li>
</ul>
<pre><code class="language-sql">ADD_MONTHS([날짜 데이터(필수)], [더할 개월 수(정수)(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 날짜 데이터에 입력한 개월 수만큼의 이후 날짜를 출력합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT SYSDATE,
ADD_MONTHS(SYSDATE, 3)
FROM DUAL;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/a369680c-1521-4316-86d0-b5615c487e70/image.png" alt=""></p>
<ul>
<li>ADD_MONTHS 함수를 WHERE절에 사용하는 것도 가능하다.</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO,
ENAME, HIREDATE, SYSDATE
FROM EMP
WHERE ADD_MONTHS(HIREDATE, 486) &gt; SYSDATE;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/20c0ef81-4920-48f0-ade0-8261e2539c7f/image.png" alt=""></p>
<blockquote>
<p>두 날짜 간의 개월 수 차이를 구하는 MONTHS_BETWEEN 함수</p>
</blockquote>
<ul>
<li>두 개의 날짜 데이터를 입력하고 두 날짜 간의 개월 수 차이를 구하는 데 사용한다.</li>
</ul>
<pre><code class="language-sql">MONTHS_BETWEEN([날짜 데이터1(필수)], [날짜 데이터2(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>두 날짜 데이터 간의 날짜 차이를 개월 수로 계산하여 출력합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT EMPNO, ENAME, HIREDATE, SYSDATE,
MONTHS_BETWEEN(HIREDATE, SYSDATE) AS MONTHS1,
MONTHS_BETWEEN(SYSDATE, HIREDATE) AS MONTHS2,
TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE)) AS MONTHS3
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/373c5d6f-8466-437c-9162-12b20e71d75b/image.png" alt=""></p>
<p>MONTHS1, MONTHS2에서  알 수 있듯이 비교 날짜의 입력 위치에 따라 음수 또는 양수가 나올 수 있다. 개월 수 차이는 소수점 단위까지 결과가 나오므로 MONTHS3과 같이 TRUNC 함수를 조합하면 개월 수 차이를 정수로 출력할 수도 있다.</p>
<hr>
<blockquote>
<p>돌아오는 요일, 달의 마지막 날짜를 구하는 NEXT_DAY, LAST_DAY 함수</p>
</blockquote>
<ul>
<li>NEXT_DAY 함수는 날짜 데이터와 요일 문자열을 입력한다. 입력한 날짜 데이터에서 돌아오는 요일의 날짜를 반환한다.</li>
</ul>
<pre><code class="language-sql">NEXT_DAY([날짜 데이터(필수)], [요일 문자(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 날짜를 기준으로 돌아오는 요일의 날짜를 출력해 주는 함수입니다.</td>
</tr>
<tr>
<td>- LAST_DAY 함수는 하나의 날짜 데이터만을 입력 데이터로 사용하며 해당 날짜가 속한 달의 마지막 날짜를 반환해 주는 함수이다.</td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-sql">LAST_DAY([날짜 데이터(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 날짜가 속한 달의 마지막 날짜를 출력해 주는 함수이다.</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>날짜의 반올림, 버림을 하는 ROUND, TRUNC 함수</p>
</blockquote>
<ul>
<li>숫자 데이터를 반올림, 버림 처리에 사용한 ROUND, TRUNC 함수는 날짜 데이터를 입력 데이터로 사용할 수도 있다. 이때는 소수점 위치 정보를 입력하지 않고 반올림, 버림의 기준이 될 포맷(format) 값을 지정해 준다.</li>
</ul>
<table>
<thead>
<tr>
<th>입력 데이터 종류</th>
<th>사용 방식</th>
</tr>
</thead>
<tbody><tr>
<td>숫자 데이터</td>
<td>ROUND([숫자(필수)], [반올림 위치])</td>
</tr>
<tr>
<td></td>
<td>TRUNC([숫자(필수)], [버림 위치])</td>
</tr>
<tr>
<td>날짜 데이터</td>
<td>ROUND([날짜데이터(필수)], [반올림 기준 포맷])</td>
</tr>
<tr>
<td></td>
<td>TRUNC([날짜데이터(필수)], [버림 기준 포맷])</td>
</tr>
</tbody></table>
<p>⭐ 날짜 데이터 기준에 대해 조금 더 자세한 내용을 알고 싶다면 ISO 공식 웹사이트(iso.org/iso/home/standards/iso8601.htm)를 참조하세요.</p>
<hr>
<h2 id="06---5-자료형을-변환하는-형-변환-함수">06 - 5 자료형을 변환하는 형 변환 함수</h2>
<ul>
<li>‘자동 형 변환’ 이라고도 불리는 암시적 형 변환</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, EMPNO + &#39;500&#39;
FROM EMP
WHERE ENAME = &#39;SCOTT&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/ad399211-2e0c-4766-8f06-23d35eca7bb9/image.png" alt=""></p>
<ul>
<li>자료형을 직접 지정해 주는 방식인 명시적 형 변환</li>
</ul>
<table>
<thead>
<tr>
<th>종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>TO_CHAR</td>
<td>숫자 또는 날짜 데이터를 문자 데이터로 변환</td>
</tr>
<tr>
<td>TO_NUMBER</td>
<td>문자 데이터를 숫자 데이터로 변환</td>
</tr>
<tr>
<td>TO_DATE</td>
<td>문자 데이터를 날짜 데이터로 변환</td>
</tr>
</tbody></table>
<p>문자를 중심으로 숫자 또는 날짜 데이터의 변환이 가능하다.</p>
<hr>
<blockquote>
<p>날짜, 숫자 데이터를 문자 데이터로 변환하는 TO_CHAR 함수</p>
</blockquote>
<ul>
<li>TO_CHAR 함수는 날짜, 숫자 데이터를 문자 데이터로 변환해 주는 함수이다.</li>
</ul>
<pre><code class="language-sql">TO_CHAR([날짜 데이터(필수)], &#39;[출력되길 원하는 문자 형태(필수)]&#39;) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>날짜 데이터를 원하는 형태의 문자열로 출력합니다.</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>문자 데이터를 숫자 데이터로 변환하는 TO_NUMBER 함수</p>
</blockquote>
<pre><code class="language-sql">TO_NUMBER(&#39;[문자열 데이터(필수)]&#39;, &#39;[인식될 숫자형태(필수)]&#39;) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>문자열을 지정한 형태의 숫자로 인식하여 숫자 데이터로 변환합니다.</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>문자 데이터를 날짜 데이터로 변환하는 TO_DATE 함수</p>
</blockquote>
<pre><code class="language-sql">TO_DATE(&#39;[문자열 데이터(필수)]&#39;, &#39;[인식될 날짜형태(필수)]&#39;) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>문자열 데이터를 날짜형의 데이터로 변환합니다.</td>
</tr>
</tbody></table>
<hr>
<h2 id="06---6-null-처리-함수">06 - 6 NULL 처리 함수</h2>
<ul>
<li>04장과 05장에서 데이터가 NULL이면 산술 연산자나 비교 연산자가 예상한 대로 동작하지 않는 것을 확인할 수 있었다. 하지만 특정 열의 데이터가 NULL일 경우에 연산 수행을 위해 데이터를 NULL이 아닌 다른 값으로 대체해 주어야 할 때가 종종 발생한다. 이때 여기에서 배울 NVL 함수와 NVL2 함수를 유용하게 사용할 수 있다.</li>
</ul>
<blockquote>
<p>NVL 함수의 기본 사용법</p>
</blockquote>
<pre><code class="language-sql">NVL([NULL인지 여부를 검사할 데이터 또는 열(필수)],
    [앞의 데이터가 NULL일 경우 반환할 데이터](필수)) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>열 또는 데이터를 입력하여 해당 데이터가 NULL이 아닐 경우 데이터를 그대로 반환하고, NULL인 경우 지정한 데이터를 반환합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT EMPNO, ENAME, SAL, COMM, SAL+COMM,
NVL(COMM, 0),
SAL+NVL(COMM, 0)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e94bfe09-183b-447e-9fca-e2aad6cb46a3/image.png" alt=""></p>
<p>EMP 테이블의 급여 외 추가 수당을 의미하는 COMM 열 값이 NULL인 데이터를 0으로 대체하여 연산이 가능하다는 것을 확인할 수 있다. 이렇게 NVL 함수는 NULL 처리를 위해 자주 사용한다.</p>
<hr>
<blockquote>
<p>NVL2 함수의 기본 사용법</p>
</blockquote>
<ul>
<li>NVL2 함수는 NVL 함수와 비슷하지만 데이터가 NULL이 아닐 때 반환할 데이터를 추가로 지정해 줄 수 있다.</li>
</ul>
<pre><code class="language-sql">NVL2([NULL인지 여부를 검사할 데이터 또는 열(필수)],
     [앞 데이터가 NULL이 아닐 경우 반환할 데이터 또는 계산식(필수)],
     [앞 데이터가 NULL일 경우 반환할 데이터 또는 계산식(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>열 또는 데이터를 입력하여 해당 데이터가 NULL이 아닐 때와 NULL일 때 출력 데이터를 각각 지정합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT EMPNO, ENAME, COMM,
NVL2(COMM, &#39;O&#39;, &#39;X&#39;),
NVL2(COMM, SAL*12+COMM, SAL*12) AS ANNSAL
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/15b26b2a-7117-407c-867d-aa45c3f455e6/image.png" alt=""></p>
<p>NVL2 함수는 NVL함수와는 달리 NULL이 아닌 경우에 반환 데이터까지 지정할 수 있으므로 좀 더 다양한 용도로 활용 가능하다.</p>
<hr>
<h2 id="06---7-상황에-따라-다른-데이터를-반환하는-decode-함수와-case문">06 - 7 상황에 따라 다른 데이터를 반환하는 DECODE 함수와 CASE문</h2>
<ul>
<li>특정 열 값이나 데이터 값에 따라 어떤 데이터를 반환할지 정할 때는 DECODE 함수 또는 CASE문을 사용한다.</li>
</ul>
<blockquote>
<p>DECODE 함수</p>
</blockquote>
<ul>
<li>DECODE 함수는 기준이 되는 데이터를 먼저 지정한 후 해당 데이터 값에 따라 다른 결과 값을 내보내는 함수이다.</li>
</ul>
<pre><code class="language-sql">DECODE([검사 대상이 될 열 또는 데이터, 연산이나 함수의 결과],
       [조건1], [데이터가 조건1과 일치할 때 반환할 결과],
       [조건2], [데이터가 조건2와 일치할 때 반환할 결과],
       ...
       [조건n], [데이터가 조건n과 일치할 때 반환할 결과],
       [위 조건1~조건n과 일치한 경우가 없을 때 반환할 결과])</code></pre>
<hr>
<blockquote>
<p>CASE문</p>
</blockquote>
<ul>
<li>기준 데이터를 반드시 명시하고 그 값에 따라 반환 데이터를 정하는 DECODE 함수와 달리 CASE문은 각 조건에 사용하는 데이터가 서로 상관없어도 된다. 또 기준 데이터 값이 같은(=) 데이터 외에 다양한 조건을 사용할 수 있다.</li>
</ul>
<pre><code class="language-sql">CASE [검사 대상이 될 열 또는 데이터, 연산이나 함수의 결과(선택)]
WHEN [조건1] THEN [조건1의 결과 값이 true일 때, 반환할 결과]
WHEN [조건2] THEN [조건2의 결과 값이 true일 때, 반환할 결과]
...
WHEN [조건n] THEN [조건n의 결과 값이 true일 때, 반환할 결과]
ELSE [위 조건1~조건n과 일치하는 경우가 없을 때 반환할 결과]
END</code></pre>
<hr>
<h2 id="잊기-전에-한-번-더">잊기 전에 한 번 더!</h2>
<ul>
<li>Q1. EMPNO 열에는 EMP 테이블에서 사원 이름(ENAME)이 다섯 글자 이상이며 여섯 글자 미만인 사원 정보를 출력합니다. MASKING_EMPNO 열에는 사원 번호(EMPNO) 앞 두 자리 외 뒷자리를 * 기호로 출력합니다. 그리고 MASKING_ENAME 열에는 사원 이름의 첫 글자만 보여 주고 나머지 글자 수만큼 * 기호로 출력하세요.</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, RPAD(SUBSTR(EMPNO, 1, 2), 4, &#39;*&#39;) AS MASKING_EMPNO,
ENAME, RPAD(SUBSTR(ENAME, 1, 1), 5, &#39;*&#39;) AS MASKING_ENAME
FROM EMP
WHERE LENGTH(ENAME) &gt;= 5
AND LENGTH(ENAME) &lt; 6;</code></pre>
<ul>
<li>Q2. EMP 테이블에서 사원들의 월 평균 근무일 수는 21.5일입니다. 하루 근무 시간을 8시간으로 보았을 때 사원들의 하루 급여(DAY_PAY)와 시급(TIME_PAY)을 계산하여 결과를 출렵합니다. 단 하루 급여는 소수점 세 번째 자리에서 버리고, 시급은 두 번째 소수점에서 반올림하세요.</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, SAL,
TRUNC(SAL/21.5, 2) AS DAY_PAY,
ROUND(SAL/21.5/8, 1) AS TIME_PAY //~~ROUND(DAY_PAY/8, 1) AS TIME_PAY~~
FROM EMP;</code></pre>
<ul>
<li>Q3. EMP 테이블에서 사원들은 입사일(HIREDATE)을 기준으로 3개월이 지난 후 첫 월요일에 정직원이 됩니다. 사원들이 정직원이 되는 날짜(R_JOB)를 YYYY-MM-DD 형식으로 오른쪽과 같이 출력해 주세요. 단 추가 수당(COMM)이 없는 사원의 추가 수당은 N/A로 출력하세요.</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, HIREDATE,
       TO_CHAR(NEXT_DAY(ADD_MONTHS(HIREDATE, 3), &#39;월요일&#39;), &#39;YYYY-MM-DD&#39;) AS R_JOB,
       NVL(TO_CHAR(COMM), &#39;N/A&#39;) AS COMM
  FROM EMP;
//nvl 데이터 타입 똑같아야 </code></pre>
<ul>
<li>Q4. EMP 테이블의 모든 사원을 대상으로 직속 상관의 사원 번호(MGR)를 다음과 같은 조건을 기준으로 변환해서 CHG_MGR 열에 출력하세요.</li>
</ul>
<ol>
<li>직속 상관의 사원 번호가 존재하지 않을 경우 : 0000</li>
<li>직속 상관의 사원 번호 앞 두자리가 75일 경우 : 5555</li>
<li>직속 상관의 사원 번호 앞 두자리가 76일 경우 : 6666</li>
<li>직속 상관의 사원 번호 앞 두자리가 77일 경우 : 7777</li>
<li>직속 상관의 사원 번호 앞 두자리가 78일 경우 : 8888</li>
<li>그 외 직속 상관 사원 번호의 경우 : 본래 직속 상관의 사원 번호 그대로 출력</li>
</ol>
<pre><code class="language-sql">SELECT EMPNO, ENAME, MGR,
       CASE
          WHEN MGR IS NULL THEN &#39;0000&#39;
          WHEN SUBSTR(MGR, 1, 2) = &#39;78&#39; THEN &#39;8888&#39;
          WHEN SUBSTR(MGR, 1, 2) = &#39;77&#39; THEN &#39;7777&#39;
          WHEN SUBSTR(MGR, 1, 2) = &#39;76&#39; THEN &#39;6666&#39;
          WHEN SUBSTR(MGR, 1, 2) = &#39;75&#39; THEN &#39;5555&#39;
          ELSE TO_CHAR(MGR)
       END AS CHG_MGR
  FROM EMP;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day7]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day7</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day7</guid>
            <pubDate>Mon, 05 Dec 2022 18:05:34 GMT</pubDate>
            <description><![CDATA[<h2 id="06---1-오라클-함수">06 - 1 오라클 함수</h2>
<ul>
<li>내장 함수의 종류</li>
</ul>
<ol>
<li>데이터가 한 행씩 입력되고 입력된 한 핸당 결과가 하나씩 나오는 함수를 단일행 함수라고 한다.</li>
<li>여러 행이 입력되어 하나의 행으로 결과가 반환되는 함수를 다중행 함수라고 한다.</li>
</ol>
<h2 id="06---2-문자-데이터를-가공하는-문자-함수">06 - 2 문자 데이터를 가공하는 문자 함수</h2>
<ul>
<li>문자 함수는 문자 데이터를 가공하거나 문자 데이터로부터 특정 결과를 얻고자 할 때 사용하는 함수이다. 실무에서 자주 사용하는 데이터는 문자, 숫자, 날짜 데이터이다.</li>
</ul>
<blockquote>
<p>대 · 소문자를 바꿔 주는 UPPER, LOWER, INITCAP 함수</p>
</blockquote>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>UPPER(문자열)</td>
<td>괄호 안 문자 데이터를 모두 대문자로 변환하여 반환</td>
</tr>
<tr>
<td>LOWER(문자열)</td>
<td>괄호 안 문자 데이터를 모두 소문자로 변환하여 반환</td>
</tr>
<tr>
<td>INITCAP(문자열)</td>
<td>괄호 안 문자 데이터 중 첫 글자는 대문자로, 나머지 문자를 소문자로 변환 후 반환</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT ENAME, UPPER(ENAME), LOWER(ENAME), INITCAP(ENAME)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/8ed652d6-4696-4880-9577-7f5a407519bd/image.png" alt=""></p>
<ul>
<li>문자열 길이를 구하는 LENGHT 함수</li>
</ul>
<p>특정 문자열의 길이를 구할 때 LENGTH 함수를 사용한다.</p>
<pre><code class="language-sql">SELECT ENAME, LENGTH(ENAME)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/78afd4e4-5f4c-4131-ab26-05d5c93b8cc2/image.png" alt=""></p>
<pre><code class="language-sql">SELECT ENAME, LENGTH(ENAME)
FROM EMP
WHERE LENGTH(ENAME) &gt;= 5;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/aa4422f5-ff75-4f54-b3b1-e4260bc3516f/image.png" alt=""></p>
<pre><code class="language-sql">SELECT LENGTH(&#39;한글&#39;), LENGTHB(&#39;한글&#39;)
FROM DUAL;
// LENGTG 함수는 길이 반환이라 2, LENGTHB 함수는 문자열의 바이트 수를 반환하기 때문에 4
// *한글은 한 문자당 2byte로 처리</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/bf0705be-5881-4660-adc1-b9e4d054d454/image.png" alt=""></p>
<blockquote>
<p>문자열 일부를 출력하는 SUBSTR 함수</p>
</blockquote>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>SUBSTR(문자열 데이터, 시작 위치, 추출 길이)</td>
<td>문자열 데이터의 시작 위치부터 추출 길이만큼 추출합니다. 시작 위치가 음수일 경우에는 마지막 위치부터 거슬러 올라간 위치에서 시작합니다.</td>
</tr>
<tr>
<td>SUBSTR(문자열 데이터, 시작 위치)</td>
<td>문자열 데이터의 시작 위치부터 문자열 데이터 끝까지 추출합니다. 시작 위치가 음수일 경우에는 마지막 위치부터 거슬러 올라간 위치에서 끝까지 추출합니다.</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT JOB, SUBSTR(JOB, 1, 2), SUBSTR(JOB, 3, 2), SUBSTR(JOB, 5)
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/dc60a06e-2758-48f1-993a-5086818876a3/image.png" alt=""></p>
<blockquote>
<p>문자열 데이터 안에서 특정 문자 위치를 차즌 INSTR 함수</p>
</blockquote>
<p>문자열 데이터 안에 특정 문자나 문자열이 어디에 포함되어 있는지를 알고자 할 때 INSTR 함수를 사용한다. INSTR 함수는 총 네 개의 입력 값을 지정할 수 있으며 최소 두 개의 입력 값, 즉 원본 문자열 데이터와 원본 문자열 데이터에서 찾으려는 문자 이렇게 두 가지는 반드시 시정해 주어야 한다.</p>
<pre><code class="language-sql">INSTR([대상 문자열 데이터(필수)],
[위치를 찾으려는 부분 문자(필수)],
[위치 찾기를 시작할 대상 문자열 데이터 위치(선택, 기본값은 1)],
[시작 위치에서 찾으려는 문자가 몇 번째인지 지정(선택, 기본값은 1)]</code></pre>
<pre><code class="language-sql">SELECT INSTR(&#39;HELLO, ORACLE!&#39;, &#39;L&#39;) AS INSTR_1,
INSTR(&#39;HELLO, ORACLE!&#39;, &#39;L&#39;, 5) AS INSTR_2,
INSTR(&#39;HELLO, ORACLE!&#39;, &#39;L&#39;, 2, 2) AS INSTR_3
FROM DUAL;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/1fd1aa7e-0f38-4f1e-93e7-0f91f4a3bd9b/image.png" alt=""></p>
<blockquote>
<p>특정 문자를 다른 문자로 바꾸는 REPLACE 함수</p>
</blockquote>
<pre><code class="language-sql">REPLACE([문자열 데이터 또는 열 이름(필수)], [찾는 문자(필수)], [대체할 문자(선택)]</code></pre>
<p>⭐ 만약 대체할 문자를 입력하지 않는다면 찾는 문자로 지정한 문자는 문자열 데이터에서 삭제된다.</p>
<blockquote>
<p>데이터의 빈 공간을 특정 문자로 채우는 LPAD, RPAD 함수</p>
</blockquote>
<pre><code class="language-sql">LPAD([문자열 데이터 또는 열이름(이름)], [데이터의 자릿수(필수)], [빈 공간에 채울 문자(선택)]
RPAD([문자열 데이터 또는 열이름(이름)], [데이터의 자릿수(필수)], [빈 공간에 채울 문자(선택)]</code></pre>
<blockquote>
<p>두 문자열 데이터를 합치는 CONCAT 함수</p>
</blockquote>
<p>CONCAT 함수는 두 개의 문자열 데이터를 하나의 데이터로 연결해 주는 역할을 한다.</p>
<pre><code class="language-sql">SELECT CONCAT(EMPNO, ENAME),
CONCAT(EMPNO, CONCAT( &#39; : &#39;, ENAME))
FROM EMP
WHERE ENAME = &#39;SCOTT&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/9e66ceec-c329-4005-af6f-de40d557c981/image.png" alt=""></p>
<blockquote>
<p>특정 문자를 지우는 TRIM, LTRIM, RTRIM 함수</p>
</blockquote>
<pre><code class="language-sql">TRIM([삭제 옵션(선택)] [삭제할 문자(선택)] FROM [원본 문자열 데이터(필수)]</code></pre>
<p>TRIM 함수의 삭제할 문자는 필수가 아니므로 지정하지 않아도 된다. 삭제할 문자가 없으면 공백이 제거된다.</p>
<pre><code class="language-sql">LTRIM([원본 문자열 데이터(필수)], [삭제할 문자 집합(선택)]) // 1.
RTRIM([원본 문자열 데이터(필수)], [삭제할 문자 집합(선택)]) // 2.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>원본 문자열의 왼쪽에서 삭제할 문자열을 지정합니다(삭제할 문자열을 지정하지 않으면 공백이 삭제됨).</td>
</tr>
<tr>
<td>2.</td>
<td>원본 문자열의 오른쪽에서 삭제할 문자열을 지정합니다(삭제할 문자열을 지정하지 않으면 공백이 삭제됨).</td>
</tr>
</tbody></table>
<h2 id="06---3-숫자-데이터를-연산하고-수치를-조정하는-숫자-함수">06 - 3 숫자 데이터를 연산하고 수치를 조정하는 숫자 함수</h2>
<ul>
<li>숫자 데이터를 다루는 함수</li>
</ul>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>ROUND</td>
<td>지정된 숫자의 특정 위치에서 반올림한 값을 반환</td>
</tr>
<tr>
<td>TRUNC</td>
<td>지정된 숫자의 특정 위치에서 버림한 값을 반환</td>
</tr>
<tr>
<td>CEIL</td>
<td>지정된 숫자보다 큰 정수 중 가장 작은 정수를 반환</td>
</tr>
<tr>
<td>FLOOR</td>
<td>지정된 숫자보다 작은 정수 중 가장 큰 정수를 반환</td>
</tr>
<tr>
<td>MOD</td>
<td>지정된 숫자를 나눈 나머지 값을 반환</td>
</tr>
</tbody></table>
<blockquote>
<p>특정 위치에서 반올림하는 ROUND 함수</p>
</blockquote>
<p>ROUND 함수는 TRUNC 함수와 함께 가장 많이 사용하는 숫자 함수 중 하나이다.</p>
<pre><code class="language-sql">ROUND([숫자(필수)], [반올림 위치(선택)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 숫자를 반올림한 결과를 출력하는 데 사용합니다. 반올림 위치를 지정하지 않으면 소수점 첫 번째 자리에서 반올림이 수행됩니다.</td>
</tr>
</tbody></table>
<blockquote>
<p>특정 위치에서 버리는 TRUNC 함수</p>
</blockquote>
<p>TRUNC 함수는 지정된 자리에서 숫자를 버림 처리하는 함수이다.</p>
<pre><code class="language-sql">TRUNC([숫자(필수)], [버림 위치(선택)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 위치에서 숫자를 버림한 결과를 출력하는 데 사용합니다. 버림 위치를 지정하지 않을 경우 소수점 첫 번째 자리에서 버림이 수행됩니다.</td>
</tr>
</tbody></table>
<blockquote>
<p>지정한 숫자와 가까운 정수를 찾는 CEIL, FLOOR 함수</p>
</blockquote>
<pre><code class="language-sql">CEIL ([숫자(필수)])
FLOOR([숫자(필수)])</code></pre>
<blockquote>
<p>숫자를 나눈 나머지 값을 구하는 MOD 함수</p>
</blockquote>
<pre><code class="language-sql">MOD([나눗셈 될 숫자(필수)], [나눌 숫자(필수)]) // 1.</code></pre>
<table>
<thead>
<tr>
<th>번호</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1.</td>
<td>특정 숫자를 나누고 그 나머지를 출력하는 함수입니다.</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day6]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day6</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day6</guid>
            <pubDate>Mon, 05 Dec 2022 18:03:36 GMT</pubDate>
            <description><![CDATA[<h2 id="05---3-연산자-종류와-활용-방법-알아보기">05 - 3 연산자 종류와 활용 방법 알아보기</h2>
<ul>
<li>산술 연산자</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL * 12 = 36000;

// SAL열에 12를 곱한 값이 36000인 행을 출력하는 SQL문</code></pre>
<ul>
<li>비교 연산자</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL &gt;= 3000;
// SAL이 3000이상인 사원을 조회하는 SQL문</code></pre>
<p>이 외에도 아래 표처럼 다른 대소 비교 연산자가 있다.</p>
<table>
<thead>
<tr>
<th>연산자</th>
<th>사용법</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>&gt;</td>
<td>A &gt; B</td>
<td>A 값이 B 값을 초과할 경우 true</td>
</tr>
<tr>
<td>≥</td>
<td>A ≥ B</td>
<td>A 값이 B 값 이상일 경우 true</td>
</tr>
<tr>
<td>&lt;</td>
<td>A &lt; B</td>
<td>A 값이 B 값 미만일 경우 true</td>
</tr>
<tr>
<td>≤</td>
<td>A ≤ B</td>
<td>A 값이 B 값 이하일 경우 true</td>
</tr>
</tbody></table>
<p>⭐ 대소 비교 연산자는 비교 대상인 데이터가 숫자가 아닌 문자열일 때도 사용할 수 있습니다. 하지만 문자열의 대소 비교는 숫자 데이터 비교보다는 자주 사용되는 내용은 아니기 때문에 가볍게 이해하는 정도로만 기억해도 된다.</p>
<ul>
<li>등가 비교 연산자</li>
</ul>
<p>연산자의 양쪽 항목 값이 같으면 true가 반환되고, 반대로 연산자의 양쪽 값이 다를 경우 true를 반환하는 연산자도 있다.</p>
<table>
<thead>
<tr>
<th>연산자</th>
<th>사용법</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td>=</td>
<td>A = B</td>
<td>A 값이 B 값과 같을 경우 true, 다를 경우 false 반환</td>
</tr>
<tr>
<td>! =</td>
<td>A ! = B</td>
<td>A 값과 B 값이 다를 경우 true, 같은 경우 false 반환</td>
</tr>
<tr>
<td>&lt;&gt;</td>
<td>A &lt;&gt; B</td>
<td>“</td>
</tr>
<tr>
<td>^=</td>
<td>A ^= B</td>
<td>“</td>
</tr>
<tr>
<td>- 논리 부정 연산자</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>비교 연산자는 아니지만 ! =, &lt;&gt;, ^=과 똑같은 결과를 출력하기 위해 사용할 수 있는 연산자가 하나 더 있다. 바로 논리 부정 연산자인 NOT 연산자이다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE NOT SAL = 3000;
// WHERE SAL != 3000; WHERE SAL &lt;&gt; 3000; WHERE SAL ^= 3000;
// 과 똑같이 출력된다.</code></pre>
<p>⭐ NOT 연산자를 IN, BETWEEN, IS NULL 연산자와 함꼐 복합적으로 사용하는 경우가 많고, 대소 · 등가 비교 연산자에 직접 사용하는 경우는 별로 없다.</p>
<ul>
<li>IN 연산자</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE JOB = &#39;MANAGER&#39;
OR JOB = &#39;SALESMAN&#39;
OR JOB = &#39;CLERK&#39;;
// OR 연산자를 사용해서 출력해도 되지만, 조건이 늘어날수록</code></pre>
<p>OR 연산자를 사용해서 출력해도 되지만, 조건이 늘어날수록 조건식을 많이 작성해야 하기 때문에 아래와 같이 IN 연산자를 사용하면 특정 열에 해당하는 조건을 여러 개 지정할 수 있다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE JOB IN (&#39;MANAGER&#39;, &#39;SALESMAN&#39;, &#39;CLERK&#39;);</code></pre>
<ul>
<li>BETWEEN A AND B 연산자</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL &gt;= 2000
AND SAL &lt;= 3000;</code></pre>
<p>AND 연산자를 사용해서도 가능하지만, 특정 열 값의 최소  · 최고 범위를 지정하여 해당 범위 내의 데이터만 조회할 경우에 대소 비교 연산자 대신 BETWEEN A AND B 연산자를 사용하면 더 간단하게 표현할 수 있다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE SAL BETWEEN 2000 AND 3000;</code></pre>
<ul>
<li>LIKE 연산자와 와일드 카드</li>
</ul>
<p>LIKE 연산자는 이메일이나 게시판 제목 또는 내용 검색 기능처럼 일부 문자열이 포함된 데이터를 조회할 때 사용한다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE ENAME LIKE &#39;S%&#39;;</code></pre>
<p>ENAME LIKE ‘S%’ 조건식은 ENAME 열 값이 대문자 S로 시작하는 데이터를 조회하라는 뜻이다.</p>
<p>위 조건식에서 사용한 %기호를 와일드 카드라고 한다. 와일드 카드는 특정 문자 또는 문자열을 대체하거나 문자열 데이터의 패턴을 표기하는 특수 문자이다.</p>
<p>LIKE 연산자와 함께 사용할 수 있는 와일드 카드는 _와 %이다.</p>
<table>
<thead>
<tr>
<th>종류</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td>_</td>
<td>어떤 값이든 상관없이 한 개의 문자 데이터를 의미</td>
</tr>
<tr>
<td>%</td>
<td>길이와 상관없이(문자 없는 경우도 포함) 모든 문자 데이터를 의미</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<p>ENAME의  두 번째 글자가 L인 사원 데이터를 조회하고 싶다면 아래와 같이 LIKE 연산자에 와일드 카드를 활용할 수 있다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE ENAME LIKE &#39;_L%&#39;</code></pre>
<hr>
<p>ENAME에 AM이라는 단어를 포함하는 사원을 조회할 때 아래와 같이 작성하면 된다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE ENAME LIKE &#39;%AM%&#39;;</code></pre>
<ul>
<li>IS NULL</li>
</ul>
<p>WHERE절은 조건식의 결과 값이 true인 행만 출력하는데 연산 결과 값이 NULL이 되어 버리면 조건식의 결과 값이 false도 true도 아니게 되므로 출력 대상에서 제외된다. </p>
<p>그러므로 특정 열 또는 연산의 결과 값이 NULL인지 여부를 확인하려면 IS NULL 연산자를 아래와 같이 사용해야 한다.</p>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE COMM IS NULL;</code></pre>
<p>IS NULL 연산자를 사용하면 추가 수당 열 값이 존재하지 않는 데이터만 출력한다.</p>
<p>⭐데이터가 NULL인지 아닌지를 확인하는 용도로만 사용하는 IS NULL과 IS NOT NULL 연산자는 매우 자주 사용되므로 사용법을 꼭 기억하자❗</p>
<ul>
<li>집합연산자 UNION</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 10
UNION
SELECT EMPNO, ENAME, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 20;</code></pre>
<p>집합 연산자를 사용하면서 주의할 점을 두 개의 SELECT문의 결과 값을 연결할 때 각 SELECT문이 출력하려는 열 개수와 각 열의 자료형이 순서별로 일치해야 한다.</p>
<p>⭐ 집합 연산자에는 아래와 같이 4가지 종류가 있다.</p>
<table>
<thead>
<tr>
<th>종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>UNION</td>
<td>연결된 SELECT문의 결과 값을 합집합으로 묶어 준다. 결과 값의 중복은 제거된다.</td>
</tr>
<tr>
<td>UNION ALL</td>
<td>연결된 SELECT문의 결과 값을 합집합으로 묶어 준다. 중복된 결과 값도 제거 없이 모두 출력된다.</td>
</tr>
<tr>
<td>MINUS</td>
<td>먼저 작성한 SELECT문의 결과 값에서 다음 SELECT문의 결과 값을 차집합 처리한다. 먼저 작성한 SELECT문의 결과 값 중 다음 SELECT문에 존재하지 않는 데이터만 출력된다.</td>
</tr>
<tr>
<td>INTERSECT</td>
<td>먼저 작성한 SELECT문과 다음 SELECT문의 결과 값이 같은 데이터만 출력된다. 교집합과 같은 의미이다.</td>
</tr>
</tbody></table>
<ul>
<li>연산자 우선순위</li>
</ul>
<p>WHERE절 조건식에 사용한 여러 연산자는 아래와 같은 우선순위(priority)를 가지고 있다.</p>
<table>
<thead>
<tr>
<th>우선순위</th>
<th>연산자</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>↑</td>
<td>*, /</td>
<td>산술 연산자 곱하기, 나누기</td>
</tr>
<tr>
<td>(높음)</td>
<td>+, -</td>
<td>산술 연산자 더하기, 빼기</td>
</tr>
<tr>
<td></td>
<td>=, ! =, ^=, &lt;&gt;, &gt;, ≥, &lt;, ≤</td>
<td>대소 비교 연산자</td>
</tr>
<tr>
<td></td>
<td>IS (NOT) NULL, (NOT) LIKE, (NOT) IN</td>
<td>(그 외) 비교 연산자</td>
</tr>
<tr>
<td></td>
<td>BETWEEN A AND B</td>
<td>BETWEEN 연산자</td>
</tr>
<tr>
<td></td>
<td>NOT</td>
<td>논리 부정 연산자 NOT</td>
</tr>
<tr>
<td>(낮음)</td>
<td>AND</td>
<td>논리 연산자 AND</td>
</tr>
<tr>
<td>↓</td>
<td>OR</td>
<td>논리 연산자 OR</td>
</tr>
</tbody></table>
<p>⭐ 수학식에서와 마찬가지로 먼저 수행해야 하는 연산식을 소괄호()로 묶어 주면 연산자의 기본 우선순위와는 별개로 괄호 안의 연산식을 먼저 수행한다.</p>
<h2 id="5장-잊기-전에-한-번-더">5장 잊기 전에 한 번 더!</h2>
<ul>
<li>Q1. EMP 테이블을 사용하여 다음과 같이 사원 이름(ENAME)이 S로 끝나는 사원 데이터를 모두 출력하는 SQL문을 작성해 보세요.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE ENAME LIKE &#39;%S&#39;;</code></pre>
<ul>
<li>Q2. EMP 테이블을 사용하여 30번 부서(DEPTNO)에서 근무하고 있는 사원 중에 직책(JOB)이 SALESMAN인 사원의 사원 번호, 이름, 직책, 급여, 부서 번호를 출력하는 SQL문을 작성해 보세요.</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 30
AND JOB = &#39;SALESMAN&#39;;</code></pre>
<ul>
<li>Q3. EMP 테이블을 사용하여 20번, 30번 부서에 근무하고 있는 사원 중 급여(SAL)가 2000 초과인 사원을 다음 두 가지 방식의 SELECT문을 사용하여 사원 번호, 이름, 급여, 부서 번호를 출력하는 SQL문을 작성해 보세요.</li>
</ul>
<ol>
<li>집합 연산자를 사용하지 않은 방식</li>
</ol>
<pre><code class="language-sql">SELECT EMPNO, ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE DEPTNO IN (20, 30)
AND SAL &gt; 2000;</code></pre>
<ol>
<li>집합 연산자를 사용한 방식</li>
</ol>
<pre><code class="language-sql">SELECT EMPNO, ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 20
AND SAL &gt; 2000
UNION
SELECT EMPNO, ENAME, JOB, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 30
AND SAL &gt; 2000;</code></pre>
<ul>
<li>Q4. 이번에는 NOT BETWEEN A AND B 연산자를 쓰지 않고, 급여(SAL) 열 값이 2000 이상 3000 이하 범위 이외의 값을 가진 데이터만 출력하도록 SQL문을 작성해 보세요.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
~~WHERE SAL &gt;= 2000
AND SAL &lt;= 3000;~~
WHERE SAL &lt; 2000
OR SAL &gt; 3000;</code></pre>
<ul>
<li>Q5. 사원 이름에 E가 포함되어 있는 30번 부서의 사원 중 급여가 1000~2000 사이가 아닌 사원 이름, 사원 번호, 급여, 부서 번호를 출력하는 SQL문을 작성해 보세요.</li>
</ul>
<pre><code class="language-sql">SELECT ENAME, EMPNO, SAL, DEPTNO
FROM EMP
WHERE DEPTNO = 30
AND ENAME LIKE &#39;%E%&#39;
AND SAL NOT BETWEEN 1000 AND 2000;</code></pre>
<ul>
<li>Q6. 추가 수당이 존재하지 않고 상급자가 있고 직책이 MANAGER, CLERK인 사원 중에서 사원 이름의 두 번째 글자가 L이 아닌 사원의 정보를 출력하는 SQL문을 작성해 보세요.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE COMM IS NULL
AND MGR IS NULL
AND JOB IN (&#39;MANAGER&#39;, &#39;CLERK&#39;)
AND ENAME NOT LIKE &#39;_L%&#39;;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day5]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day5</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day5</guid>
            <pubDate>Mon, 05 Dec 2022 18:02:22 GMT</pubDate>
            <description><![CDATA[<h2 id="05---1-필요한-데이터만-쏙-출력하는-where절">05 - 1 필요한 데이터만 쏙 출력하는 WHERE절</h2>
<ul>
<li>WHERE절은 SELECT문으로 데이터를 조화할 때 특정 조건을 기준으로 원하는 행을 출력하는 데 사용한다.</li>
</ul>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
WHERE [조회할 행을 선별하기 위한 조건식];</code></pre>
<ul>
<li>모든 열 출력</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e855a644-7f99-4f8f-80ee-2da200fcde78/image.png" alt=""></p>
<ul>
<li>DEPTNO가 30인 데이터만 출력</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/5b054763-4024-4028-b889-4388510d6e82/image.png" alt=""></p>
<h2 id="05---2-여러-개-조건식을-사용하는-and-or-연산자">05 - 2 여러 개 조건식을 사용하는 AND, OR 연산자</h2>
<blockquote>
<p><strong>AND</strong></p>
</blockquote>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE DEPTNO = 30
AND JOB = &#39;SALESMAN&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/21b8c5ef-8c84-4b0e-ad58-3da5243de061/image.png" alt=""></p>
<ul>
<li>EMP 테이블에서 JOB과 DEPTNO 조건식의 결과 값이 모둔 true인 행만 출력한다.</li>
</ul>
<p>❗테이블 안에 들어 있는 문자 또는 문자열 데이터는 대 · 소문자를 구별하니 주의.</p>
<hr>
<blockquote>
<p><strong>OR</strong></p>
</blockquote>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE DEPTNO = 30
OR JOB = &#39;CLERK&#39;;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/adb84bd2-7b5b-4db2-b095-15011a756efb/image.png" alt=""></p>
<ul>
<li>AND 연산자를 사용했을 때와 달리 조건식이 하나만 일치하는 DEPTNO = 30인 행과 JOB = ‘CLERK’인 행 모두 출력된다.</li>
</ul>
<hr>
<ul>
<li>오른쪽과 같이 WHERE절에 사용할 수 있는 조건식의 개수는 사실상 제한이 없다고 보아도 무방하다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE [조건식 1]
  AND [조건식 2]
   OR [조건식 3]
...
  AND [조건식 N]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[20220716 스터디 발표]]></title>
            <link>https://velog.io/@bebeco_o/20220716-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%9C%ED%91%9C</link>
            <guid>https://velog.io/@bebeco_o/20220716-%EC%8A%A4%ED%84%B0%EB%94%94-%EB%B0%9C%ED%91%9C</guid>
            <pubDate>Mon, 05 Dec 2022 18:00:37 GMT</pubDate>
            <description><![CDATA[<h2 id="4-select문의-기본-형식">4. SELECT문의 기본 형식</h2>
<h3 id="사원-정보가-들어-있는-emp-테이블">사원 정보가 들어 있는 EMP 테이블</h3>
<pre><code class="language-sql">DESC EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/21d3f2de-8011-48a5-8a18-7f4a53de1501/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>열 이름</th>
<th>열 의미</th>
<th>데이터 종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>EMPNO</td>
<td>사원 번호</td>
<td>네 자리 숫자</td>
<td>EMP 테이블에서 각 사원의 데이터를 구분할 수 있는 유일한 값을 저장하는 열이며 기본키로 사용한다.</td>
</tr>
<tr>
<td>ENAME</td>
<td>사원 이름</td>
<td>10byte 크기의 가변형 문자열</td>
<td>SCOTT, JONES 등</td>
</tr>
<tr>
<td>JOB</td>
<td>사원 직책</td>
<td>9byte 크기의 가변형 문자열</td>
<td>MANAGER, CLERK 등</td>
</tr>
<tr>
<td>MGR</td>
<td>직속 상관의 사원 번호</td>
<td>네 자리 숫자</td>
<td>MGR은 manager의 약어로 현재 행에 해당하는 사원의 상급자의 네 자리 사원 번호를 저장하는 열이다.</td>
</tr>
<tr>
<td>HIREDATE</td>
<td>입사일</td>
<td>날짜 데이터</td>
<td>HIREDATE는 입사일을 나타내는 날짜 데이터이다.</td>
</tr>
<tr>
<td>SAL</td>
<td>급여</td>
<td>두 자리 소수점을 포함하는 입곱 자리 숫자</td>
<td>800, 600, 5000 등</td>
</tr>
<tr>
<td>COMM</td>
<td>급여 외 추가 수당</td>
<td>두 자리 소수점을 포함하는 일곱 자리 숫자</td>
<td>COMM은 commission의 약어로 월 급여 외 추가 수당을 의미한다.</td>
</tr>
<tr>
<td>DEPTNO</td>
<td>사원이 속한 부서 번호</td>
<td>두 자리 숫자</td>
<td>DEPTNO는 department number의 약어이며 사원이 속해 있는 부서의 고유번호를 의미한다.</td>
</tr>
<tr>
<td>- 가변형 문자열 :</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>문자열 데이터가 10byte보다 작은 공간을 차지할 경우에는 데이터가 차지하는 공간만큼만 저장 공간을 할당한다.</p>
<p>기억장소가 절약되는 장점이 있다.</p>
<ul>
<li>고정형:</li>
</ul>
<p>CHAR(7)은 3byte만 사용해도 7byte 만큼의 데이터가 사용된다.</p>
<p>사이즈가 고정인 만큼 추후에 연산 필요성이 없어 검색 및 읽기 속도가 다른 타입보다 빠르다.  </p>
<h3 id="회사-부서-정보가-들어-있는-dept-테이블">회사 부서 정보가 들어 있는 DEPT 테이블</h3>
<pre><code class="language-sql">DESC DEPT;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/5cce91bf-f6c8-43c3-8ef3-b9ea781d5307/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>열 이름</th>
<th>열 의미</th>
<th>데이터 종류</th>
</tr>
</thead>
<tbody><tr>
<td>DEPTNO</td>
<td>부서 번호</td>
<td>두 자리 숫자</td>
</tr>
<tr>
<td>DNAME</td>
<td>부서 이름</td>
<td>14byte 크기의 가변형 문자열</td>
</tr>
<tr>
<td>LOC</td>
<td>부서가 위치한 지역</td>
<td>13byte 크기의 가변형 문자열</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/7932bb4c-592d-439e-a2f7-2285f32c2715/image.png" alt=""></p>
<p>좌 : EMP, 우 : DEPT</p>
<hr>
<ul>
<li>EMP 테이블의 DEPTNO 열이 DEPT 테이블의 DEPTNO 열을 참조하여 부서 관련 데이터를 확인할 수 있다. 즉 DEPT 테이블의 DEPTNO 열은 EMP 테이블의 외래키로 사용할 수 있다.</li>
</ul>
<h3 id="데이터를-조회하는-3가지-방법">데이터를 조회하는 3가지 방법</h3>
<ul>
<li>셀렉션(selection) : 행 단위로 원하는 데이터를 조회</li>
<li>프로젝션(projection) : 열 단위로 원하는 데이터를 조회</li>
<li>조인(join) : 두 개 이상의 테이블을 연결하여 하나의 테이블인 것처럼 데이터를 조회</li>
</ul>
<h3 id="select절과-from절">SELECT절과 FROM절</h3>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름] 또는 애스터리스크(*)로 전체 열
FROM [조회할 테이블 이름];</code></pre>
<ul>
<li>EMP 테이블 전체 열 조회하기</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/3a8b4095-dd02-4389-97b1-f287a2dd7bec/image.png" alt=""></p>
<p>❗문장 끝에 세미콜론(;)을 꼭 넣자.</p>
<ul>
<li>EMP 테이블 부분 열 출력</li>
</ul>
<pre><code class="language-sql">SELECT EMPNO, ENAM
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/b4d97218-874b-4106-9aea-309086497a48/image.png" alt=""></p>
<h3 id="중복-데이터-삭제-distinct">중복 데이터 삭제 DISTINCT</h3>
<ul>
<li>열 중복 제거하기</li>
</ul>
<pre><code class="language-sql">SELECT DISTINCT JOB, DEPTNO                        //DISTINCT DEPTNO, JOB
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/1ea9a8c6-1518-4c6a-8f17-181e16ce9748/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e2658f63-8573-4af0-8e73-94cea0048560/image.png" alt=""></p>
<ul>
<li>SALESMAN의 경우 JOB(직책)과 DEPTNO(부서 번호)가 모두 일치하므로 중복 데이터로 걸러져 한 번만 출력되지만 MANAGER의 경우 DEPTNO(부서 번호)가 다르기 때문에 중복 데이터가 아닙니다.</li>
</ul>
<p>⭐ DISTINCT [열1 이름], [열2 이름] 순서를 바꾸면 열 출력 순서만 바뀌고 결과는 똑같다~</p>
<ul>
<li>ALL로 중복되는 열 제거 없이 그대로 출력하기</li>
</ul>
<pre><code class="language-sql">SELECT JOB, DEPTNO          // SELECT ~~ALL~~ JOB, DEPTNO     
FROM EMP;                   // FROM EMP;</code></pre>
<h3 id="별칭-설정하기">별칭 설정하기</h3>
<ul>
<li><p>SQL문에서는 최종 출력되는 열 이름을 임의로 지정할 수 있다.</p>
</li>
<li><p>별칭 지정하는 방식</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>사용 방법</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>SAL*12+COMM ANNSAL</td>
<td>연산 및 가공된 문장 이후 한 칸 띄우고 별칭 지정</td>
</tr>
<tr>
<td>SAL*12+COMM “ANNSAL”</td>
<td>연산 및 가공된 문장 이후 한 칸 띄우고 별칭을 큰따옴표(” “)로 묶어 지정</td>
</tr>
<tr>
<td>SAL*12+COMM AS ANNSAL</td>
<td>연산 및 가공된 문장 이후 한 칸 띄운 후 ‘AS’, 한 칸 뒤에 별칭 지정</td>
</tr>
<tr>
<td>SAL*12+COMM AS “ANNSAL”</td>
<td>연산 및 가공된 문장 이후 한 칸 띄운 후 ‘AS’, 한 칸 뒤에 별칭을 큰따옴표(” “)로 묶어 지정</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/4b64a748-0eb0-4915-9f3c-c5961cd4af2f/image.png" alt=""></p>
<p>좌 : 별칭 지정 ❌, 우 : 별칭 지정 ⭕벼</p>
<hr>
<p>별칭은 가독성을 위해 사용하기도 하지만 보안이나 데이터 노출 문제 때문에 사용하는 경우도 있다.  </p>
<p>예로 별칭을 사용하지 않으면 위와 같이 계산식 자체가 열 이름에 노출되는 경우이다.</p>
<h3 id="원하는-순서로-출력-데이터를-정렬하는-order-by">원하는 순서로 출력 데이터를 정렬하는 ORDER BY</h3>
<ul>
<li>ORDER BY절은 SELECT문을 작성할 때 사용할 수 있는 여러 절 중 가장 마지막 부분에 쓴다.</li>
</ul>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM   [조회할 테이블 이름]
.
. (그 밖의 절)
.
ORDER BY [정렬하려는 열 이름(여러 열 지정 가능)] [정렬 옵션];</code></pre>
<ul>
<li>정렬 옵션</li>
</ul>
<ol>
<li>ASC(오름차순) : 기본값이라 정렬 옵션을 지정하지 않을 경우 ASC로 정렬</li>
<li>DESC(내림차순)</li>
</ol>
<ul>
<li>각각의 열에 ASC와 DESC 동시에 사용하기</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
ORDER BY DEPTNO ASC, SAL DESC;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/d7c439da-e5a7-4da5-a478-5b905fa5aa4a/image.png" alt=""></p>
<pre><code class="language-sql">SELECT *
FROM EMP
ORDER BY SAL DESC, DEPTNO; //DEPTNO ASC &lt;-- ASC는 기본값이라 생략가능</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/69e9f821-e354-4254-baba-45a61e1fa1ce/image.png" alt=""></p>
<p>⭐ ORDER BY절은 먼저 기입하는 것에 따라 우선순위가 부여된다.</p>
<p>❗정렬을 하지 않으면 더 빨리 데이터 출력이 가능하고 여러 이유로 꼭 필요한 경우가 아니면 사용하지 않는 것이 좋다.</p>
<h2 id="5-더-정확하고-다양하게-결과를-출력하는-where절과-연산자">5. 더 정확하고 다양하게 결과를 출력하는 WHERE절과 연산자</h2>
<h3 id="필요한-데이터만-출력하는-where절">필요한 데이터만 출력하는 WHERE절</h3>
<ul>
<li>특정 조건을 기준으로 원하는 <del>행</del>을 결과가 참(true)인 경우 출력하는데 사용한다.</li>
</ul>
<pre><code class="language-sql">SELECT *
FROM EMP
WHERE ~~DEPTNO = 30;~~</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/1297f5f8-a6d5-483c-bbe5-271c24311aa6/image.png" alt=""></p>
<h3 id="and-or-연산자">AND, OR 연산자</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day4]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day4</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day4</guid>
            <pubDate>Mon, 05 Dec 2022 17:57:06 GMT</pubDate>
            <description><![CDATA[<h2 id="04---1-실습용-테이블-살펴보기">04 - 1 실습용 테이블 살펴보기</h2>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/af20d8ee-ef84-4a3b-a63d-7065dee991ec/image.png" alt=""></p>
<ul>
<li>VARCHAR2(10)는 가변형 문자열이라 10byte보다 작은 공간을 차지할 경우에 데이터가 차지하는 공간만큼만 저장 공간을 할당한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/16768d1f-680d-4288-be9f-b45456e204ac/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/ee70d5ef-aab8-4bda-b992-e4a10dd51640/image.png" alt=""></p>
<ul>
<li>EMP테이블의 DEPTNO 열이 DEPT테이블의 DEPTNO 열을 참조하여 부서 관련 데이터를 확인할 수 있어 데이터의 중복을 최소화할 수 있다. 즉 DEPT테이블의 DEPTNO 열은 EMP테이블의 외래키로 사용할 수 있따.</li>
</ul>
<h2 id="04---2-데이터를-조회하는-3가지-방법---셀렉션-프로젝션-조인">04 - 2 데이터를 조회하는 3가지 방법 - 셀렉션, 프로젝션, 조인</h2>
<ul>
<li>셀렉션 : 행 단위로 원하는 데이터를 조회하는 방식이다.</li>
<li>프로젝션 : 열 단위로 원하는 데이터를 조회하는 방식이다.</li>
<li>조인 : 두 개 이상의 테이블을 양옆에 연결하여 마치 하나의 테이블인 것처럼 데이터를 조회하는 방식이다.</li>
</ul>
<h2 id="04---3-sql의-기본-뼈대-select절과-from절">04 - 3 SQL의 기본 뼈대, SELECT절과 FROM절</h2>
<ul>
<li>SELECT문은 DB에 보관되어 있는 데이터를 조회하는 데 사용한다.</li>
<li>FROM절은 조회할 데이터가 저장된 테이블 이름을 명시한다.</li>
</ul>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름] 또는 *로 전체 열
FROM [조회할 테이블 이름];</code></pre>
<h2 id="04---4-중복-데이터를-삭제하는-distinct">04 - 4 중복 데이터를 삭제하는 DISTINCT</h2>
<ul>
<li>SELECT문으로 데이터를 조회한 후 DISTINCT를 사용하여 중복을 제거한다.</li>
</ul>
<pre><code class="language-sql">// 중복제거X
SELECT DEPTNO
FROM EMP;</code></pre>
<pre><code class="language-sql">// 중복제거O
SELECT DISTINCT DEPTNO
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/6bf1cd0e-311b-4b0c-bf15-1d9617319163/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/82a5440b-4eec-4119-9761-fc7cd76276cc/image.png" alt=""></p>
<ul>
<li>ALL은 중복되는 열 제거 없이 그대로 출력하기지만 ALL을 빼고 열만 조회해도 결과는 같습니다.</li>
</ul>
<pre><code class="language-sql">SELECT ALL JOB, DEPTNO
FROM EMP;</code></pre>
<h2 id="04---5-한눈에-보기-좋게-별칭-설정하기">04 - 5 한눈에 보기 좋게 별칭 설정하기</h2>
<ul>
<li>별칭 사용 없이 출력하기</li>
</ul>
<pre><code class="language-sql">SELECT SAL*12+COMM
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/e7458e6b-34b3-474c-b9a1-3d90328b1686/image.png" alt=""></p>
<ul>
<li>별칭 지정해서 출력하기</li>
</ul>
<pre><code class="language-sql">SELECT SAL*12+COMM AS ANNSAL
FROM EMP;</code></pre>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/610d20fd-f275-4cb6-acb4-70c957f55375/image.png" alt=""></p>
<ul>
<li>별칭은 가독성을 위해서만 사용되는 게 아닌 위 이미지처럼 계산식 자체가 열 이름에 노출되면 안 되는 경우 보안이나 데이터 노출 문제를 위해서도 사용된다.</li>
</ul>
<table>
<thead>
<tr>
<th>사용 방법</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>SAL*12+COMM ANNSAL</td>
<td>연산 및 가공된 문장 이후 한 칸 띄우고 별칭 지정</td>
</tr>
<tr>
<td>SAL*12+COMM “ANNSAL”</td>
<td>연산 및 가공된 문자 이후 한 칸 띄우고 별칭을 큰따옴표로 묶어 지정</td>
</tr>
<tr>
<td>SAL*12+COMM AS ANNSAL</td>
<td>연산 및 가공된 문장 이후 한 칸 띄운 후 ‘AS’, 한 칸 뒤에 별칭 지정</td>
</tr>
<tr>
<td>SAL*12+COMM AS “ANNSAL”</td>
<td>연산 및 가공된 문장 이후 한 칸 띄운 후 ‘AS’, 한 칸 뒤에 별칭을 큰따옴표로 묶어 지정</td>
</tr>
</tbody></table>
<p>⭐<strong>SAL*12+COMM AS ANNSAL</strong> 방식을 선호한다.</p>
<h2 id="04---6-원하는-순서로-출력-데이터를-정렬하는-order-by">04 - 6 원하는 순서로 출력 데이터를 정렬하는 ORDER BY</h2>
<ul>
<li>SELECT문을 사용하여 데이터를 조회할 때 시간이나 이름 순서 또는 어떤 다른 기준으로 데이터를 정렬해서 출력해야 하는 경우에 데이터를 정렬된 상태로 출력하기 위해 ORDER BY절을 사용한다.</li>
<li>ORDER BY절 정렬옵션</li>
</ul>
<ol>
<li>ASC : 오름차순이며 정렬옵션을 지정하지 않을 경우 기본값으로 ASC가 설정된다.</li>
<li>DESC : 내림차순이다.</li>
</ol>
<p>❗ORDER BY절은 SELECT문을 작성할 때 사용 할 수 있는 여러 절 중 가장 마지막 부분에 쓴다.</p>
<pre><code class="language-sql">SELECT [조회할 열1 이름], [열2 이름], ..., [열N 이름]
FROM [조회할 테이블 이름]
.
.
ORDER BY [정렬하려는 열 이름(여러 열 지정 가능)] [정렬옵션];</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day3]]></title>
            <link>https://velog.io/@bebeco_o/sql-study-day3</link>
            <guid>https://velog.io/@bebeco_o/sql-study-day3</guid>
            <pubDate>Mon, 05 Dec 2022 17:51:53 GMT</pubDate>
            <description><![CDATA[<h3 id="설치-파트">설치 파트</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[sql-study-day2]]></title>
            <link>https://velog.io/@bebeco_o/fp2641rf</link>
            <guid>https://velog.io/@bebeco_o/fp2641rf</guid>
            <pubDate>Mon, 05 Dec 2022 17:50:43 GMT</pubDate>
            <description><![CDATA[<h2 id="02---1-관계형-데이터베이스의-구성-요소">02 - 1 관계형 데이터베이스의 구성 요소</h2>
<h3 id="테이블">테이블</h3>
<ul>
<li>관계형 데이터베이스는 기본적으로 데이터를 2차원 표 형태로 저장하고 관리하며 이 형태의 저장 공간을 테이블(table)이라고 한다.</li>
<li>가로줄을 행(row), 세로줄을 열(column)이라고 부른다.</li>
</ul>
<ol>
<li>행은 저장하려는 하나의 개체를 구성하는 여러 값을 가로로 늘어뜨린 형태이다.</li>
<li>열은 저장하려는 데이터를 대표하는 이름과 공통 특성을 정의한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/ba06641f-91e9-4b78-8da8-51f2716cc4da/image.png" alt=""></p>
<h3 id="특별한-의미를-지닌-열-키">특별한 의미를 지닌 열, 키</h3>
<ul>
<li>종류별로 데이터를 구별하거나 테이블 간의 연관 관계를 표현할 때 키로 지정한 열을 사용한다.</li>
<li>키는 기본키(primary key), 후보키(candidate key), 외래키(foreign key), 복합키(composite key) 등으로 구분된다.</li>
</ul>
<ol>
<li>기본키</li>
</ol>
<p>키 중에서 가장 중요한 키로서 한 테이블 내에서 중복되지 않는 값만 가질 수 있는 키이다.</p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/730846df-12e0-4506-97a0-fcb056569f46/image.png" alt=""></p>
<ol>
<li>보조키</li>
</ol>
<p>대체키(alternate key)라고도 부르며 후보키(candidate key)에 속해 있는 키이다.</p>
<p>후보키는 기본키가 될 수 있는 모든 키를 의미하며, 기본키 역시 후보키에 속한다.</p>
<ol>
<li>외래키</li>
</ol>
<p>특정 테이블에 포함되어 있으면서 다른 테이블의 기본키로 지정된 키를 의미한다.</p>
<p>외래키를 사용하면 병합과 유사한 효과를 얻을 수 있어 데이터 중복을 최소화할 수 있으며, 저장 공간 크기와 관리는 비용과 밀접한 관련이 있기 때문에 데이터 중복은 최대한 피하느 것이 좋다.</p>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/30770718-d0d2-4f94-b89f-49dc7ef16768/image.png" alt=""></p>
<ol>
<li>복합키</li>
</ol>
<p>여러 열을 조합하여 기본키 역할을 할 수 있게 만든 키이다.</p>
<h2 id="02---2-오라클-데이터베이스">02 - 2 오라클 데이터베이스</h2>
<h3 id="자료형">자료형</h3>
<ul>
<li>테이블을 구성하는 열에 지정한다.</li>
<li>가장 많이 사용하는 자료형은 VARCHAR2, NUMBER, DATE이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/5b2a0f86-3c5e-457f-b6e3-9f7ad22c71a3/image.png" alt=""></p>
<ul>
<li>위 자료형 외에도 더 있다.</li>
</ul>
<h3 id="객체">객체</h3>
<ul>
<li>객체는 오라클DB 내에서 데이터를 저장하고 관리하기 위한 논리 구조를 가진 구성 요소이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bebeco_o/post/a19505c9-42b8-489e-94ca-9e1eb02a5905/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>