---
# System prepended metadata

title: SQL語法

---

# SQL語法

密碼:1234

> 市面上所有商用資料庫系統皆支援ANSI SQL語法。
-  由於各廠商為突顯自家資料庫系統之獨特性，會對部份的ANSI SQL語法做些微修改，以支援自家資料庫系統所發展之各項功能

### 零. MySQL 註解
`/* 想講的話 */`

### 一. SQL指令種類
![image](https://hackmd.io/_uploads/BJ2C1iDta.png)

### 二. SQL資料型態
#### 1. 字串 (Character Strings)
- CHAR(n)：固定長度字元串 (n為字元個數)
- VARCHAR(n)：變動長度字元串
-  BIT(n)：固定長度位元串 (n為位元個數)
- BIT VARING(n)：變動長度位元串
![image](https://hackmd.io/_uploads/H13LeoDtp.png)

#### 2. 數值串(Numeric Strings)

- INT, INTEGER：整數
- DEC(m,n), DECIMAL(m,n), NUMERIC(m,n)：格式化數值 (m：總位數或精確度，n：小數位數)
- SMALLINT：短整數
- FLOAT：浮點數
- REAL：單精度實數 (32bits)
- DOUBLE PRECISION：雙精度實數 (64bits)
![image](https://hackmd.io/_uploads/BkS1bjwt6.png)

#### 3. 日期/時間 (Date/Time)資料型態
- DATE：一般格式為 YYYY-MM-DD
- TIME：一般格式為 HH:MM:SS
- TIMESTAMP：時間戳記，由DATE+TIME+六位以上小數秒數
- 用以記錄交易進入系統的時間順序
- INTERVAL：時間區間

![image](https://hackmd.io/_uploads/ByRGZjwtp.png)



### 三. 資料類型可以分為數字、字串與日期時間三個類型：

- 數字類型：包括INT、DECIMAL、NUMERIC、FLOAT等。
- 字串類型：包括CHAR、VARCHAR、TEXT等。
- 時間類型：包括DATE、DATETIME、TIMESTAMP等。

## 四. 建立資料庫的基本操作
> DDL(Data Definition Language,資料定義語言)
下面的指令可以對資料庫進行基本的操作。
- 使用指令的時候，結尾一定要加上分號（;）作為指令的結束。

#### 1. 顯示SQL中資料庫的狀況
```
show databases;
```
![image](https://hackmd.io/_uploads/Bkx51gutp.png =40%x)


#### 2. 建立資料庫
> 在create database後面接上想要建立的資料庫名稱。要注意的是，資料庫的名稱不可以有空白。
```
create database 資料庫名稱;
```
![image](https://hackmd.io/_uploads/rkmI8qwFp.png)



#### 3. 指定當前要使用的資料庫。才可以操作該資料庫
```
use 想要操作的資料庫名稱;
```
![image](https://hackmd.io/_uploads/H1t2L9DtT.png)

#### 4. 查看目前選定的資料庫是哪一個
```
select database();
```
![image](https://hackmd.io/_uploads/B1Gev9wYT.png)



#### 5. 刪除特定名稱的料庫
```
drop database 想刪除DB的名稱;
```
![image](https://hackmd.io/_uploads/SygdvqDY6.png)

#### 6. 查看特定資料庫中的所有資料表
> 記得要先  `use 資料庫;`
```
SHOW TABLES;
```
![image](https://hackmd.io/_uploads/SJ2YZs_K6.png =50%x)


## 五. 資料表的基本操作
![image](https://hackmd.io/_uploads/S1YK_9PFa.png)

#### 1. 建立資料表
```
CREATE TABLE member(
    username VARCHAR(20),
    email VARCHAR(40),
    phone VARCHAR(20),
    age INT
);
```
![image](https://hackmd.io/_uploads/B1mb95DFT.png)


#### 2. 檢視創建的資料表
```
desc 資料表名稱;
```
![image](https://hackmd.io/_uploads/r1eGc5vFT.png)

#### 3. 刪除指定的資料表
![image](https://hackmd.io/_uploads/Skpss5DtT.png)

```
drop table 資料表名稱;
```
![image](https://hackmd.io/_uploads/S1rKccDK6.png)


#### 4. 更改資料表內容
ALTER TABLE: 更改一個關聯 (表格) 中之某欄位的基本定義與限制。
包括：
- 增加(ADD)欄位、刪除(DROP)欄位
- 修改(ALTER/CHANGE/MODIFY…) 欄位預設值、定義、或名稱
- 更改表格名稱(RENAME)
- 更改表格類型(ENGINE)
```
ALTER TABLE 資料表名稱
ADD/DROP/ALTER/CHANGE/MODIFY/ENGINE/RENAME 新欄位名稱 型態;
```
#### - 增加欄位：
![image](https://hackmd.io/_uploads/BkRfa9vtT.png)

    


#### - 刪除欄位 : 
![image](https://hackmd.io/_uploads/B1xWa9DKT.png)



#### - 修改欄位 1 (增改/刪除預設值)：
![image](https://hackmd.io/_uploads/rJ5ip9wKa.png)

![image](https://hackmd.io/_uploads/HyqTTqPY6.png)



#### - 修改欄位 2 (更改欄位定義，不含修改欄位名)：
![image](https://hackmd.io/_uploads/S1VgA5wYa.png)


#### - 修改欄位 3 (更改欄位定義，含修改欄位名)：
![image](https://hackmd.io/_uploads/SJ2bCqwF6.png)


#### - 更改表格類型：
![image](https://hackmd.io/_uploads/HJSOR5Ptp.png)


#### - 更改表格名稱：
![image](https://hackmd.io/_uploads/HJSYC9DKa.png)
![image](https://hackmd.io/_uploads/SJ6s0cwYp.png)


## 六. 針對關聯表中的部分資料進行處理
> DML(Data Manipulation Language,資料處理語言)

#### 1. 將數據資料插入資料表裡面。
> 我們可以一次插入一筆數據資料進入資料表，也可以一次插入多筆資料進入資料表

![S__3416105](https://hackmd.io/_uploads/r1d0jowFp.jpg)
```
#插入部分指定的欄位資料
INSERT INTO 資料表名稱(欄位名1, 欄位名2,…) VALUES (…)
```
![image](https://hackmd.io/_uploads/Hk8oosvFp.png)


```
#插入全部欄位的資料
INSERT INTO 資料表名稱 VALUES 
```
![image](https://hackmd.io/_uploads/SyvbosPK6.png)

![image](https://hackmd.io/_uploads/Hk8nooPK6.png)

#### 2. 根據WHERE條件刪除表中的資料
```
DELETE FROM 表格名 WHERE 條件
```
![S__3416108](https://hackmd.io/_uploads/BkVEpiDF6.jpg)

#### 3. 根據WHERE條件更改表中的屬性值
```
UPDATE 表格名稱
SET 欄位名稱 = 新的值
WHERE 須滿足條件
```
![S__3416107](https://hackmd.io/_uploads/B1y_pjvtp.jpg)


![image](https://hackmd.io/_uploads/SkD_HhwKp.png)

## 七. 利用DQL查詢DB的相關資料
> DQL(Data Query Language,資料查詢語言)
![S__3416109](https://hackmd.io/_uploads/r1bvs3wFT.jpg)

![S__3416111](https://hackmd.io/_uploads/HkZvonvtT.jpg)

> 只有Select 和 From 是每次一定都要寫的，其他依需求而訂

```
SELECT * FROM Warriors;   //將FROM 中表格的所有資料顯示出來
```

### SQL相關運算子
![image](https://hackmd.io/_uploads/rkAXh2wF6.png)

EX. ![image](https://hackmd.io/_uploads/r1MUhnPK6.png)

### 欄位名稱重複處理
> 較複雜的資料查詢可能會用到多個table,此時可能發生位於不同表格中的同名欄位被一起使用的情況
> 解法: 在使用同名欄位時，加上表格名稱
```
Warriors.player  //勇士隊此表格中的球員
```
![image](https://hackmd.io/_uploads/HJVWeTvKp.png)

![S__3416112](https://hackmd.io/_uploads/S1xOZavtT.jpg)

![image](https://hackmd.io/_uploads/Hkz4NjOFa.png)


### 聚合函數(Aggregate function)：
- COUNT(attribute_name): 計算非空屬性值個數
- SUM(attribute_name): 計算屬性中數值的總合
- AVG(attribute_name): 計算屬性中數值的平均
- MAX(attribute_name): 找出屬性中數值的最大值
- MIN(attribute_name): 找出屬性中數值的最小值

#### Ex1. 
![S__3416113](https://hackmd.io/_uploads/HJaTPTDFT.jpg)

![image](https://hackmd.io/_uploads/ry7CBjuYp.png =40%x)

#### Ex2.
![S__3416115](https://hackmd.io/_uploads/rJT6Pawt6.jpg)

![image](https://hackmd.io/_uploads/S1e9SouFa.png =60%x)

#### Ex3.
![image](https://hackmd.io/_uploads/BkLguTwFT.png)

![image](https://hackmd.io/_uploads/S1c5SjdKa.png =60%x)

---

#### 【注意】利用聚合函數所設立之條件，不能直接寫在WHERE子句
> - Where子句是繼From子句後，第二個會被執行到的SQL查詢語句
> - 若無搭配Group By先做分群，則聚合函數僅會得到單一筆計算結果。若對此計算結果再做條件過濾是會有函數使用上的問題!!

### 欄位取別名(Alias):
```
表格名稱 as 別名

欄位名稱 as 別名
```

EX.
![image](https://hackmd.io/_uploads/Byzi_pwFp.png)

### 聚合函數中COUNT的用法：
- COUNT(*): 計算表格中，共有幾筆非空記錄
- COUNT(欄位名稱): 此屬性有幾筆非空值
- COUNT(DISTINCT 欄位名稱): 此屬性有幾筆不同的非空值
> COUNT(DISTINCT: 代表重複資料只算一次

EX.
![S__3416116](https://hackmd.io/_uploads/HyGzxCwt6.jpg)

![image](https://hackmd.io/_uploads/ByCyvjOFa.png =60%x)
![image](https://hackmd.io/_uploads/S1P-PjOtT.png =80%x)


## 八. 巢狀查詢
> 查詢中又包含另一個查詢

![S__3416125](https://hackmd.io/_uploads/H1KCs1OYa.jpg)

![S__3416126](https://hackmd.io/_uploads/ByU1n1utp.jpg)

### 巢狀查詢的分類
![S__3416127](https://hackmd.io/_uploads/Hyrg3yuta.jpg)

![S__3416124](https://hackmd.io/_uploads/Skhb2J_K6.jpg)

![image](https://hackmd.io/_uploads/SyOE2ydY6.png)

---
#### 練習題:
![image](https://hackmd.io/_uploads/r16k6JuYa.png =70%x)

EX1. 列出供應商“大勝”有供應給專案使用的零件之平均重量

![image](https://hackmd.io/_uploads/S1kUTkOYa.png)

![image](https://hackmd.io/_uploads/B1yETj_ta.png =80%x)


EX2.列出重量大於供應商代號S2有供應給專案使用之所有零件的零件名稱

![image](https://hackmd.io/_uploads/SJ_hakdY6.png)

EX3. 列出重量大於供應商代號S2有供應給專案使用之任一零件的零件名稱
![image](https://hackmd.io/_uploads/ByS1Ay_KT.png)



### [NOT] EXISTS的用法
> 回傳Boolean value
#### EXISTS:
> 此運算子在當子查詢有查詢結果產生時，會回傳TRUE給主查詢，否則便回傳FALSE。
> - 同時，子查詢若有資料產生，會暫存於記憶體以待主查詢使用。
#### NOT EXISTS:
> EXISTS的反義詞。成立回傳False、不成立回傳True

##### EX. 標準子查詢:
![image](https://hackmd.io/_uploads/Syj7ZfFYp.png)

![S__3416128](https://hackmd.io/_uploads/rJPsRy_Kp.jpg)

![image](https://hackmd.io/_uploads/B1_30JOYT.png =70%x)

![image](https://hackmd.io/_uploads/SkdTC1_Y6.png =70%x)

##### EX. 關聯子查詢:
![image](https://hackmd.io/_uploads/BJqMfztFa.png)
EX.
![image](https://hackmd.io/_uploads/H1NxfMFY6.png)
#### Q: ，列出有供應零件'P1'的供應商名稱
- 主查詢的表格，在子查詢中會使用到，它將與子查詢之表格做合併處理，所以是有關的。
- 子查詢在此除告知主查詢它是否有回傳值，其條件式也會影響主查詢。
![image](https://hackmd.io/_uploads/S1k8QzKK6.png)

![image](https://hackmd.io/_uploads/ryUj7MFtp.png)

### 其他運算子
![S__3432455](https://hackmd.io/_uploads/HJg47iMYKT.jpg)

### EX1.
![image](https://hackmd.io/_uploads/rJy23zKK6.png)

### EX2.
![image](https://hackmd.io/_uploads/ByAC3fKt6.png)

### EX3.
![image](https://hackmd.io/_uploads/B1_l6ftFT.png)

### EX4.
![image](https://hackmd.io/_uploads/By-M6MtFT.png)

## 合併查詢(JOIN)
> 若使用者要查詢的資料來源，是一個以上的表格資料合併在一起的結果，則此一查詢任務需採用合併查詢
![image](https://hackmd.io/_uploads/SJVPpzFFa.png)

#### 合併查詢可分成：
### Inner Join (內部合併)
> 將多個表格的內容以某合併條件結合在一起，只顯示符合條件的資料

![image](https://hackmd.io/_uploads/BJbhaftFa.png)

EX. 列出位於相同城市的專案名稱、供應商名稱與兩者之城市名稱。
> (學習重點：1. 內部合併; 2. 對表格取別名)

![image](https://hackmd.io/_uploads/rklzRMKta.png)

#### 寫法1
![image](https://hackmd.io/_uploads/rJvGy7YKp.png)

#### 寫法2
![image](https://hackmd.io/_uploads/BJm71XKFa.png)






### Outer Join (外部合併)
> 將多個表格的內容以某合併條件結合在一起，而不符合條件的資料將視需求以不同方式予以呈現。
> 
> 當不滿足合併條件的資料也想要查看時可用

#### 外部合併的類型可分為：
- 左外部合併 (Left Outer Join)
> 左邊表格重要,即便他不滿足合併條件也會顯示出來。而右邊表格只會顯示符合條件的資料

- 右外部合併 (Right Outer Join)
> 反之，右邊表格全顯示，左邊須符合條件才顯示

- 全外部合併 (Full Outer Join):
> 不管條件全部都顯示，但MySQL不支援全外部合併指令，但可以用 `Union` 達到相同的效果。

![image](https://hackmd.io/_uploads/BJsCJQtFa.png)
> OUTER 此關鍵字可寫可不寫(但老師建議要寫，為了日後的好維護)

#### EX1. 列出位於相同城市的專案名稱、城市與供應商名稱、城市，但是不符條件的專案資料也請一併列出。(學習重點：1. 左外部合併; 2. 對表格取別名)
![image](https://hackmd.io/_uploads/r1DdzmFFT.png)

![image](https://hackmd.io/_uploads/B1E6fQtt6.png)

---

#### EX2. 列出位於相同城市的專案名稱、城市與供應商名稱、城市，但是不符條件的專案資料也請一併列出。(學習重點：1. 右外部合併; 2. 對表格取別名)

![image](https://hackmd.io/_uploads/Hy24zQFYa.png)

![image](https://hackmd.io/_uploads/SyvRzXFYT.png)

---

#### EX3. 列出位於相同城市的專案名稱、城市與供應商名稱、城市，但是不符條件的專案資料也請一併列出。(學習重點：1. 全外部合併; 2. 對表格取別名)
![image](https://hackmd.io/_uploads/rkycM7KFa.png)

![image](https://hackmd.io/_uploads/B1Iy77KK6.png)

---

## DDL(Data Definition Language,資料定義語言)
> DL主要有CREATE, DROP, ALTER三個指令，並可針
對以下不同的資料庫系統物件進行操作：
- 資料庫 (database)
- 表格 (Table)
- 景觀 (View)
- 索引 (Index)
- …


### View(景觀)
![S__3432456](https://hackmd.io/_uploads/H11W-VFta.jpg)

![S__3432457](https://hackmd.io/_uploads/H1kZZVFFT.jpg)


#### 建立View
![image](https://hackmd.io/_uploads/Bk9H-VtFp.png)

![image](https://hackmd.io/_uploads/HyGXVEYFT.png)

#### 檢視View
![image](https://hackmd.io/_uploads/HyUNEVtY6.png)



#### 刪除View
![image](https://hackmd.io/_uploads/HJUOZEFK6.png)

![image](https://hackmd.io/_uploads/B1b3U44Yta.png)


#### View的優點：
- 隱藏不需要或具私密性的資料
- 同一關聯表可建立多種不同的觀點，讓使用者以不同的角度看同一份資料。
#### 景觀的缺點：
- 景觀的DML操作有諸多限制，無法提供與實際表格完全相同的操作 (畢竟它是屬於虛擬表格)。

## Index (索引)
![image](https://hackmd.io/_uploads/SkKez4YKa.png)

![image](https://hackmd.io/_uploads/rJ3C-NFKa.png)

![image](https://hackmd.io/_uploads/Skabf4tFT.png)

![image](https://hackmd.io/_uploads/B12IBVKtp.png)

![image](https://hackmd.io/_uploads/HySFBVFYp.png)


![image](https://hackmd.io/_uploads/H1k7GVFFp.png)

![image](https://hackmd.io/_uploads/ry8nrEtKp.png)


#### 建構索引的時機：
- 表格資料量龐大
- 欲建構索引的欄位，極少有DML的操作
- 欲建構索引的欄位，經常作為查詢條件使用
#### 不適合建構索引的狀況：
- 表格資料量很少
- 欲建構索引的欄位，經常有DML的操作
- 欲建構索引的欄位，極少作為查詢條件使用

## DCL (Data Control Language,資料控制語言)
![S__3432458](https://hackmd.io/_uploads/BJ7xQEYFa.jpg)


![image](https://hackmd.io/_uploads/B14Kz4FK6.png)

![image](https://hackmd.io/_uploads/BJMqfVYFp.png)

![S__3432460](https://hackmd.io/_uploads/Hyf-QVtFa.jpg)

- REVOKE敘述只移除使用者的資料操作權限而非移除使用
者，該使用者資訊仍存在於資料庫系統中。
- 要完整的移除使用者，必須使用DELETE指令明確地由資
料庫系統之相關權限設定表格中，將使用者紀錄刪除。






---

### 練習題:
![image](https://hackmd.io/_uploads/B1tNmowt6.png)
```
CREATE TABLE Supplier
       (供應商代號 CHAR(4),
        供應商名稱 CHAR(10),
        城市       CHAR(6),
        PRIMARY KEY(供應商代號)
       );

CREATE TABLE Project
       (專案代號 CHAR(4),
        專案名稱 CHAR(10),
        城市     CHAR(6),
        PRIMARY KEY(專案代號)
       );

CREATE TABLE Component
       (零件代號 CHAR(4),
        零件名稱 CHAR(10),
        顏色     CHAR(4),
        重量     INT,
        PRIMARY KEY(零件代號)
       );

CREATE TABLE Project_supp_Component
       ( 供應商代號 CHAR(4),
         零件代號 CHAR(4),
         專案代號 CHAR(4),
         數量     INT,
         PRIMARY KEY(供應商代號,專案代號,零件代號),
         FOREIGN KEY(供應商代號) REFERENCES Supplier(供應商代號) ON Delete CASCADE,
         FOREIGN KEY(專案代號) REFERENCES Project(專案代號) ON Delete CASCADE,
         FOREIGN KEY(零件代號) REFERENCES Component(零件代號) ON Delete CASCADE
       )ENGINE=INNODB;

SHOW TABLES;
```

Ex2. 建立的四個空表格插入其應有的資料
```
INSERT INTO Supplier VALUES ('S1', '大勝', '台南');
INSERT INTO Supplier VALUES ('S2', '冠軍', '高雄');
INSERT INTO Supplier VALUES ('S3', '無敵', '台中');
INSERT INTO Supplier VALUES ('S4', '一級棒', '高雄');

INSERT INTO Project VALUES ('J1', '火星', '台中');
INSERT INTO Project VALUES ('J2', '土星', '高雄');
INSERT INTO Project VALUES ('J3', '太陽', '台北');

INSERT INTO Component VALUES ('P1', '螺絲釘', '黑',14);
INSERT INTO Component VALUES ('P2', '螺帽', '黑',16);
INSERT INTO Component VALUES ('P3', '齒輪', '綠',27);
INSERT INTO Component VALUES ('P4', '板手', '藍',63);
INSERT INTO Component VALUES ('P5', '撬子', '棕',80);

INSERT INTO Project_supp_Component VALUES ('S1', 'P1', 'J2',300);
INSERT INTO Project_supp_Component VALUES ('S1', 'P1', 'J3',100);
INSERT INTO Project_supp_Component VALUES ('S1', 'P4', 'J1',500);
INSERT INTO Project_supp_Component VALUES ('S2', 'P2', 'J1',400);
INSERT INTO Project_supp_Component VALUES ('S2', 'P3', 'J3',600);
INSERT INTO Project_supp_Component VALUES ('S3', 'P1', 'J2',300);
INSERT INTO Project_supp_Component VALUES ('S4', 'P3', 'J1',200);
INSERT INTO Project_supp_Component VALUES ('S4', 'P4', 'J1',700);
INSERT INTO Project_supp_Component VALUES ('S4', 'P5', 'J2',100);
```

```
--檢視一下4個表格內的資料

SELECT * FROM Supplier;
SELECT * FROM Project;
SELECT * FROM Component;
SELECT * FROM Project_supp_Component;
```

![image](https://hackmd.io/_uploads/H1yp7sDFp.png)


#### 參考資料:
1. 杰哥程式碼: http://debussy.im.nuu.edu.tw/sjchen/Database/Final/SQL%E6%93%8D%E4%BD%9C%E7%AF%84%E4%BE%8B.txt

3. 杰哥數位教室影片: http://debussy.im.nuu.edu.tw/sjchen/DataBaseMan_Final.html

2. https://medium.com/web-design-zone/mysql資料庫的安裝與基本操作-f36a079afd85