Oracle Master Bronz SQL

[1.基本（リレーショナルデータベースとSQL）](#1基本リレーショナルデータベースとsql)
[2.select文（select文を使用したデータの取得)](#2select文select文を使用したデータの取得)
[3.データの制限及びソート](#3データの制限及びソート)
[3-1.比較演算子](#3-1比較演算子)
[3-2.論理演算子](#3-2論理演算子)
[3-3.演算子の優先順位](#3-3演算子の優先順位)
[3-4.ソート(order by句)](#3-4ソートorder-by句)
[4.単一行関数（SQL関数の概要と単一行関数の基本）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4単一行関数sql関数の概要と単一行関数の基本)
[4-1.SQL関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4-1sql関数)
[4-2.単一関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4-2単一関数)
[4-2-1.文字関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4-2-1文字関数)
[4-2-2.数値関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4-2-2数値関数)
[4-2-3.日付関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#4-2-3日付関数)
[5.単一行関数（変換関数・汎用関数と条件式の指定）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#5単一行関数変換関数汎用関数と条件式の指定)
[5-1.変換関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#5-1変換関数)
[5-1-1.to_char(日付値)](https://qiita.com/drafts/2f8f2fdde810d2405a04/edit#5-1-1to_char日付値)
[5-1-2.to_char(数値)](https://qiita.com/drafts/2f8f2fdde810d2405a04/edit#5-1-2to_char数値)
[5-1-3.to_date](https://qiita.com/drafts/2f8f2fdde810d2405a04/edit#5-1-3to_date)
[5-2.汎用関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#5-2汎用関数)
[6.グループ関数（グループ関数とデータの集計）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#6グループ関数グループ関数とデータの集計)
[6-1.グループ関数](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#6-1グループ関数)
[6-2.group by句とhaving句](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#6-2group-by句とhaving句)
[7.結合（複数表からのデータの取り出し)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7結合複数表からのデータの取り出し)
[7-1.等価結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-1等価結合)
[7-1-1.自然結合(natural join句)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-1-1自然結合natural-join句)
[7-1-2.using句](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-1-2using句)
[7-1-3.on句](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-1-3on句)
[7-1-4.3つ以上の表の結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-1-43つ以上の表の結合)
[7-2.非等価結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-2非等価結合)
[7-3.自己結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-3自己結合)
[7-4.外部結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-4外部結合)
[7-5.クロス結合](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#7-5クロス結合)
[8.副問合せ（副問合せによる問い合わせの解決方法）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#8副問合せ副問合せによる問い合わせの解決方法)
[9.集合演算子（集合演算子の種類と使用方法）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#9集合演算子集合演算子の種類と使用方法)
[10.データ操作(DML)とトランザクション制御](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10データ操作dmlとトランザクション制御)
[10-1.DML(insert/update/delete)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10-1dmlinsertupdatedelete)
[10-1-1.insert(行の挿入)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10-1-1insert行の挿入)
[10-1-2.update(行の更新)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10-1-2update行の更新)
[10-1-3.delete(行の削除)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10-1-3delete行の削除)
[10-2.トランザクション制御](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#10-2トランザクション制御)
[11.DDL文を使用した表の作成と管理](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11ddl文を使用した表の作成と管理)
[11-1.create（表の作成）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-1create表の作成)
[11-2.alter（表の構造変更）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-2alter表の構造変更)
[11-3.drop（表の削除）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-3drop表の削除)
[11-4.データ型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4データ型)
[11-4-1.文字型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-1文字型)
[11-4-2.数値型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-2数値型)
[11-4-3.日付型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-3日付型)
[11-4-4.バイナリ型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-4バイナリ型)
[11-4-5.ROWID型](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-5rowid型)
[11-4-6.その他のデータ型（日付、時刻、期間を格納）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-4-6その他のデータ型日付時刻期間を格納)
[11-5.制約](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5制約)
[11-5-1.not null制約](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5-1not-null制約)
[11-5-2.unique制約(一意キー)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5-2unique制約一意キー)
[11-5-3.primary key制約(主キー)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5-3primary-key制約主キー)
[11-5-4.foreign key制約(外部キー。参照整合性制約)](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5-4foreign-key制約外部キー参照整合性制約)
[11-5-5.check制約](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#11-5-5check制約)
[12.表以外のスキーマオブジェクトの作成](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#12表以外のスキーマオブジェクトの作成)
[12-1.ビュー](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#12-1ビュー)
[12-2.順序（シーケンス）](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#12-2順序シーケンス)
[12-3.索引（インデックス）](#12-3索引インデックス)
[12-4.シノニム](https://qiita.com/ghogho-seki/items/2f8f2fdde810d2405a04#12-4シノニム)

# 1.基本（リレーショナルデータベースとSQL）

|DML(データ操作)|DDL(データ定義)|DCL(データ制御|トランザクション制御|
|:--|:--|:--|:--|
|select|create|grant|commit|
|insert|alter|revoke|rollback|
|update|drop||savepoint|
|delete|rename|||
|merge|truncate|||
||comment|||

- 主キー
    - 行を一意に識別するための列 or列の組み合わせ

- 外部キー
    - 同じ表 or 他の表の主キー(or 一意キー)を参照する列(or 列の組み合わせ) 

|主キー|外部キー|
|:--|:--|
|重複した値は格納できない||
|NULLを含めれない|NULLを含めれる|

# 2.select文（select文を使用したデータの取得)

- 算術式の優先順位
    - 優先順位は**()**で明示的に指定可能
    - NULLを含む算術式は計算結果も**NULL**

|優先順位|算術式|
|:--|:--|
|1|*(乗算) or /(除算)|
|2|+(加算)  or -(減算)|

|射影|選択|結合|
|:--|:--|:--|
|特例**列**のみ取り出す|特例**行**のみ取り出す|複数表を関連付けてデータを取り出す|

- 列別名
    - where句では列別名を使用した条件は指定できない
    - 計算式に列別名は使用できない

パターン1

```sql
select 列名 列別名,算術式 列別名
```
パターン2

```sql
select 列名 as 列別名,算術式 as 列別名
```

例

```sql
selece sal*12 as "Annual Salary"
→Annual Salary
```

- 連結演算子

```sql
列名 || 列名
```

例

```sql
select ename||'さんの入社日'|
→佐藤さんの入社日
```

|""(ダブルコーテーション)で囲む場合|''(シングルコーテーション)で囲む場合|
|:--|:--|
|列別名に**スペース**、**特殊文字（#、$など）**を使用する場合|文字式の中に**文字リテラル**、**日付リテラル**を指定する場合|
|大文字・小文字を区別する場合||

- q(代替引用符演算子)
    - 任意のシングルバイト文字 or ダブルバイト文字
    - []、{}、()、<>の組み合わせ

```sql
Q'引用符デリミタ ... 引用符デリミタ'
```

例1

```sql
select yomi || q'?'s Salary:?'||sal AS "Monthly Salary"

→
Monthly Salary
--------------
sato's Salary:50000
```
例2

```sql
select yomi || q'['s Salary:]'||sal AS "Monthly Salary"

→
Monthly Salary
--------------
sato's Salary:50000
```

- distinct句
    - 重複行の排除
    - selectキーワードの直前に指定
    - 指定した列値の組み合わせで一意になる行のみ取り出す

```sql
select distinct 列名[,列名...]
```

# 3.データの制限及びソート
## 3-1.比較演算子
|比較演算子|説明
|:--|:--|
|=|等しい|
|>|大きい|
|>=|以上|
|<|小さい|
|<=|以下|
|<>、!=、^=|等しくない|
|between A and B<br>(xx >= A, xx <= B)|A以上B以下|
|not between A and B<br>（xx < A, xx > B）|Aより小さい、Bよりも大きい|
|in(値1[,値2...])|値のリストのいずれかに一致|
|not in(値1[,値2...])|値のリストのすべてと等しくない|
|like '文字パターン'|文字パターン一致する場合TRUE|
|not like '文字パターン'|文字パターン一致しない場合TRUE|
|is null|値がNULLの場合にTRUE|
|is not null|値がNULL以外の場合TRUE|

- like演算子

|ワイルドカード|説明|
|:--|:--|
|%|**0文字以上**の任意の文字列と一致|
|_|任意の**1文字**と一致|

- escapeオプション
    - エスケープ文字
        - 任意の1バイトの文字（¥、$、#、aなど）
        - 文字パターンに含まれるエスケープ文字の直後のワイルドカードは**文字リテラル**として扱われる

```sql
where 列名 like '文字パターン' escape 'エスケープ文字'
```

## 3-2.論理演算子

|論理演算子|説明|
|:--|:--|
|and|A かつ B(A、B両方TRUEならTRUE)|
|or|A または B(A、Bどちらか一方がTRUEならTRUE)|
|not|後ろに指定された条件がFALSEならTURE|

```sql
where 列1 = 値1 or 列1 = 値2 or 列1 = 値3
```
↓ 書き換え可能

```sql
where 列1 in(値1,値2,値3)
```

## 3-3.演算子の優先順位

|優先順位|演算子|
|:--|:--|
|1|算術演算子（*、/、+、-）|
|2|連結演算子|
|3|比較演算子（=、>、>=、<、<=）|
|4|in演算子、like演算子、is null演算子|
|5|between演算子|
|6|等しくない（<>、!=、^=）|
|7|not演算子|
|8|and演算子|
|9|or演算子|


## 3-4.ソート(order by句)
- order by句
    - select文の**最後**に指定
    - デフォルト(昇順)のソート順序
    - 計算式を使用できる
    - **列別名**を指定可能
    - order by句とgroup by句を併用する場合
        - 以下のみorder by句には以下のみ指定可能
            - group by句で指定した列
            - グループ関数
        - 他の列を指定するとエラー

|データ型|内容|
|:--|:--|
|数値|小さい数値　→　大きい数値|
|日付値|古い日付　→　新しい日付|
|文字列|アルファベット順、続いて50音順(文字コード順)|
|NULL|もっとも大きい値として扱われる|

- NULLのソート順の制御

```sql
order by 列名 [nulls first | nulls last]
```

|キーワード|説明|
|:--|:--|
|nulls first|NULLを最初に取り出す|
|nulls last|NULLを最後に取り出す|

# 4.単一行関数（SQL関数の概要と単一行関数の基本）
## 4-1.SQL関数

- 単一行関数
    - 1件の入力データ毎に処理を行い、入力データ毎に1件の結果を戻す
    - ネスト制限なし
    - 以下で使用できる
        - select句
        - where句
        - order by句
    - sysdate関数のように、**引数を受け入れない**関数もある
    - 受け取った引数とは異なるデータ型の値を返すこともある

- グループ関数
    - 複数行の入力データをグループ化し、集計処理を行った結果を1つだけ戻す
    - グループ関数を含む条件式はhaving句に指定する必要がある
    - where句に指定するとエラー

## 4-2.単一関数
### 4-2-1.文字関数
- 大文字・小文字変換関数

|文字関数|記述|説明|例|
|:--|:--|:--|:--|
|upper|upper(文字列)|文字列を**大文字**に変換|(test characters)　→　TEST CHARACTERS|
|lower|lower(文字列)|文字列を**小文字**に変換|(TEST CHARACTERS) →　test characters|
|initcap|initcap(文字列)|文字列の**各単語の先頭を大文字**、**それ以降を小文字**|(test characters)　→　Test Characters|

- 文字操作関数

|文字関数|記述|説明|例|
|:--|:--|:--|:--|
|concat|concat(文字列1,文字列2)|引数として受け入れた**2つの文字列を結合**し戻す|('Oracle','Server') → Oracle Server|
|substr|substr(文字列, m [,n])|引数として受け入れた文字列の**m番目の文字からn文字の文字列**を戻す|('Oracle Server',2,3) → rac <br> ('Oracle Server',2) → racle Server|
|length|length(文字列)|引数として受け入れた文字列の**文字数**を戻す|('Oracle Server') → 13 <br> ('あいうえお') → 5|
|instr|instr(文字列1,文字列2 [,m][,n])|**指定した文字パターンが現れる位置**を戻す(m番目から文字列2を検索し、n回目に一致した文字位置を戻す)|('Oracle Server','er',1,2) → 12 <br> ('Oracle Server','er') → 9|
|lpad/rpad|lpad/rpad(文字列, n , '埋込文字')|引数を受け入れた文字列がn文字になるように**埋め込み文字**を埋め込んで戻す|lpad(yomi,10,'*')　→******yomi <br> rpad(yomi,10,'*') → yomi******|
|trim|trim([leading │ trailing │ both] [削除文字] from 文字列) or trim(文字列)|引数として受け入れた文字列の左右(前後)にある文字の文字列(削除文字)を**取り除いて**戻す|trim(leading 'O' from 'Oracle Server') → racle Server|
|replace|replace(文字列, 変更前文字列 [,変更後文字列])|引数として受け入れた文字列のうち、任意の文字列(変更前文字)を、別の文字列(変更後文字)に**置き換える**|('Oracle Server','Server','Master') → Oracle Master <br> ('Oracle Server',' Server'　→　Oracle)|

※trim関数の削除位置の指定

|引数|説明|
|:--|:--|
|leading|文字列の**先頭**にある削除文字を削除|
|trailing|文字列の**末尾**にある削除文字を削除|
|both|文字列の**先頭および末尾**にある削除文字を削除(デフォルト値)|

### 4-2-2.数値関数

|数値関数|記述|説明|例|
|:--|:--|:--|:--|
|round|round(数値 [,n])|小数点n桁に**四捨五入**|(12345.678,1) → 12345.7 <br> (12345.678,0) → 12346 <br> (12345.678) → 12346 <br> (12345.678,-1) → 12350| 
|trunc|trunc(数値 [,n])|小数点n桁に**切り捨て**|(12345.678,1) → 12345.6 <br> (12345.678,0) → 12345 <br> (12345.678) → 12345 <br> (12345.678,-1) → 12340| 
|mod|mod(n,m)|n を m で割ったあまり|(10,3) → 1|

### 4-2-3.日付関数

|日付値の計算|返す値|
|:--|:--|
|日付 + 数値|日数|
|日付 - 数値|日数|
|日付 + 数値/24|時間数|
|日付 - 数値/24|時間数|
|日付 - 日付|日数(1日以下の値は少数として返される)|
|日付 + 日付|**エラー**(日付値同士の加算はできない)|

|実行環境|日付表示書式|
|:--|:--|
|日本語環境|RR-MM-DD(年-月-日)|
|英語環境|DD-MON-RR(日-月-年)|

```sql
alter session set nls_date_format = '表示書式';
(例)alter session set nls_date_format = 'DD-MON-RR';
```

```sql
alter session set nls_date_language = '言語';
(例)alter session set nls_date_language = 'AMERICAN';
```

|日付関数|記述|説明|例|
|:--|:--|:--|:--|
|sysdate|sysdate|現在の日付(日時)を戻す|sysdate → 11-05-20(DBサーバの現在の日付)|
|months_between|months_between(日付1,日付2)|2つの日付感の**月数**を戻す|(sysdate,hiredate) → 現在の日時 - 入社時の日時 = 122.864116|
|add_months|add_months(日付,n)|指定した日付の**nか月後**の日付を戻す|(sysdate) → 11-05-20 <br> (sysdate,3) → 11-08-20(3か月後) <br> (sysdate,-1) → 11-04-20(1か月前)|
|next_day|next_day(日付.'曜日')|指定した**日付**の翌日以降に指定した**曜日**になる最初の日付を戻す|('11-05-23','日曜日') → 11-05-29(2011.05.24以降で最初の日曜日)|
|last_day|last_day(日付)|指定した日付を含む月の**最終日**の日付を戻す|('08-02-01') → 08-02-29|
|round|round(日付,[, '書式'])|指定された日付値を*四捨五入**|(sysdate) → 11-05-20 <br> (sysdate,'YEAR') → 11-01-01 <br> (sysdate,'MONTH') → 11-06-01|
|trunc|trunc(日付,[, '書式'])|指定された日付値を*切り捨て**|(sysdate) → 11-05-20 <br> (sysdate,'YEAR') → 11-01-01 <br> (sysdate,'MONTH') → 11-05-01|

- sysdate関数
    - 次の場合エラーでない(例)

```sql
select sysdate - sysdate - 7 from dual;
```
「日付-日付-数値」の順で処理される。「日付-日付」は日付間の**数値**を返す。
「sysdate-sysdate = 0」→「0-7 = -7」で**-7**が表示される。

```sql
select sysdate - (sysdate - 7) from dual;
```
「日付-(日付-数値)」となる。
「日付-数値」は指定した数値の日数分だけ前の日時を返す。
この場合は、7日前の日時が返されるので「sysdate-7日前」の日時で*:「日付-日付」**の計算が行われ**7**が表示される

```sql
select sysdate - 7 from dual;
```
「日付-数値」で**7日前**の日時が表示される

次の場合はエラーが発生する

```sql
select sysdate + (sysdate - 7) from dual;
```
「sysdate + 7日前」の日時は「日付+日付」で計算できない



- next_day関数

|実行環境|曜日の指定形式|
|:--|:--|
|日本語環境|日曜日、月曜日、火曜日、水曜日、木曜日、金曜日、土曜日（or 日、月、火・・・）|
|英語環境|SUN、MON、TUE、WED、THU、FRI、STA(大文字、小文字は区別されない)|

- round関数

|指定できる書式|指定した日付|戻す値|
|:--|:--|:--|
|YEAR|6月30日以前|当年の1月1日午前0時|
|YEAR|7月1日以降|翌年の1月1日午前0時|
|MONTH|15日以前|当月の1日午前0時|
|MONTH|16日以降|翌月の1日午前0時|
|DD|正午以前|当日の午前０時|
|DD|正午以降|翌日の午前0時|

- trunc関数

|指定できる書式|指定した日付|
|:--|:--|
|YEAR|当年の1月1日午前0時を戻す|
|MONTH|当月の1日午前0時を戻す|
|DD|当日の午前0時を戻す(デフォルト値)|

# 5.単一行関数（変換関数・汎用関数と条件式の指定）
## 5-1.変換関数
　　日付値(date型)
　　↓　　　　　　↑　
to_char関数　   to_date関数
　　↓　　　　　　↑　
　文字値(char型/varchar2型)
　　↓　　　　　　↑　
to_number関数　 to_char関数
　　↓　　　　　　↑　
　　数値(number型) 

|関数|記述|説明|
|:--|:--|:--|
|to_char(日付値)|to_char(**日付**[,'日付書式'[,NLSパラメータ]]|日付書式を使用し**日付値**を**文字値**に変換|
|to_char(数値)|to_char(**数値**[,'数値書式'][,NLSパラメータ])|数値書式を使用し**数値**を文字値**に変換|
|to_date|to_date(**文字列**[,'日付書式'][,NLSパラメータ]|文字値を**日付値**に変換|
|to_number|to_number(**文字列**[,'数値書式'][,NLSパラメータ]|文字値を**数値**に変換

### 5-1-1.to_char(日付値)

|日付書式の要素|説明|
|:--|:--|
|SCC or CC|**世紀**。S を指定すると紀元前の日付の先頭に**「-」**がつく|
|SYYY or YYYY|**年**。。S を指定すると紀元前の日付の先頭に**「-」**がつく|
|YYY or YY、Y|年の下3桁、2桁、1桁|
|IYYY or IYY、IY、I|ISO基準に基づく4桁、3桁、2桁、1桁の年|
|SYEAR or YEAR|スペル表記による年|
|RR|年の下2桁。|
|Q|年の四半期|
|MM|**月**。2桁の値|
|MONTH|空白が埋め込まれた9文字の長さの**月の名前**。日本語環境では「1月」、「2月」など|
|MON|**月の名前**。3文字の省略形。日本語環境では「1月」、「2月」など|
|RM|ローマ数字で表した月|
|WW or W|年 or 月における週|
|DDD or DD、D|年または月、週における日|
|DAY|空白が埋め込まれた9文字の長さの**曜日**。日本語環境では「日曜日」、「月曜日」など|
|DY|**曜日**。3文字省略形。日本語環境では「日」、「月」など|
|IW|ISO基準に基づく、年における週（1〜53）|
|AM or PM|AM pr PMを示す要素。日本語環境では「午前」 or 「午後」|
|HH or HH12、HH24| 時間、時間（1〜12）、時間（0〜23）|
|MI|分（0〜59）|
|SS|秒（0〜59）|
|SSSSS|午前0時からの経過秒数（0〜86399）|
|半角記号（/,.など）|半角記号はそのまま結果に表示される|
|"of the"|ダブルコーテーションで囲まれた文字列はそのまま結果に表示される|
|FM|埋め込みモードの有効／無効を切り替える(デフォルト有効)。埋込モードを無効にすると「数値の先行0」や「文字値の前後に含まれるスペース」が取り除かれて表示される|

|数値で表示される日付書式に使用できる接尾辞|説明|
|:--|:--|
|TH|順序表記（例：DDTH →　4TH）|
|SP|スペル表記（例：DDSP → FOUR）|
|SPTH or THSP|順序表記 + スペル表記（例：DDSPTH → FOURTH）|

- 例1
    - 'YYYY/MM/DD' → 1999/06/21、1994/06/07など
    - 'YYYY/MM/D'  → 1999/6/21、1994/6/7など
    - 'YYYY/M/D'   → 「M」という書式はないのでエラー

- 例2
    - 2009年10月17日を「Seventeenth of October,Two Thousand Nine」という形式で表示したい

```sql
select
 to_char(
          to_date('17-oct-2009'),
          'fmDdthsp "of" Month,Year'
        )
from dual;
```

これだと

```sql
select
 to_char(
          to_date('17-oct-2009'),
          'fmDdth "of" Month,Year'
        )
from dual;
```
 →**「sp」**がないと「17th of October,Two Thousand Nine」と表示される

※補足
　「spth」と「thsp」は同じ意味。
　　DD書式をスペル表記するときは、大文字・小文字が区別される。
　　**DD**は全て大文字、**Dd**は先頭のみ大文字、**dd**は全て小文字
   **fm(埋込モード)**を指定すると、前後の空白を削除したり先行ゼロを抑制できる。

- NG

```sql
to_char('17-oct-2009','fmDdspth "of" Mopnth,Year')
```
 →「to_char(**日付**,['日付書式'])」の形式でないのでエラー


### 5-1-2.to_char(数値)

- 指定した桁数が実際のデータの桁数よりも少ない場合は**#**が表示される

|数値書式の要素|説明|例|結果|
|:--|:--|:--|:--|
|9|数値のいち（9の数で表示桁数が決まる）|99999|1234|
|0|先行0を表示|099999|001234|
|$|ドル記号の表示|$999999|$1234|
|L|ローカル通貨記号の表示（日本語環境だと**¥**）|L999999|¥1234|
|D|指定した位置に小数点を表示|999D999|1.234|
|.|指定された位置に小数点を表示|999.999|1.234|
|G|指定された位置に桁区切りを表示|999G999|1,234|
|,|指定された位置にカンマを表示|999,999|1,234|
|MI|右にマイナス記号を表示（負の値の場合）|999999MI|1234-|
|PR|負の値を<>で囲む|999999PR|<1234>|
|EEEE|科学表記法で表示|99.999EEEE|1,234E+03|
|V|10のn乗を乗算する（nはVの後ろの9の数）|9999V99|123400|
|S|**+** or **-**を表示|S999999|+1234 or -1234|

### 5-1-3.to_date

|YY要素とRR要素|説明|
|:--|:--|
|YY|受け入れた値（年の下2桁）を、**常に現在の世紀**として扱う|
|RR|受け入れた値（年の下2桁）を、**現在の年に近い世紀**として扱う|

- YY要素が表す値

|現在の年（下2桁）|受け入れた値（年の下2桁：0〜49年）|受け入れた値（年の下2桁：50〜99年）|
|:--|:--|:--|
|0〜49年|現在の世紀|現在の世紀|
|50〜99年|現在の世紀|現在の世紀|

- RR要素が表す値

|現在の年（下2桁）|受け入れた値（年の下2桁：0〜49年）|受け入れた値（年の下2桁：50〜99年）|
|:--|:--|:--|
|0〜49年|現在の世紀|現在の1つ前の世紀|
|50〜99年|現在の1つ前の世紀|現在の世紀|

- 日付書式の具体例

|現在の年|受け入れた値|RR要素の場合|YY要素の場合|
|:--|:--|:--|:--|
|1995|95-10-10|1995-10-10|1995-10-10|
|1995|20-10-10|2020-10-10|1920-10-10|
|2010|95-10-10|1995-10-10|2095-10-10|
|2010|20-10-10|2020-10-10|2020-10-10

## 5-2.汎用関数

|関数|記述|説明|例|備考|
|:--|:--|:--|:--|:--|
|nlv|nlv(式1,式2)|式1がNULL以外 → **式1** <br><br> 式1がNULL →**式2**を返す|nvl(comm,0)<br><br>comm列がNULL以外なら**comm列の値**<br>comm列がNULLなら**0**を返す|戻り値のデータ型は**式1**の**データ型と同じ**（データ変換できない場合はエラー）|
|nlv2|nlv2(式1,式2,式3)|式1がNULL以外 → **式2** <br><br> 式1がNULL → **式3**を返す|nvl2(comm,sal+comm,sal)<br><br>comm列がNULL以外なら**sal+commの値**<br>comm列がNULLなら**sal列の値**を返す|戻り値のデータ型は常に**式2**のデータ型と同じ（データ変換できない場合はエラー）|
|nullif|nullif(式1,式2)|式1 = 式2　→ NULL <br><br> 式1 ≠ 式2 →NULL以外を返す|nullif(comm,sal/10)<br><br>comm列 = sal/10なら**NULL**<br>comm列 ≠ sal/10なら**sal/10の値**を返す|**式1**にはリテラルの**NULL値以外**を指定|
|coalesce|coalesce(式1,式2[,式n])|最初にみつかった**NULL以外の値**を返す（全部NULLなら**NULL**を返す）|coalesce(to_char(comm),to_char(mgr),ename)|式はすべて同じデータ型|

- comm列を0に置き換える系
    - nvl(comm,0)
        - comm列がNULLなら「0」を返す
        - comm列がNULL以外ならcomm列の値を返す
    - nvl2(comm,comm,0)
        - comm列がNULLなら「0」を返す
        - comm列がNULL以外ならcomm列の値を返す
    - coalesce(comm,0)
        - comm列がNULLなら「0」を返す
        - comm列がNULL以外ならcomm列の値を返す
    - ちなみに
        - nullif(comm,0)
            - 「comm列 = 0」ならNULLを返す
            - 「comm列 ≠ 0」ならNULL以外を返す

- 条件式
    - case式
        - SQL文にIF-THEN-ELSEロジックを実装できる
        - ANSI SQLに準拠
    - decode関数
        - SQL文にIF-THEN-ELSEロジックを実装できる
        - Oracle固有の関数

- case式
    - 式 = 条件式1 なら戻り値1を返す。
    - 式 ≠ 条件式1 なら条件式nを評価する。
    - 式 ≠ 条件式nならデフォルトの戻り値を返す（else句が省略されている場合は、NULLを返す）。

```sql
case 式 when 条件式1 then 戻り値1
       [when 条件式n thwn 戻り値n]
       [else デフォルトの戻り値]
end
```

(例)

```sql
case deptno when 10 then sal*1,1
            when 20 then sal*1,2
            else sal*1.5
end new_sal
```
deptno列が10なら**sal*1,1**、20なら**sal*1,2**、それ以外なら **sal*1.5** を返す


- decode関数
    - 式 = 条件式1 なら戻り値1を返す。
    - 式 ≠ 条件式1 なら条件式nを評価する。
    - 式 ≠ 条件式nならデフォルトの戻り値を返す（else句が省略されている場合は、NULLを返す）。

```sql
decode(式,条件式1,戻り値1
        [,条件式n,戻り値n]
        [,デフォルトの戻り値])
```

# 6.グループ関数（グループ関数とデータの集計）
## 6-1.グループ関数
- グループ関数（複数行関数、集計関数ともいう）
    - 複数行の入力データをグループ化し、集計処理を行った結果を1つだけ戻す(**グループ毎に集計した結果**)
    - **where句にグループ関数は使用できない**
        - エラーとなる
    - 使用できる箇所は以下
        - select句
        - order by句
        - having句

```sql
関数名([distinct │ all] {列名 │ 式})
```

|グループ関数に指定できるオプション|説明|
|:--|:--|
|distinct|重複した値は1回だけ処理する|
|all(デフォルト値)|重複値を含む全ての値を処理する|

|グループ関数|記述|説明|備考|
|:--|:--|:--|:--|
|count|count({* │ [distinct │ all] 式}|件数|引数には**数値型、文字型、日付型**を戻す式 or 列を指定|
|max|max([distinct│ all]式) |最大値|引数には**数値型、文字型、日付型**を戻す式 or 列を指定|
|min|min([distinct│ all]式) |最小値|引数には**数値型、文字型、日付型**を戻す式 or 列を指定|
|avg|avg([distinct│ all]式) |平均値|引数には**数値型**を戻す式 or 列を指定|
|sum|sum([distinct│ all]式) |合計値|引数には**数値型**を戻す式 or 列を指定|

-例

```sql
max(sysdate - hire_date)
```
この場合はエラーとならない。「日付 - 日付」で**日数**を返すため。
↓これはエラー

```sql

avg(hire_date),max(hide_date)
```

- count関数
    - NULLの扱い
        - 「*」 以外の場合はNULLを無視して集計処理を行う
        - nvl、nvl2、coalsceと組み合わせれば、NULLを「0」に置き換え集計可能

|引数|データ件数に含まれるデータ|
|:--|:--|
|*|重複値や**NULL**も含む全てのデータの件数|
|式 or all|重複値をそれぞれ1件としてカウントしたデータの件数(NULLは含まない)。<br>オプションを省略した場合はデフォルトで「ALL」|
|distinct|重複値を1回だけカウントしたデータの件数(NULLは含まない)|

- Oracleのグループ関数（上記以外）
    - stddev関数
        - 標準偏差を求める
    - variance関数
        - 分散を求める

## 6-2.group by句とhaving句
- group by句
    - 行をグループ化
    - 1つ以上の列を指定する必要がある
    - 指定箇所
        - 必ず**where句の後ろ、かつorder by句の前**に指定
        - select句にの選択リストには以下のみ指定可能
            - group by 句で指定した列
            - グループ関数
        - **order by 句**と併用する場合、order by句に指定できるのは以下のみ
            - group by句で指定した列
            - グループ関数
    - **列別名**は指定不可
    - グループ関数
        - ネストは**2レベル**まで
            - 3レベル以上ネストするとエラー
        - **where句の条件**に指定できない
        - NULLを無視して集計処理を行う
    - 副問合せは指定できない


```sql
select 列名,グループ関数(列名)
from   表名
[where 条件]
[group by グループ化で使用する列のリスト]
[order by ソートで使用する列のリスト]
```    

```sql
group by 列名[,列名...]
```

- having句
    - グループ関数を**条件**に指定したい場合に使用する
    - 取り出すグループを制限できる
        - 指定した条件の評価が**TRUE**のグループだけ取り出す
    - 必ず**where句の後ろ、かつorder by句の前**に指定
    - group by句、having句は順不同
    - 条件には**group by 句で指定した列**のみ指定可能
    - 条件には以下を指定可能
        - 比較演算子（比較条件）
        - 定数（リテラル）
        - グループ関数
    - grouo by句が指定されず、having句のみ指定した場合
        - 選択された行全体が1つのグループとして処理される
    - grouo by句に指定した列を使用した条件に限り、having句に指定可能

```sql
select 列名,グループ関数(列名)
from   表名
[where 条件]
[group by グループ化で使用する列のリスト]
[having グループに対する条件]
[order by ソートで使用する列のリスト]
```

||取り出すグループの制御|
|:--|:--|
|1|where句がある場合、where句の条件によってグループ化する対象行が制御される|
|2|group by句で行がグループ化|
|3|グループ関数を適用|
|4|having句で指定された条件を満たすグループが取り出される|

- これはどちらも同じ結果を返す

```sql
select department_id,avg(e.salary)
from   employees e join departments d
using(department_id)
group by department_id
having count(*) > 2
and    department_id < 100 ★これ
order by 1;
```

```sql
select department_id,avg(e.salary)
from   employees e join departments d
using(department_id)
where department_id < 100 ★これ
group by department_id
having count(*) > 2
order by 1;
```


# 7.結合（複数表からのデータの取り出し)

|結合|キーワード|
|:--|:--|
|等価結合(自然結合)|natural join|
|等価結合(using句)|join/using|
|等価結合(on句)|join/on|
|非等価結合|join/on|
|自己結合|join/on|
|外部結合(左側)|left [outer] join/on|
|外部結合(右側)|right [outer] join/on|
|外部結合(完全)|full [outer] join/on|
|クロス結合|cross join|

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1
{
  natural join 表名2 │
  join 表名2 using(列名) │
  join 表名2 on 結合条件 │
  {left │ rigth │ full} [outer] join 表名2 on 結合条件 │
　cross join 表名2
}
[where 結合条件以外の条件];
```

- 表接頭辞を使用した列名の就職

```sql
表名.列名
```

- 表名の指定
    - 30文字以下
    - 表別名は、表別名を指定したsql文内でのみ有効
    - from句で**表別名**を指定した場合、そのSQL文全体で**表別名**を使用する必要がある
        - 元の表名は使用できない

```sql
from 表名 表別名
```

## 7-1.等価結合
### 7-1-1.自然結合(natural join句)
- natural join句
    - 結合する**2つの表に共通して存在する列**に基づいて等価結合をおこなう
        - **同じ列名かつ同じデータ型の列**
    - 明示的に結合条件を指定する必要なし
        - 結合列が自動的に判断されるため
    - 共通して存在する列が複数ある場合
        - **全ての列が結合条件として使用される**(それらの全ての値が等しいデータのみ取り出される)
    - データ型の異なる同名の列があると**エラー**
    - 結合列に表接頭辞は使用できない（エラー）
    - natural join句を使用して**3つ以上の表**を結合できる

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 natural join 表名2
[where 結合条件以外の条件];
```

### 7-1-2.using句
- using句
    - 結合列を明示的に指定
    - **2つの表にある同じ名前の列**に基づいて等価結合をおこなう
    - **()**内に結合列を指定
    - 結合列に**表接頭辞**をしようするとエラー
    - natural join句との併用は不可
    - using句を使用して**3つ以上の表**を結合できる
    - 利用例
        - 結合列を明示的に指定しSQL文をわかりやすくしたい場合
        - 結合する2つの表に共通して存在する列が複数ある場合、その**いずれかを結合列として使用したい**場合
        - 列名が同じで**データ型が異なる**結合列を使用する場合

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 join 表名2
using(列名[,列名...])
[where 結合条件以外の条件];
```

### 7-1-3.on句
- on句
    - 結合列を明示的に指定
    - **異なる名前の列**を使用して結合することもできる
    - 表接頭辞を使用して列名を修飾する必要がある
    - on句を使用して**3つ以上の表**を結合できる

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 join 表名2
on [表名1.]列名 = [表名2.]列名
[where 結合条件以外の条件];
```

### 7-1-4.3つ以上の表の結合
```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1
join   表名2 on [表名.]列名 = [表名.]列名
join   表名3 on [表名.]列名 = [表名.]列名
[join   表名3 on [表名.]列名 = [表名.]列名...]
[where 結合条件以外の条件];
```

## 7-2.非等価結合
- 非等価結合
    - **=(等価演算子)**以外の演算子を使って、条件を満たすデータを取り出す結合
    - 結合条件に使う演算子
        - <、>、<=、>=、betweenなど

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 join 表名2
on 結合条件;
```

## 7-3.自己結合
-  自己結合
    -  同一の表に2つの表別名を指定することで1つの表を2つの表に見立ててデータを取り出す
    -  自然結合（natural join句）やusing句を使った結合では使えない

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 表別名1 join 表名2 表別名2
on [表別名1.]列名 = [表別名2.]列名;
```

## 7-4.外部結合
- 外部結合
    - 条件を満たしていないデータも取り出す結合
    - using句も使える

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 { left │ rigth │ full} [outer] join 表名2
on 結合条件;
```

## 7-5.クロス結合
- クロス結合
    - 結合する表に格納されているデータの全ての組み合わせ（直積）

```sql
select [表名.]列名 [,[表名.]列名...]
from   表名1 cross join 表名2;
```

# 8.副問合せ（副問合せによる問い合わせの解決方法）
- 副問合せ
    - 副問合せは**()**で囲む
    - 主問い合わせと副問合せのfrom句に**異なる表**を指定可能
    - 1つの主問い合わせに複数の副問合せを指定可能
    - 以下で指定可能
        - select句
        - where句
        - from句
        - having句
        - DML文
            - insert文
            - update文
            - set句
            - update句
            - delete文など
    - 以下は指定**不可**
        - group by句
    - 副問合せの中でhaving句やgroup by句は使用できる
    - 副問合せの実行結果が0件なら、主問い合わせに**NULL**が戻されるため、実行結果も0件(エラーにはならない)
        - 副問合せの条件式に合うデータがない場合
        - 主問い合わせに戻す値（副問合せのselect句に指定されている列値）がNULLの場合
    - where句の副問合せは**最大255レベル**までネスト可能
    - 比較演算子のどちらでも使用可能

```sql
select 列名[,列名...]
from   表名
where  列名 比較演算子 (select 列名 from 表名
                      [where 条件]);
```

- 副問合せの種類

|分類|説明|
|:--|:--|
|単一行副問合せ|データを1件だけ戻す副問合せ。<br>単一行演算子（>、<、=、>=、<=、<>、!=、^=）を使用する|
|複数行副問合せ|複数件のデータを戻す副問合せ。<br>複数行演算子（in、any、all）を使用する|

- 複数行演算子
    - in、any、all演算子ともにnot演算子は使える

|複数行演算子|説明|
|:--|:--|
|in(値のリスト)|リスト内のいずれかと等しければTRUE|
|単一行演算子 + any(値のリスト)|リスト内の**いずれかの値**が条件を満たすとTRUE。<br>(例)=any、>any|
|単一行演算子 + all(値のリスト)|リスト内の**全ての値**が条件を満たすとTRUE。<br>(例)=all、>all|


- any演算子
    - 「in(値のリスト)」=「=any(値のリスト)」
        - いずれかと等しければTRUE 
    - >any(値のリスト)
        - リスト内の値の**いずれか1つよりも大きい**
        - リスト内の**最小値**よりも**大きい**場合
    - <any(値のリスト)
        - リスト内の値の**いずれか1つよりも小さい**
        - リスト内の**最大値**よりも**小さい**場合

- 「>any」（最小値よりも大きい）の書き換え
    - 最小値（min）よりも大きい（>）

```sql
select empno,ename,sal,deptno
from   employees
where  sal >any (select avg(sal) from employees
                 group by deptno);
```
↓書き換え可能

```sql
select empno,ename,sal,deptno
from   employees
where  sal > (select min(avg(sal)) from employees
                 group by deptno);
```
 →平均給与がもっとも低い部門の平均給与よりも、給与が高い社員

- 「<any」（最大値よりも小さい）の書き換え
    - 最大値（max）よりも小さい（<）

```sql
select empno,ename,sal,deptno
from   employees
where  sal <any (select avg(sal) from employees
                 group by deptno);
```
↓書き換え可能

```sql
select empno,ename,sal,deptno
from   employees
where  sal < (select max(avg(sal)) from employees
                 group by deptno);
```

- all演算子
    - <all(値のリスト)
        - 比較対象の列値がリスト内の**全ての値**よりも小さい
        - **最小値**よりも**小さい**
    - >all(値のリスト)
        - 比較対象の列値がリスト内の**全ての値**よりも大きい
        - **最大値**よりも**大きい**

- 「>all」（最大値よりも大きい）の書き換え
    - 最大値（max）よりも大きい（>）

```sql
select empno,ename,sal,deptno
from   employees
where  sal >all (select avg(sal) from employees
                 group by deptno);
```
↓書き換え可能

```sql
select empno,ename,sal,deptno
from   employees
where  sal > (select max(avg(sal)) from employees
                 group by deptno);
```

- 「<all」（最小値よりも小さい）の書き換え
    - 最小値（min）よりも小さい（<）

```sql
select empno,ename,sal,deptno
from   employees
where  sal <all (select avg(sal) from employees
                 group by deptno);
```
↓書き換え可能

```sql
select empno,ename,sal,deptno
from   employees
where  sal < (select min(avg(sal)) from employees
                 group by deptno);
```

|演算子|説明|
|:--|:--|
|>any|最小値よりも大きい|
|<any|最大値よりも小さい|
|>all|最大値よりも大きい|
|<all|最小値よりも小さい|

- 「not in」 =　「<>all」
    - 全てFALSEだと値を返す
    - 全てFALSEでなければ0件

- 複数行副問合せで、単一行副問合せでしか使用できない演算子（= など）を使用するとエラー

```sql
delete from orders
where customer_id = (select customer_id from customers where cust_last_name = 'Johnson')
and   customer_id = (select customer_id from customers where cust_last_name = 'Young');
```

```sql
delete from orders
where customer_id = (select customer_id from customers where cust_last_name = 'Johnson')
or   customer_id = (select customer_id from customers where cust_last_name = 'Young');
```
これらはエラー

↓ならOK

```sql
delete from orders
where customer_id in(select customer_id from customers
                     where  cust_last_name = 'Johnson'
                     or     cust_last_name = 'Young');
```

```sql
delete from orders
where customer_id in(select customer_id from customers
                     where  cust_last_name
                     in('Johnson','Young');
```

# 9.集合演算子（集合演算子の種類と使用方法）
- 集合演算子
    - 複数の問い合わせの結果を1つにまとめることができる
    - 1つ目、2つ目の問い合わせで、select句に指定する**列(または式)の個数**を同数にする必要がある
    - 2つ目の問い合わせのselect句に指定する列のデータ型は、1つ目の問い合わせのselect句に指定されている列のデータ型と同じか、同じデータ型のグループである必要がある。
    - **order by句**
        - 複合問い合わせの**最後の問い合わせ**に指定
        - 1つ目のselect句に指定されている**列**または**列別名**を指定する必要がある
    - 複合問い合わせでは**NULL**は無視されない
        - union all以外の演算子を使った場合は、重複したNULLは排除
    - 集合演算子の優先順位は**全て同じ**

|集合演算子|説明|備考|
|:--|:--|:--|
|union|重複排除し戻す|内部的にソートした上で重複行排除|
|union all|重複も含め戻す(全部戻す)|ソートはしない|
|intersect|共通行のみ戻す|2つの問い合わせに同一行がある場合、その行は1度しか表示されない|
|minus|2つ目の問い合わせ結果にない行を戻す|minus演算子を使用している場合は、問い合わせの順番を入れ替えると表示結果も変わる|

```sql
select 文1
{ union │ union all │ intersect │ minus}
select 文2
```

# 10.データ操作(DML)とトランザクション制御
## 10-1.DML(insert/update/delete)
### 10-1-1.insert(行の挿入)
- insert
    - 文字値、日付値を追加する場合は**''(シングルコーテーション)**で囲む

```sql
insert into 表名 [(列名1 [,列名2...])]
values (値1[,値2...]);
```

- 副問合せを使ったinsert
    - 副問合せを囲む**()**はあってもなくてもいい
    - values句は指定しない
        - 次の場合は、**values句に副問合せを指定可能**
            - 行を1件だけ返す**単一行副問合せ**で、select句の選択リストには1つの列だけを指定する**単一列福問い合わせ**
                - values区の副問合せのselect句の選択リストに**複数列**指定すると**エラー**
    - insert句に指定する列を省略する場合
        - 副問合せのselct句には、**表に定義されている列と同数の値**を、**表の列構成と同じ順番**で指定
    - insert句に列名を指定する場合
        - 副問合せのselect句には、**列名のリストと同数の値**を、**同じ順番**で指定
    - 副問合せの結果を列名に使用できない

```sql
insert into 表名1 [(列名1 [,列名2...])]
select 列名 [,列名...]
from   表2
[where 条件];
```

- OK

```sql
insert into (select employee_id,last_name,hire_date,job_id from employees)
values (201, 'Green',sysdate,(
                               select job_id
                               from   employees
                               where  employee_id = 101
                             )
       );                               
```
 →insert文の表名の代わりに、およびvalues句に副問合せを指定可能

- NG

```sql
insert into employeed(employee_id,last_name,hire_date,(
                                                        select job_id from employees where employee_id = 101)
values (201, 'Green',sysdate,'&JOB_ID');                               
```
　→副問合せの結果を**列名**として使用できないため、エラー

```sql
insert into employeed(employee_id,last_name,hire_date,(
                                                        select job_id from employees where employee_id = 101)
select 301,'Green',sysdate,job_id from employees where employee_id = 101;
```
　→副問合せの結果を**列名**として使用できないため、エラー


### 10-1-2.update(行の更新)

```sql
update 表名
set    列名 = 値 [,列名 = 値 ...]
[where 条件];
```

- 以下で副問合せを使える
    - 表名の代わり
    - set句
    - where句

### 10-1-3.delete(行の削除)

```sql
delete [from] 表名
[where 条件];
```

- 以下で副問合せを使える
    - where句


## 10-2.トランザクション制御

|種類|トランザクションの構成要素|
|:--|:--|
|DML(データ操作)|トランザクションは**論理的な最小単位**をして扱われる。1 or 複数のDML文で構成|
|DDL(データ定義)|トランザクションは**1つのDDL文のみ**で構成される|
|DCL(データ制御)|トランザクションは**1つのDCL文のみ**で構成される|

|トランザクションの開始と終了|処理|
|:--|:--|
|トランザクションの開始|最初にDML文が実行されたとき|
|トランザクションの終了|・commi / rollbackを実行<br>・DDL文実行<br>・DCL文実行<br>・SQL*PLUSやSQL Developerをユーザが終了させたとき<br>・マシン障害やシステムクラッシュの発生|
　※Pl/SQL無名ブロックの実行ではトランザクションは終了しない


- 明示的なトランザクション制御

|トランザクション制御文|説明|
|:--|:--|
|commit|一連の処理(DML)を**全て確定**し、トランザクション終了|
|savepoint セーブポイント名|セーブポイントを作成。<br>トランザクションは継続|
|rollback|一連の処理(DML)を**全て取り消し**し、トランザクション終了|
|rollback to [savepoint] セーブポイント名|指定したセーブポイントまでの処理をロールバック。<br>トランザクションは継続。<br>指定されたセーブポイントよりもあとに作成したセーブポイントは破棄。<br>セーブポイント名を省略すると、トランザクション全体がロールバック。|

- 暗黙的なトランザクション制御

|種類|トランザクション処理が実行されるタイミング|
|:--|:--|
|自動コミット|・DDL実行時<br>・DCL実行時<br>・SQL*PLUSやSQL Developerの**正常終了**時<br>(SQL*PLUSのexitコマンド）|
|自動ロールバック|・SQL*PLUSやSQL Developerの**異常終了**時<br>(SQL*PLUSのウィンドウの「閉じる」ボタン(×)を押すと異常終了)<br>・システム障害時|

- truncate文
    - 表に格納されている**全てのデータ**を削除
    - 削除するデータは指定できない
    - DDL文なので、実行時は自動コミット（ロールバック不可）
    - ロールバック用のデータを生成しないので、delete文よりも高速

```sql
truncate table 表名;
```

- for update句

```sql
select  列名 [,列名...]
from    表名
[where  条件]
for update [of 表名.列名] [nowait │ wait 秒数]
[order by 列名[,列名...]];
```

|要素|説明|
|:--|:--|
|nowait|待機せず、すぐにエラーを返す|
|wait 秒数|指定した秒数待機し、その間にロックが解除されなければエラーを返す|
|of 表名.列名|指定した列を含む表の行のみにロックを限定|

# 11.DDL文を使用した表の作成と管理
- データベースオブジェクト
    - Oracle Databaseに格納できるモノの総称

- スキーマ
    - データベースオブジェクトを管理するための論理的な概念
        - ユーザが所有するオブジェクトのリスト
    - Oracleサーバの各ユーザは、ユーザ名と同名のスキーマを1つ所有する
    - 領域が割り当てられてるわけではない
    - スキーマオブジェクト
        - 表、ビュー、順序（シーケンス）、索引、シノニムなど
        - ユーザはスキーマには含まれない

- オブジェクトの命名規則
    - 長さは30バイト以下
    - 先頭は数字以外の文字（数字、記号は不可）
    - 英数字（A〜Z、a〜z、0〜9）、漢字、カタカナ、ひらがな（日本語環境の場合）
    - 記号は「_」、「$」、「#」のみ
    - 同一スキーマ内で重複はダメ
    - 予約後はオブジェクト名に使用できない
        - 「SELECT」「FROM」「ORDER」 など

## 11-1.create（表の作成）
- **create table権限**が必要

```sql
create table [スキーマ名.]表名
(   列名 データ型
  [,列名 データ型...]
);
```
※create table文では**or replace**は使用できない。指定するとエラーとなる。

- defaultオプション
    - デフォルト値を指定
        - データ追加時にその列に対する値の指定を省略した場合に、その列に格納される値を設定できる

```sql
列名 データ型 [default 式] 
```

- 副問合せを使った表の作成
    - 注意点
        - データ型は指定できない
            - **デフォルト値（DEFAULT）**や**制約**は指定できる
        - NOT NULL制約のみコピー
            - その他の制約はコピーされない
        - 列名を指定した場合
            - 列名をコピーできる
            - ただし、副問合せのselect句のリストと同数の列名の指定が必要
        - 副問合せのselect句で計算式や関数を使用している場合
            - 明示的にれる列名（列別名）の指定が必要

```sql
create table 表名 [(列名 [,列名...])]
AS
副問合せ;
```

## 11-2.alter（表の構造変更）
- alter table文で表構造を変更
    - 主な操作
        - 表に新規列をお追加（add）
        - 既存列のデータ型を変更
        - 既存列にデフォルト値を設定
        - 既存列を削除（drop column）
        - 既存列の名前を変更（rename column）
        - 読み取り/書き込みモード（read write）
        - 読み取り専用（read only）

- 表のモード変更

```sql
alter table 表名 {read write │ read only};
```

## 11-3.drop（表の削除）
- **drop any table権限**が必要
- 表を削除
    - 表内の全てのデータが削除
    - **定義、制約、索引**も削除
    - 以下は無効（削除はされない）
        - 表を参照するビュー
        - シノニム
    - ゴミ箱（リサイクルビン）に移動される（完全に削除されない）
        - purge句で完全に削除

```sql
drop table 表名[purge];
```

## 11-4.データ型

|分類|説明|主なデータ型|
|:--|:--|:--|
|文字型|列に文字データを格納|・CHAR型<br>・VARCHAR2型<br>・LONG型<br>・CLOB型|
|数値型|列に数値データを格納|・NUMBER型|
|日付型|列に日付データを格納|・DATE型|
|バイナリ型|列にバイナリデータを格納|・RAW型<br>・LONG RAW型<br>・BLOB型<br>・BFILE型|
|ROWID|列にROWIDを格納|・ROWID型|

### 11-4-1.文字型

```sql
列名 VARCHAR2(最大サイズ)
列名 CHAR[(最大サイズ)]
列名 LONG
列名 CLOB
```

|データ型|説明|
|:--|:--|
|VARCHAR2型|最大4000バイトまで格納。**可変長**|
|CHAR型|最大2000バイトまで格納。**固定長**|
|LONG型|最大2GBまで格納。可変長|
|CLOB型|最大4GBまで格納。|

- VARCHAR2型 と CHAR型の違い

||VARCHAR2型|CHAR型|
|:--|:--|:--|
|最大サイズ|4000バイト|2000バイト|
|最大サイズ指定の省略|不可<br>（省略するとエラー）|可<br>（省略した場合のデフォルト値は「1」）|
|確保するデータサイズ|可変長<br>（格納するデータサイズに応じて変わる）|固定長<br>（格納するデータサイズに関わらず、**表作成時に定義したサイズで一定**）|

- LONG型
    - VARCHAR2型、CHAR型の列に格納できない大きな文字データを格納できる
    - LONG型が定義された列（LONG列）の制限
        - 副問合せを使用した表作成時に、LONG列 はコピー不可（エラー）
        - group by句、order by句にLONG列は指定不可
        - 1つの表に1つだけ定義可能
            - LONG列 or LONG RAW列のどちらか
        - LONG列に制約を定義できない

### 11-4-2.数値型
- NUMBER型

```sql
列名 NUMBER[(最大精度 [,位取り])]
```

|オプション|説明|
|:--|:--|
|最大精度|最大38桁|
|位取り|小数点以下の桁数を指定|

- 最大精度、位取りを**両方省略**
    - **最大38桁の浮動小数点**を格納
- 最大精度を指定、位取りを省略
    - 最大精度に指定した桁数の整数値を格納

### 11-4-3.日付型
- DATE型
    - 固定長の7バイトのデータを格納
    - 世紀、年、月、日、時、分、秒が内部的な**数値書式の形式**で格納

```sql
列名 DATE
```

### 11-4-4.バイナリ型

```sql
列名 RAW(最大サイズ)
列名 LONG RAW
列名 BLOB
列名 BFILE
```

|データ型|説明|
|:--|:--|
|RAW型|最大2000バイトまでのバイナリデータ<br>可変長<br>最大サイズの指定は省略できない|
|LONG RAW型|最大3GB。<br>可変長<br>LONG型と同様の
制限がある|
|BLOB型|最大4GB|
|BFILE型|最大4GB<br>読み取り専用のデータ型<br>BFILE型が定義された列に格納したデータは、Oracleサーバのデータファイル上ではなく、OS上のファイル（イメージファイルや動画ファイルなど）に保存される|

### 11-4-5.ROWID型

```sql
列名 ROWID
```

### 11-4-6.その他のデータ型（日付、時刻、期間を格納）
- TIMESTAMP型
    - DATE型の拡張
    - DATE型の列が格納できる以下に加えて**秒の小数点以下の値**も格納できる
        - 年、月、日、時、分、秒
    - 小数点以下の桁数には0〜9 の範囲で指定（省略した場合のデフォルト値は9）

```sql
列名 TIMESTAMP[(小数点以下の桁数)]
```

|TIMESTAMP型のバリエーション|説明|
|:--|:--|
|TIMESTAMP WITH TIME ZONE|タイムゾーンの**時差**を含むことができる。<br>タイムゾーンの時差は列の一部として格納、表示。|
|TIMESTAMP WITH LOCAL TIMEZONE|タイムゾーンの**時差**を含むことができる。<br>タイムゾーンの時差は列の一部として格納されず、データ取得時に**ローカルセッションのタイムゾーンの値**で表示。|

- INTERVAL YEAR TO MONTH型
    - 2つの日付・時刻の感覚を**年および月**単位で格納


- INTERVAL DAY TO SECOND型
    - 2つの日付・時刻の感覚を**日、時、分、秒**単位で格納

## 11-5.制約

|種類|説明|
|:--|:--|
|not null|NULLを許可しない|
|unique(一意)|重複を許可しない。複数のNULLは許可|
|primary key(主キー)|表内の各行を**一意**に識別できる値のみ許可（重複、NULLは許可しない）|
|foreign key(外部キー、参照整合性制約)|参照先の列にある値 or NULLのみ許可|
|check|指定した条件に合う値のみ許可|

- 制約
    - 定義レベル
        - 列レベル
        - 表レベル
    - 注意点
        - 「constraint 制約名」は省略可能
            - SYS_Cn(省略時の制約名)
        - 1つの列に複数の列レベル制約を定義する場合
            - 改行 or スペースで区切る(カンマでない)
        - 1つの表に複数の表レベル制約を定義する場合
            - 「,」(カンマ)で区切る（改行 or スペースでない）
        - 表レベル制約の構文では、「()」内に制約を定義する列を1つ以上指定する
        - 1つのcreate table文の中に列レベル制約と表レベル制約を同時に指定可能
        - not null制約は**列レベルのみ**
        - 複数列の組み合わせからなる制約（複合制約）は**表レベルのみ**

- 表作成時に定義

```sql
create table [スキーマ.]表名
(
  列名 データ型 [列レベル制約 [列レベル制約...]]
  [,列名 データ型 [列レベル制約 [列レベル制約...]] ...]
  [,表レベル制約 [,表レベル制約...]]
)
```

- 列レベル

```sql
[constraint 制約名] 制約の種類
```

- 表レベル

```sql
[constraint 制約名] 制約の種類 (列名 [,列名...])
```

### 11-5-1.not null制約
- NULLを許可しない
- 列レベルのみ
- not null制約が定義されている列にprimary key制約の追加はOK

```sql
[constraint 制約名] not null
```

### 11-5-2.unique制約(一意キー)
- 重複を許可しない
    - NULLは許可する
    - 列の組み合わせに対して定義する場合は**表レベル**で定義
- 制約と同名の一意索引が作成される
    - この自動的に作成された索引は**drop index文**では削除できない
- unique制約がついている列にprimary key制約の追加はできない
    - 既に自動的に索引がついているため

- 列レベル

```sql
[constraint 制約名] unique
```
- 表レベル

```sql
[constraint 制約名] unique (列名 [,列名...])
```

### 11-5-3.primary key制約(主キー)
- not null制約 + unique制約
    - NULLも重複も許可しない
    - 列の組み合わせに対して定義する場合は**表レベル**で定義
- **表に1つのみ**定義可能
- 制約と同名の一意索引が作成される
    - この自動的に作成された索引は**drop index文**では削除できない
- primary key制約を定義する列の値が重複していなければ、既にデータが登録されている表でもprimary key制約を追加できる

- 列レベル

```sql
[constraint 制約名] primary key
```
- 表レベル

```sql
[constraint 制約名] primary key (列名 [,列名...])
```

### 11-5-4.foreign key制約(外部キー。参照整合性制約)
- 参照先の列に存在する値のみ格納
    - NULLは許可
- 外部キーが参照する列には主キー制約（primary key） or 一意キー制約（unique）が必要

- 列レベル

```sql
[constraint 制約名] references 親表名(参照する列名 [,参照する列名...])
```

- 表レベル

```sql
[constraint 制約名] foreign key(列名[,列名...])
references 親表名(参照する列名 [,参照する列名...])
```

|指定値|説明|
|:--|:--|
|親表名|**参照先の表の名前**。<br>foreign key制約で参照する表を**親表**。<br>foreign key制約が定義されている表を**子表**。|
|参照する列名|親表に定義されている**参照先の列名**。<br>主キー制約（primary key） or 一意キー制約（unique）が定義されている列しか参照できない|

- 参照整合性制約
    - 親表を削除する場合、子表から削除
    - on delete cascde
    - on delete set null

|参照整合性制約のオプション|説明|
|:--|:--|
|指定なし|子表に親表を参照する行が存在する場合、親表に参照されている行は削除できない|
|on delete cascde|子表に親表を参照する行が存在する場合、親表の参照されている行を削除すると、**子表の参照している行も削除される**|
|on delete set null|子表に親表を参照する行が存在する場合、親表の参照されている行を削除すると、**子表の参照している行にNULL値が設定される**|

### 11-5-5.check制約
- その列には指定した条件に対してTRUE or NULLを戻す値しか格納できない
- check制約の条件は、where句に指定できる条件と同じだが、以下の指定は**許可されない**
    - currval、nextval、level、rownum疑似列の参照
    - sysdate、uid、user、userenv関数の呼び出し
    - 他の行の値を参照する問い合わせ
- check制約では**他の列の値は参照できる*
    - また、複数の列の値を参照できる
        - check制約で複数の列を参照する場合は、**表制約**で定義する必要がある

```sql
[constraint 制約名] check(条件)
```

- 例

```sql
create table orders
(order_id NUMBER(8) constraint orders_order_id_pk primary key,
 order_date date default sysdate not null,
 customer_id number(6) not null,
 shipped_date date constraint orders_shepped_date_ck check(order_date < shipped_date)　★
);
```
これは**列制約**。
check制約で複数列を参照する場合、**列制約**で定義するとエラー

↓こう書き換えればOK（表制約）

```sql
create table orders
(order_id NUMBER(8) constraint orders_order_id_pk primary key,
 order_date date default sysdate not null,
 customer_id number(6) not null,
 shipped_date date, ★違い
 constraint orders_shepped_date_ck check(order_date < shipped_date)　★
);
```


# 12.表以外のスキーマオブジェクトの作成
## 12-1.ビュー
- select文に名前をつけて保存しているスキーマオブジェクト
- ビューには実データは含まれない
    - ビューのもとになる表 = **実表**
    - ビュー = **仮想表**
- ビューのメリット
    - 複雑なselect文を簡素化できる（結合など）
    - データアクセスを制限できる
        - ビューに定義されている列にしかアクセスできない
    - データの独立性を実現できる
        - 表の定義が変更されても、ビューに定義されている列が変更されていない場合は、ビューを利用したアプリケーションは修正しなくていい
    - 同じデータを異なるビューで表示できる

|ビューの種類|説明|
|:--|:--|
|単一ビュー|1つの実表から作成され、かつ関数やgroup by句を含まないビュー。<br>ビューを通じて実表のデータを操作可能（一部例外あり）。|
|複合ビュー|単一ビュー以外のビュー。<br>2つ以上の実表から作成されているビューや、1つの実表から作成されていても関数やgroup by句を使用しているビュー。<br>ビューを通じた実表のデータ操作は**特定の条件を満たす場合のみ可能**|

- ビューの作成
    - create view権限が必要

```sql
create [or replace] [force │ noforce] view ビュー名[(列名 [,列名...])]
AS
副問合せ
[with check option [constraint 制約名]]
[with read only [constraint 制約名]];
```

|オプション|説明|
|:--|:--|
|or replace|既存の同名のビューの定義を置き換え。権限も引き継がれる。<br>指定した名前のビューがなければ、新規にビューを作成。|
|force │ noforce|・force：実表の有無にかかわらずビューを作成。ビュー参照時に表がないとエラー<br>・noforce（デフォルト値）：実表がある場合のみビューを作成。実表や対象列がない場合はエラー|
|別名|ビューに定義する列名。<br>副問合せのselect句のリストで計算式や関数を使用している場合は、別名を指定するか、副問合せに列別名を指定する必要がある|
|with check option|ビューを使用してアクセスできる行のみ、**追加 or 更新**可能|
|with read only|ビューが**読み取り専用**になる|

- ビューの削除
    - drop any view権限が必要
        - この権限を持っているユーザは、他のユーザが所有するビューも削除可能
    - 実表には影響はない
    - 削除したビューをもとに作成されたビューは**無効**

```sql
drop view ビュー名;
```

- ビューを使ったデータ変更
    - 削除
        - ビューの定義に以下の**全ての要素が含まれていない場合**に、ビューを通じて実表の行を削除可能
            - distinctキーワード
            - rownum疑似列
            - グループ関数
            - group by句
    - 更新
        - ビューの定義に以下の**全ての要素が含まれていない場合**に、ビューを通じて実表の行を更新可能
            - distinctキーワード
            - rownum疑似列
            - グループ関数
            - group by句
            - **式によって定義された列**(SAL*12など)
    - 追加
        - ビューの定義に以下の**全ての要素が含まれていない場合**に、ビューを通じて実表の行を追加可能
            - distinctキーワード
            - rownum疑似列
            - グループ関数
            - group by句
            - **式によって定義された列**(SAL*12など)
            - ビューに含まれていない実表の列にNOT NULL制約が定義されている

|ビューの定義に含まれている要素|行の削除(delete)|行の更新(update)|行の追加(insert)|
|:--|:--|:--|:--|
|ビューに含まれていない実表の列にNOT NULL制約が定義されている|○|○|×|
|式によって定義された列|○|×|×|
|distinctキーワード|×|×|×|
|rownum疑似列|×|×|×|
|グループ関数|×|×|×|
|group by句|×|×|×|

## 12-2.順序（シーケンス）
- 一意な番号（順序値）を自動的に生成するスキーマオブジェクト

```sql
create sequence 順序名
 [increment by n]
 [start with n]
 [maxvalue n │ nomaxvalue]
 [minvalue n │ nominvalue]
 [cycle │ nocycle]
 [cache n │ nocache];
```

|要素|説明|
|:--|:--|
|increment by n|n に増分値を指定（**デフォルト値：1**）|
|start with n|n に初期値を指定（**デフォルト値：1**）|
|maxvalue n|n に最大値を指定|
|nomaxvalue|デフォルトの最大値。<br>増分値がプラスの場合、10の27乗。<br>増分値がマイナスの場合は-1|
|minvalue n|n に最小値を指定|
|nominvalue|デフォルトの最小値。<br>増分値がプラスの場合、1。<br>増分値がマイナスの場合は-(10の16乗)|
|cycle|順序値が最大値 or 最小値に達した場合、**初期値に戻して繰り返し順序値を生成**。<br>順序値が最大値 or 最小値まで達したあとは、一意ではない順序値が生成される（一巡するため）|
|nocycle|順序値が最大値 or 最小値に達した場合、**順序値を生成しない**（デフォルト値）|
|cache n|メモリ内に割り当てる順序値の数。デフォルト値は20|
|nocache|順序値をキャッシュしない（順序を参照するたびに順序値を生成する）|

- 順序の使用方法
    - 以下の場合にnextval疑似列、currval疑似列を使用する
        - 順序から新しい順序値を取得する場合
        - 現行セッションで最後に取得された順序値を確認する場合

|疑似列|説明|
|:--|:--|
|nextval疑似列|新しい順序値を戻す|
|currval疑似列|現行セッションで**最後に取得された順序値**を戻す。<br>現行セッションで一度も順序値を取得していない(nextval疑似列を参照していない)状態でcurrval疑似列を参照すると**エラー**。<br>currval疑似列を参照しセッションで最後に取得した順序値を確認した直後にnetxval疑似列を参照した場合でも**必ず次の番号を参照できるとは限らない**。|

- nextval疑似列、currval疑似列の参照方法
    - 以下で参照可能
        - 主問い合わせのselect句のリスト
        - insert文内の副問合せのselect区のリスト
        - insert文のvalues句
        - update文のset句
    - 以下では**参照不可**
        - ビューのselect句のリスト
        - distinctキーワードを含むselect文
        - 以下を含むselect文
            - group by句
            - having句
            - order by句
        - select文、update文、delete文内の副問合せ
        - create table文とalter table文内の**defaultオプション（デフォルト値）**に指定する式

```sql
順序名.nextval
順序名.currval
```

- 順序のキャッシュ
    - create sequence文で**cache n(nは整数値)**指定するか、指定を省略して順序を作成すると以下の処理が行われる
        - n 個分の順序値をメモリー上に生成する
            - 指定を省略した場合のデフォルト値は**20**
        - データディクショナリの「次に生成する順序値」を「n + 1」に設定する
            - 指定を省略した場合のデフォルト値は**21**
    - その後、順序値「n」が生成されるまでキャッシュ上の順序値を戻し、n + 1 個目の順序値が要求された時点で再度以下の処理が行われる
        - n + 1 から n個分の順序値をメモリー上に生成する
            - 「20」の場合は**「21から20個分」**
        - データディクショナリの「次に生成する順序値」を「n + 1」に設定する
            - 「20」の場合は**「41」**を設定する

- 順序に欠番が発生するケース
    - 以下の場合には、nextval疑似列から戻される**順序値を使用してデータを追加している表に、欠番が発生する**
        - ロールバックが発生した場合
        - システムがクラッシュした場合
        - 順序が複数の表で使用されている場合

- 例1

手順1
開始値/増分値を指定しない場合、**デフォルト値1**が設定

```sql
create sewuence order_id_seq;
```
手順2
順序値1が発行。
cacheのデフォルト値は20なので、1〜20までの順序番号がメモリ上に生成

```sql
select order_id_seq.nextval from dual;
```
手順3
insert文のcurrvalで手順2で発行した**順序値1**を参照。
この値を使用し、order表に1件のデータとして登録

```sql
insert into orders
values(order_id_seq.currval, 'SYSDATE' ,100,1000);
```
手順4
nextvalを使用し、メモリ上に生成された**順序値2**を取得。
この値を使用し、手順3で登録したcustomer_id列が100のデータのorder_id列を更新。
最終的に、**order_id列の値が2のデータ**が1件登録されている。

```sql
update
set order_id = order_id_seq.nextval
where customer_id = 100;
```

- 順序の定義変更
    - 順序の定義変更をしても、**初期値（start with n）を再指定できない**
    - 順序値がmaxvalueに達した場合、alter sequence文でmaxvalueの変更はできる
    - alter権限

```sql
alter sequence 順序名
 [increment by n]
 [maxvalue n │ nomaxvalue]
 [minvalue n │ nominvalue]
 [cycle │ nocycle]
 [cache n │ nocache];
```

- 順序の削除
    - **初期値を指定したい場合**は、順序を削除してから再作成
    - drop any sequence権限

```sql
drop sequence 順序名;
```

## 12-3.索引（インデックス）
- 索引
    - 既に索引が作成されている列や、列の組み合わせに新たな索引は作成できない

```sql
create [unique] index 索引名
on 表名(列名[,列名...]);
```
- uniqueを指定すると**一意索引**が作成される
    - 一意索引は以下を定義した場合に自動的に作成される
        - primary key制約（主キー制約）
        - unique制約（一意キー制約） 
- on句に複数の列名を指定すると**複合の索引**が作成される
- 索引作成後に**索引の変更はできない**
    - 作成時に指定した列名は、後から変更できない
    - 索引を変更するには、1度削除し再作成

```sql
drop index 索引名;
```
drop any index権限

- 索引のガイドライン
    - 以下の条件に該当する列に索引を作成
        - where句の条件 or 結合条件としてよく使用する列
        - いろいろな種類のデータが含まれている列
        - 多くのNULL値が含まれており、NULL値以外の値を検索する列
        - 表の規模が大きく、ほとんどの問い合わせで表の**2%〜4%未満の行**を検索する列
    - 以下の場合は索引を作成しない
        - where句の条件としてあまり使用されない列
        - 規模が小さい表の列
        - 表の規模は大きいが、ほとんどの問い合わせで表の**2%〜4%を超える行**を検索する列
        - 頻繁に更新される列
        - 式の一部として参照される列


## 12-4.シノニム
- シノニムとは
    - オブジェクト（表やビューなど）の別名
    - メリット
        - セキュリティを高めれる
            - 別スキーマのオブジェクトを参照する際は「スキーマ名.オブジェクト名」と指定する必要があるが、シノニムで参照できるため、オブジェクトの所有者やオブジェクト名を隠蔽できる
        - オブジェクトの指定が用意
            - オブジェクト名が長い場合に、オブジェクトに短いシノニムを定義できる

```sql
create [public] synonym シノニム名
for オブジェクト名;
```

|種類|説明|
|:--|:--|
|パブリックシノニム|・create public synonym権限が必要<br>・**全てのユーザ**が使用できる<br>・publicオプションを指定すると作成可能<br>・デフォルトでは、DB管理者のみが作成できる|
|プライベートシノニム|・create synonym権限が必要<br>・**作成したユーザのみ**が使用できる|

- 同名のパブリックシノニムとプライベートシノニムがある場合の優先順位
    - **プライベートシノニム**が優先される

- シノニムの削除
    - drop any synonym権限：プライベートシノニムの削除権限
    - drop public synonym権限：パブリックシノニムの削除権限（デフォルトではDB管理者のみ）
    - シノニムを削除しても、もとのオブジェクトには影響はない。
    - シノニムが参照しているオブジェクトを削除しても**シノニム自体削除されない**

```sql
drop [public] synonym シノニム名;
```