---
# System prepended metadata

title: 資料庫
tags: [家教]

---




## 資料庫基本概念

### 什麼是資料庫？
1. 資料表（Table）：資料表是資料庫中最基本的資料存儲結構。它是一個二維的資料結構，包含多列和多行，用於存儲特定類型的數據。每個資料表都具有唯一的名稱，用於識別和查詢資料。
    - ![](https://hackmd.io/_uploads/SkDb0n7-p.png)
2. Column：資料表中的列代表特定的資料屬性或字段。每列都有一個名稱，用來識別該列的內容，並具有特定的資料類型，例如整數、字符串、日期等。資料表的結構是由它的列定義所確定的。

3. Row：資料表中的行是實際的記錄或數據項。每行包含一個或多個列的值，這些值對應於特定記錄的屬性。例如，如果你有一個資料表用於存儲員工信息，每行代表一個員工，包含姓名、工號、職位等。

4. 主鍵（Primary Key）：主鍵是一個用來唯一識別資料表中每一行的列或一組列。主鍵確保了每行的唯一性，並且可以用來查找、連接和修改資料。一個資料表只能有一個主鍵，且主鍵的值不能為 NULL。
    - ![](https://hackmd.io/_uploads/rJkwC2XW6.png)

5. 外鍵（Foreign Key）：外鍵是一個用來建立表之間關聯的列。它建立了一個參照其他資料表的關聯，通常用於維護資料之間的完整性和關聯。外鍵的值是另一個資料表中的主鍵，用於確保關聯的一致性。


### 數據模型分類
#### 關聯資料庫 (Relational Database)：
- 結構化資料存儲： 關聯資料庫以表格形式存儲數據，每個表格包含列和行，具有固	定的結構，並使用結構化查詢語言（SQL）來查詢和操作數據。
- 表格和列： 關聯資料庫使用表格（表）來組織數據，每個表格包含一組列，每列定義了特定的數據類型
- 關聯： 關聯資料庫通過主鍵和外鍵來建立表之間的關聯，以實現數據的一致性和參照完整性。
- 廣泛使用場景： 關聯資料庫適用於需要複雜查詢、多表關聯、事務處理的場景，如企業應用、交易處理系統、銀行系統等。

#### 非關聯資料庫 (Non-relational Database，NoSQL Database)：

- 彈性數據存儲： 非關聯資料庫允許靈活的數據存儲，可以存儲半結構化或非結構化數據，不需要固定的表結構。
- 多種數據模型： NoSQL 資料庫支持多種數據模型，如文件數據庫、列族數據庫、鍵值對數據庫和圖形數據庫。
- 
> 總之，關聯資料庫和非關聯資料庫之間的主要區別在於數據模型、結構、查詢語言。選擇使用哪種類型的資料庫取決於您的項目需求、數據性質和性能要求。有時候，混合使用關聯資料庫和非關聯資料庫也是一種有效的策略。

#### 什麼是結構化
- 結構化資料是指以一種固定格式或結構來組織和存儲的數據。這種類型的數據具有清晰的結構，每個數據元素都有特定的字段和值，這些字段的名稱和數據類型是預定義的。結構化數據通常以表格形式存儲，每個數據項目都位於特定的列和行中。這種結構使得數據容易被組織、查詢和分析。

### [什麼是 key](https://medium.com/pierceshih/%E7%AD%86%E8%A8%98-%E8%B3%87%E6%96%99%E9%97%9C%E8%81%AF%E7%9A%84%E4%B8%89%E7%A8%AE%E9%97%9C%E4%BF%82-245152c093da)

### [資料庫的正規化](https://blog.build-school.com/2022/07/22/%E8%B3%87%E6%96%99%E5%BA%AB%E6%AD%A3%E8%A6%8F%E5%8C%96%E7%AD%86%E8%A8%98/)

## SQL（Structured Query Language）：
- 定義：SQL（Structured Query Language，結構化查詢語言）是一種用於管理和操作關聯式數據庫系統的標準化查詢語言。SQL 用於執行各種數據庫操作，包括檢索數據、插入、更新和刪除數據，以及創建和管理數據庫對象（如表、視圖、索引等）。

## 資料庫 sample
- [sample](https://www.sqlitetutorial.net/sqlite-sample-database/)
## 使用環境
- [SQLlite](https://www.runoob.com/sqlite/sqlite-installation.html)
### 基本 SQL 語法： 掌握 SQL 的基本語法

- 具體而言，資料操作 可細分為 
    - 創造 Create
    - 查詢 Read
    - 更新 Update
    - 刪除 Delete
### 查詢

#### SELECT FROM： 用於查詢數據。
1. SELECT 與 FROM 敘述是從指定的資料表中選擇欄位的查詢語法，SELECT * 表示選擇資料表的「所有」欄位
    - ![](https://hackmd.io/_uploads/Sk8KBa7-6.png)
2. SELECT column_name 表示只選擇指定欄位
    - ![](https://hackmd.io/_uploads/By6AS6m-6.png)
3. 若想指定多個欄位，可用逗號 , 將多個欄位名稱隔開
    - ![](https://hackmd.io/_uploads/BJj1LpX-a.png)
#### WHERE 子句： 用於篩選查詢結果。
![](https://hackmd.io/_uploads/S10WU6mWa.png)

#### Operator
- 比較運算符：
```sql=
=：等於（相等）。
<> 或 !=：不等於。
<：小於。
>：大於。
<=：小於等於。
>=：大於等於。
BETWEEN：在某個範圍內。
LIKE：模糊查詢，用於匹配模式。
IN：在某個值集合中。
```

- 邏輯運算符：
```sql=
AND：邏輯與（兩個條件都必須為真）。
OR：邏輯或（至少一個條件為真）。
NOT：邏輯非（取反）。
```
- 算術運算符：
```sql=
+：加法。
-：減法。
*：乘法。
/：除法。
%：取餘數。
```

#### ORDER BY 子句： 用於排序查詢結果。
- ORDER BY 子句用於對 SQL 查詢的結果進行排序。你可以使用 ORDER BY 子句根據一個或多個列的值來指定排序順序。以下是 ORDER BY 子句的基本用法：
    ```sql=

    SELECT column1, column2, ...
    FROM table_name
    ORDER BY column1 [ASC | DESC], column2 [ASC | DESC],       ...;
    ```

    - SELECT column1, column2, ...: 定義你想要檢索的列。
    - FROM table_name: 指定你要檢索數據的資料表。
    - ORDER BY: 這是排序子句的開始。
    - column1, column2, ...: 這是你想要用來排序的列的名稱，你可以指定多個列以建立複雜的排序。
    - [ASC | DESC]: 可選的，表示排序順序。默認情況下是升序（ASC），即從小到大排序。如果你想降序排序（從大到小），則使用 DESC。

- 升序排序（默認情況下）：
```sql=
sql
Copy code
SELECT FirstName, LastName
FROM employees
ORDER BY LastName, FirstName;
```

- 降序排序：
```sql=
sql
Copy code
SELECT ProductName, UnitPrice
FROM products
ORDER BY UnitPrice DESC;
```
- 多列排序：
```sql=
sql
Copy code
SELECT CustomerName, OrderDate, TotalAmount
FROM orders
ORDER BY CustomerName, OrderDate DESC;
```

#### JOIN 操作： 用於聯接多個資料表。
- INNER JOIN：
    - INNER JOIN 返回兩個資料表中匹配行的交集。這是最常見的 JOIN 類型。
    ```sql=

    SELECT employees.EmployeeName, departments.DepartmentName
    FROM employees
    INNER JOIN departments ON employees.DepartmentId = departments.DepartmentId;
    ```

- LEFT JOIN（或 LEFT OUTER JOIN）：
    - LEFT JOIN 返回左邊資料表中的所有行，以及右邊資料表中與左邊資料表匹配的行。如果右邊資料表中沒有匹配的行，則返回 NULL。
    ```sql=

    SELECT customers.CustomerName, orders.OrderDate
    FROM customers
    LEFT JOIN orders ON customers.CustomerID = orders.CustomerID;
    ```

- RIGHT JOIN（或 RIGHT OUTER JOIN）：
    - RIGHT JOIN 返回右邊資料表中的所有行，以及左邊資料表中與右邊資料表匹配的行。如果左邊資料表中沒有匹配的行，則返回 NULL。
    ```sql=

    SELECT orders.OrderDate, customers.CustomerName
    FROM orders
    RIGHT JOIN customers ON orders.CustomerID = customers.CustomerID;
    ```
- FULL JOIN（或 FULL OUTER JOIN）：
    - FULL JOIN 返回左邊和右邊資料表中的所有行，如果沒有匹配的行，則返回 NULL。
    ```sql=

    SELECT employees.EmployeeName, departments.DepartmentName
    FROM employees
    FULL JOIN departments ON employees.DepartmentId = departments.DepartmentId;
    ```
- SELF JOIN：
    - SELF JOIN 是一個特殊的情況，其中你加入資料表的不同行，通常用於處理層次結構的資料，如組織樹。
    ```sql=

    SELECT e1.EmployeeName AS Employee, e2.EmployeeName AS Manager
    FROM employees e1
    LEFT JOIN employees e2 ON e1.ManagerID = e2.EmployeeID;
    ```
- 這些是 JOIN 操作的基本類型，它們允許你根據不同的關聯條件合併資料表，以執行更複雜的查詢。你應根據你的資料表結構和查詢需求選擇合適的 JOIN 類型。

#### GROUP BY 子句
- 用於分組數據。
- having
    - HAVING 子句是 SQL 中用於篩選聚合查詢結果的一個子句。它通常與 GROUP BY 子句一起使用，用於對分組後的數據應用過濾條件。HAVING 子句允許你篩選聚合值，而 WHERE 子句用於篩選行級數據。 
    ```sql=
    SELECT column1, column2, aggregate_function(column3)
    FROM table_name
    GROUP BY column1, column2
    HAVING condition;
    ```
    - SELECT 子句列出了你想要檢索的列，包括聚合函數（如 SUM、COUNT、AVG 等）。
    - FROM 子句指定了你要查詢的資料表。
    - GROUP BY 子句用來指定分組的條件，列出了根據哪些列進行分組。
    - HAVING 子句用來篩選根據 GROUP BY 分組後的結果。這裡的 condition 是一個運算式，如果運算式的結果為真，則相應的分組將包含在結果中。
    ```sql=
    SELECT product_id, SUM(quantity * price) AS total_sales
    FROM orders
    GROUP BY product_id
    HAVING SUM(quantity * price) > 1000;
    ```

#### Partition

- PARTITION BY 子句通常與分析函數一起使用，它允許你將查詢結果分為多個分區，然後在每個分區內應用分析函數。這對處理有組織結構的資料或需要按特定條件分組的查詢非常有用。

- 以下是一個簡單的示例，說明如何使用 PARTITION BY：

    - 假設你有一個 sales 資料表，包含銷售員工的銷售金額以及他們所屬的部門。你想查詢每個部門內每位銷售員工的銷售金額排名。這就是你可以使用 PARTITION BY 的情況：
    ```sql=

    SELECT
      Department,
      Salesperson,
      SalesAmount,
      RANK() OVER (PARTITION BY Department ORDER BY SalesAmount DESC) AS SalesRank
    FROM sales;
    ```
    - 在這個查詢中，PARTITION BY Department 表示你要將結果集分為多個分區，每個分區代表一個不同的部門。然後，RANK() OVER (PARTITION BY Department ORDER BY SalesAmount DESC) 部分選擇在每個部門內按銷售金額遞減排序，並賦予每位銷售員工在其部門內的銷售金額排名。

- 這是 PARTITION BY 的基本用法，它允許你在結果集的分區內應用分析函數，以便更好地理解和分析資料。你可以根據不同的情況和需求調整 PARTITION BY 子句。

#### with
- "WITH" 子句在 SQL 中用於建立臨時的查詢結果集，也稱為公共表達式（Common Table Expression，CTE）。這些臨時結果集可以在查詢中多次引用，從而使複雜查詢更易於閱讀和維護。

    - "WITH" 子句的基本語法如下：
    ```sql=

    WITH cte_name (column1, column2, ...) AS (
        -- 查詢語句
        SELECT ...
    )
    -- 主查詢
    SELECT ...
    ```
- 以下是 "WITH" 子句的一些常見用法：

    - 建立公共表達式（CTE）：
        - 使用 "WITH" 子句，你可以創建一個具有列名的臨時表達式，這個表達式可以在查詢中多次引用。例如：
        ```sql=
        sql
        Copy code
        WITH EmployeeCTE (EmployeeName, Salary) AS (
            SELECT Name, Salary FROM Employees
        )
        SELECT EmployeeName, Salary
        FROM EmployeeCTE
        WHERE Salary > 50000;
        ```
- 這裡，"EmployeeCTE" 是一個臨時表達式，用於存儲 Employee 表中的數據，然後在後續查詢中引用。

### 常用函數
1. **聚合函數：**
   - `COUNT()`: 計算行數或某列的非 NULL 值的數量。
   - `SUM()`: 計算某列的數值總和。
   - `AVG()`: 計算某列的平均值。
   - `MAX()`: 找出某列的最大值。
   - `MIN()`: 找出某列的最小值.

2. **字符串函數：**
   - `CONCAT()`: 連接兩個或多個字符串。
   - `LENGTH()` 或 `LEN()`: 返回字符串的長度。
   - `UPPER()`: 轉換字符串為大寫。
   - `LOWER()`: 轉換字符串為小寫。
   - `SUBSTRING()`: 提取部分字符串.

3. **日期和時間函數：**
   - `CURRENT_DATE` 或 `NOW()`: 返回當前日期和時間。
   - `DATE()`: 提取日期部分。
   - `TIME()`: 提取時間部分。
   - `YEAR()`, `MONTH()`, `DAY()`: 提取年、月、日。
   - `DATEDIFF()`: 計算兩個日期之間的天數差異.

4. **條件函數：**
   - `IF()`: 如果條件為真，返回一個值，否則返回另一個值。
   - `CASE WHEN`: 用於根據不同條件返回不同的值.

5. **數學函數：**
   - `ABS()`: 返回絕對值。
   - `ROUND()`: 四捨五入到指定的小數位數。
   - `CEIL()` 或 `FLOOR()`: 分別返回不小於和不大於指定數字的整數.

6. **型別轉換函數：**
   - `CAST()`: 將一種數據型別轉換為另一種數據型別。
   - `CONVERT()`: 用於數據型別轉換，具體語法取決於SQL實現.

7. **空值處理函數：**
   - `IS NULL`: 用於檢查是否為NULL。
   - `COALESCE()`: 返回第一個非NULL值.

8. **排序函數：**
   - `ORDER BY`: 用於排序查詢結果。
   - `GROUP BY`: 用於分組查詢結果.

9. **窗口函數：**
   - `ROW_NUMBER()`: 為查詢結果集的行賦予唯一的序號。
   - `RANK()`: 返回排序的排名。
   - `DENSE_RANK()`: 返回排序的排名，如果有相同排名，則排名相同.
