# 專題 - 課輔
[TOC]
## 時間
- 每個禮拜六 19:00~21:00
## 學生專案
- https://github.com/Sylvia2002/scholarship
## 資料庫
### 概論
- DBMS (Database Management System)
- 管理資料庫的資訊系統
- ex. MySQL, MSSQL
- database 相較 file system 的優點
- 降低 data 與 app 的相依性
- 統一存取 data 的標準
- 3-tier architecture
- each layer
- database layer
- business logic layer
- UI layer
- ex. web-based app
- 優
- 減輕單台 server 負擔
- 架構分工明確,易於開發和維護
- 缺
- layer 間需額外傳輸成本
- Data Model
- data 存於 database 的規範
- relational data model
- 表格式的方式存 data
- table 由 row, column 組成
- 效率差
- 要 join table,需 O(n*m)
- object-oriented data model
- column 存 object 而不是 value
- hierarchical data model
- 階層式,類似 tree 的方式存 data
- 父、子紀錄以 link 連接
- 
- https://www.geeksforgeeks.org/difference-between-hierarchical-and-network-data-model/
- Key
1. Primary Key
- 具備唯一性(一個 table 只有一個 column 為 PK)
- 可用於唯一識別一個 record
2. Foreign Key
- 會對應到一個 table 的 PK
3. Candiate Key
4. Super Key
- Integrity Rules
1. entity : record 需有 PK
2. referential : FK 對應的 PK 需存在
3. domain : value type 需符合對應的 column,且為 atomic value
- ER Model
- 將實體的關係結構的表示
- component
- entity
- 長方形
- attribute
- 橢圓形
- key
- 橢圓形加底線
- relationship
- 菱形
- 種類
- 一對一
- 一對多
- 多對多
- ER Diagram
- ex.
- 
- ref : https://miro.com/diagramming/how-to-draw-an-er-diagram/
- Normalization
- 優點
- 可以降低重複儲存
- 避免 新增、修改、刪除 的異常
- 缺點
- 降低查詢的效率(因 join)
1. 1NF
- 定義
- 去除多值,所有欄位為 atomic
- 每個 record 有 pk
- ex.
- 
- 有 新增、刪除、修改 異常
- 練習
- stu(snum, name, tel)
2. 2NF
- 定義
- 符合 1NF
- 去除對 pk 的部分相依
- ex.
- 
- 仍有 新增、修改、刪除 異常
- 練習
- room(course_name, teacher_name, time, teacher_birth)
- room(course_name, teacher_name, time)
- teacher(teacher_name, teacher_birth)
3. 3NF
- 定義
- 符合 1NF & 2NF
- 去除非 key 的遞移相依
- ex.
- 
- 練習
- room(course_name, teacher_name, time, teacher_birth, teacher_age)
- room(course_name, teacher_name, time)
- teacher(teacher_name, teacher_birth)
- birth(teacher_birth,teacher_age)
- 練習
- 訂單內容 
- customer(cid, name)
- product(pid, name, price)
- order(oid, cid, pid, date time, num)
- schema
- 依照不同情境,建立資料庫的綱要
- 一對一
- ex. 一個男生只能娶一個女生(兩個 table,男生、女生)
1. 建新的 table : (男生 ID, 女生 ID)
2. 在男生 table 欄位新增 女生 ID 欄位
- 一對多
- ex. 一個老師可以教很多堂課(兩個 table,老師、課程)
1. 建新的 table : (老師 ID, 課程 ID)
- 多對多
- ex. 學生選課
1. 建新的 table : (學生 ID, 課程 ID)
- 練習
1. 

:::spoiler 參考解法
relation

ER Model

:::
2. 
:::spoiler 參考解法

:::
### 語法
- 教學
- https://hackmd.io/@-WjEAPGMTkmWoSDEHpaZuQ/BJaBURrlo/%2FdQr7hSfYS7aSLChtHNEfBw
- DDL (Data Definition Language)
- 建立、調整 DB、table
- 語法
- CREATE : 建立
- ALTER : 更新
- DROP : 刪除
- constraint definition
- 當某一 row 的某一 column 被 reference 成其他 table 的 FK,須確保 referential integrity,故可以設定 column 的 constraint definition
- ON UPDATE, ON DELETE
- NO ACTION : 不能更新該欄或刪除該列。MySQL 的預設
- ex.
- Member(MID, name)
- (1, "tommy")
- (2, "good")
- Song(SID, name)
- (1, "小星星")
- Order(MID, SID)
- (1,1)
- CASCADE : 連帶刪除或更新受影響的 FK
- SET NULL : 將受影響的 column 設為 NULL
- SET DEFAULT : 將受影響的 column 設為預設值
- ex.
```sql=
CREATE TABLE Student (
s_id int(10),
name varchar(10),
t_id int(10),
PRIMARY KEY (s_id),
FOREIGN KEY (t_id) REFERENCES Teacher(t_id) ON DELETE CASCADE ON UPDATE NO ACTION
);
```
- DQL (Data Query Language)
- 查詢 data
- 語法
- SELECT
- operator
- WHERE : 過濾篩選條件
- 可以用 =, LIKE 篩選
- LIKE : `%` 代表 0~N 個字元。1 個 `_` 代表 1 個字元
- 可以用 AND, OR 連接
- DISTINCT : 過濾重複欄位的 record
- GROUP BY
- 依欄位將 record 做分群
- SELECT 的欄位一定會出現於此,但反之不然
- HAVING : 依據 GROUP BY 分群後,再過濾條件
- ORDER BY
- 依欄位值大小做排序
- ASC : 遞增,預設
- DESC : 遞減
- AVG
- 取平均
- SUM
- 加總
- COUNT
- 計算 record 數量
- MAX
- 找出該欄位最大值
- MIN
- 找出該欄位最小值
- join
- 同時需要兩個以上的 table 的 data,故須將多個 table 做集合,過濾條件以 `on` 表示
- inner join
- 只有條件符合才顯示
- 
- ex.
- `select Customers.CustomerID, Orders.OrderID from Orders inner join Customers on Customers.CustomerID = Orders.CustomerID;`
- outer join
- left join
- 以左邊為主,會顯示條件符合 + 剩下的左邊的資料
- ex. `Orders` 196 筆 + 剩下的 `Employees` 1 筆(該 `EmployeeID` 沒有在 `Orders` 裡)
- `SELECT Employees.EmployeeID, Orders.OrderID FROM Employees left join Orders on Employees.EmployeeID = Orders.EmployeeID order by Employees.EmployeeID desc;`
- 
- mulitple left join
- 
- ref : https://stackoverflow.com/questions/4950296/how-to-use-multiple-left-joins-in-sql
- right join
- 改成以右邊為主
- full join
- 顯示條件符合 + 剩下的右邊、左邊 的資料
- cross join
- 列出兩個 table 的所有 records 排列組合
- ex. a table 有 5 筆 records,b table 8 筆:會有 40 筆 records
- ref
- https://ithelp.ithome.com.tw/articles/10215741
- DML (Data Manipulation Language)
- 操作 data
- 語法
- INSERT : 新增一筆 record
- DELETE : 刪除 record
- UPDATE : 更新 record
- 練習
1. 找出所有商品的商品名稱
:::spoiler 參考解法
SELECT ProductName FROM Products;
:::
3. 找出所有商品的名稱及其供應商的名稱
:::spoiler 參考解法
SELECT P.ProductName, S.SupplierName FROM Products P, Suppliers S WHERE P.SupplierID = S.SupplierID;
:::
2. 找出商品的平均單價超過 30 的供應商名稱
:::spoiler 參考解法
SELECT S.SupplierName, AVG(Price) FROM Products P, Suppliers S WHERE P.SupplierID = S.SupplierID GROUP BY P.SupplierID, S.SupplierName HAVING AVG(Price) > 30;
:::
### 線上測試環境
- https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_top&ss=-1
### 畫圖工具
- draw.io
- 
## 網頁開發
### 教學
- https://ycchen.im.ncnu.edu.tw/www2011/
- html
- frontend js
- css
- php
### 概論
- 介紹
- 使用者端送 request (其中可能包含一些資訊) 給 web server,web server response data (ex. html) 給 使用者端,再由 browser (ex. chrome) render 在頁面上
- 架構
- 主要由前後端組成
- 前端
- 主要負責頁面的渲染
- 由 HTML, CSS, JS 組成
- 後端
- 主要負責資料的處理
- 可用 php, nodejs, java web ...
- 開發架構
- MVC
- Model View Controller
- 
- 前後端分離架構
- 將前後端拆分成不同系統,前端(ex. ReactJS)只負責畫面顯示
- 分工更清楚、彈性更高
### HTML
- 介紹
- 有多種 element,讓 browser 去解析
- 語法
- 宣告是 html 的文件,讓 browser 知道如何解析,因可能是 xml 或其他種文件
- `<!DOCTYPE html>`
- element 宣告
- `<element attribute = "" style = "">content</element>`
- `attribute` : 此 element 可設定的屬性
- `style` : 此 element 的排版
- 註解
- `<!-- 我是註解 -->`
- 常用 element
- `html`
- `title` : 頁面標題
- `head`
- `h1`
- `<meta charset="utf-8">`
- `body`
- `div` : block element,會占用一整個區塊的大小
- `span` : inline element,僅占用內容的大小
- `br` : 換行
- `table` : 表格
- `a` : 超連結
- `script` : js script
- `link` : 引入外部連結的資料(ex. css)
- ex.
```html
<!DOCTYPE html>
<html>
<title>Main Page</title>
<head>
<meta charset="utf-8">
<h1>This is main page.</h1>
</head>
<body>
<div>Contents</div>
<div>i am good.</div>
<!--
<span>Contents</span>
<span>i am good</span>
-->
</body>
</html>
```
### CSS
- 介紹
- 將 html 內容做排版
- box model
1. `margin`
- element <b>之間</b> 的距離,隔開相鄰的 element 多少
- 
- 
2. `padding`
- element <b>內部</b> 內容(可能是其他 element)的距離,把 element 往裡面擠多少,同時會把外面的 element 撐大
```html=
<html>
<style>
#test2 {
color : hsl(120, 100%, 25%);
padding: 100px 50px 50px 500px; // 上右下左
}
</style>
<body>
<div id = "test2">
<div id = "test3">test3</div>
</div>
</body>
```
- 
3. `border`
- 邊線本身的設定
- bootstrap
### JS
- ECMAScrpit
- 
- https://ithelp.ithome.com.tw/articles/10206587
- javascript = dynamic + 超級 week type
- strong vs weak type
- weak type lanaguage
- 會自動轉換 type
- ex. js
```js=
let a = 1;
let b = "1";
console.log(a+b); // 11
```
- ex. c/c++ : int 會被轉換成 boolean
- strong type language
- 不會自動轉換 type
- ex. java, c#
- dynamic vs static type
- static
- 需先宣告 vairable type
- dynamic
- 不須,交給編譯器判斷
- 
- js 的 `+` 有 2 個意思:數學、字串
- 當兩方其中有一方是字串,js 就會設定此 `+` 是字串相加
```js=
111 + 222 + "333" + 111 + 222; // 333333111222
```
- 但 php 會分開來 : `+` = 數學, `.` = 字串
```php=
<?php
$v1 = 111;
$v2 = 222;
$x = $v1 + $v2; // 333
$x = $v1 . $v2; // "111222"
?>
```
- js 中,幾乎所有東西都可以相加
- 
- 但 php 雖然是弱型別,但還是有限制
- 
- 解法
- `typescript` : 可讓 code 的型別更嚴謹(雖然不嚴謹還是可以被編譯成 .js),更易讀、維護
- function 加入回傳 type
- function 限制傳入參數 type
- 有 `private`, `public`, `protected`
- scope
- 作用域
1. function scope : variable 只在 function 裡有用
2. global scope
- 在 html 是 window object
- 
`window.aaa; // 5`
- 可以在 function 內宣告全域 : 不宣告(`var`, `let`, `const`)變數就給值
```js=
function test() {
aaa = 5;
}
test();
console.log(aaa);
```
- 在 nodejs 是 global object
3. block scope
- 只作用在大括號之中
- 
- var vs let vs const
- var 缺點
1. 同 scope 內可以重複宣告
- 且不會初始化原本的值
- 
- 可能會不小心改到之前有宣告過的同名的變數
2. 不支援 constant variable(不能被改的)
3. 不支援 block scope
- 
- 因為 var 是 function scope
- 
4. 會產生 global variable
- 
- let 優點
1. 同個 scope 內不可重複宣告
2. 支援 block scope
- 
- 
4. 不會產生 global variable
- 
- 原因
- 
- 這樣的好處是進一步管控了 Global 變數,只能透過 Global Object 去存取,提升程式的嚴謹性和安全性。
- const 優點
- 除了 let 優點再加上 : 定義時必須初始化 (Initialization),且之後不能再更改
- ref
- https://something-about-js-book.onejar99.com/day08
- hosting
- js 會將 variable, function 的 declare 拉到 scope 最上面
- varaiable
```js=
console.log(x);
var x = 5;
// 會變成
var x; // declare
console.log(x);
x = 5; // 這邊是 init
```
- function
```js=
sayHi();
function sayHi(){
console.log('Hi');
}
// 會變成
// 整個 function 都被拉到最上面
function sayHi(){
console.log('Hi');
}
sayHi
```
- function in variable
- 
- 因會變成
- 
- 只有 `var` 會有 undefined 的效果,`let` 和 `const` 雖然也有 hosting,但不會初始化為 undefiend,所以會顯示 `reference error : is not defined`
- function 常用寫法
1. 一般 : 有 hosting
```js=
a("test");
function a(name) {
console.log(name); // test
}
```
2. anonymous function : 無 hosting
```js=
a("test"); // error : a is not a function
var a = function (name) {
console.log(name);
}
```
3. arrow function
- 語法更為簡潔
- 
- 主要和傳統 function 差在 `this`
- 傳統 function 的 this 是指向呼叫他的 object
- 
- ref
- https://ithelp.ithome.com.tw/articles/10207992
- arrow function 的 this 是指向外圍一層的 function(如果一直往外找沒有的話就會指向 window)
- 適合用在 `setTimeout`, `setInterval`
- object 寫法
- 
- 
- function 寫法
- 
- 
- 不為此 scope 產生新的 `arguments`
- 傳統可用 `arguments`,不用管帶入的參數
- 
- 改成這樣
- 
- AJAX
- 藉由 browser 的 web api 達成和 js main thread 達成非同步去 call api,動態去更改網頁中部份內容,而不用重新載入
- callback
- 一個 function 裡面在 call 別的 function,可確保執行順序,目前這個 function 跑完,才去 callback 下一個 function
- 常見於封裝 XMLHttpRequest 的 ajax
- 
- callback hell
- 如果要連續呼叫多個有上下關係的 api,就會變成巢狀不易維護和閱讀
- 
- promise
- 為了解決 callback hell 的問題而產生的 object
- 
- 3 種狀態
- pending : 等待中
- fullfilled : 成功,執行 `then` 裡面的 code
- rejected : 失敗,執行 `catch` 裡面的 code
- ex.
```js=
myName()
.then((res) => console.log('成功:'+ res))
.catch((error) => console.log('失敗:' + error));
```
- 多種寫法
1. `Promise.all` : 一次等待所有 promise 完成才做 `then`,且多隻 api 是同時執行(不是一個執行完換下一個),適合打多隻 api 的,但是若有一隻 error 就不會顯示其他正確的 api 的訊息
- 
- `resolve` : 回傳成功的訊息
- `reject` : 回傳錯誤的訊息
- 如果上下 api 沒有關係,可以用此來加快速度
- 
- 需一個一個等待,較慢
- 
- 一起做,較快
2. `Promise.allSettled` : 和 `all` 差別在,會回傳所有 api 的訊息(就算有 error),回傳時會多帶一個 `status` 代表成功 or 失敗
- 
3. `Promise.race` : 只做先完成的
- 
- 教學
- https://israynotarray.com/javascript/20211128/2950137358/
- async/await
- 解決 promise 還要寫 then, catch,還是有可能變巢狀結構,更易讀
- async
- function 加上 async,代表會回傳一個 promise 的 object
- sync vs async
- sync : 等一行執行完才會到下一行
- ex. nodejs : `fs.readFileSync('./README.md')`
- async : 可先去執行別行,等之前的執行完再執行 callback function
- ex. `fs.readFile('./README.md',readFileFinished);`
- await
- await 會等其後的 promise object 結束(resolved or rejected),再繼續執行
- await 需在 async function 內用
- axios vs ajax vs fetch
- ajax
- 不支援 promise,要用 callback
- fetch
- 基於 promise,所以可以用 then、async+await,js 原生支援,不須引入
- request body 的 data 需先 json.stringify
- axios
- 基於 promise,所以可以用 then、async+await
- 較 fetch 易用
- 可直接 `axios.post`,fetch 需寫在裡面
- 
- 不須 stringify,直接送 json
- request method
- 有分為:get, post, put, delete, update
- get
- 將傳送的資料轉為 query string 加再 url 後面
- 如果用 get 來更新資料會有點危險,因可能別人隨便傳給你連結就點,結果是亂帶資料的
- 或是不小心點到錯誤網址
- 好處是可以藉由 url 傳參數,使用者也方便知道參數
- post
- 將資料放入 request 的 body
- Restful API
- url 內容的部分的 root = api
- 
- 用正確的 method 可以增加 SEO
- get
- 獲得所有實驗室資料
- `/api/lab`
- 獲得單一實驗室資料
- `/api/lab/{lab_id}`
- post
- 建立新實驗室資料
- `/api/lab`
- put
- 更新單一實驗室資料
- `/api/lab/{lab_id}`
- 更新單一實驗室部分資料
- 更新實驗室負責人資料
- `/api/lab/{lab_id}/manager`
- delete
- 刪除單一實驗室資料
- `/api/lab/{lab_id}`
- ref
- https://igouist.github.io/post/2021/05/newbie-2-webapi/
### NodeJS
- 介紹
- nodejs 是一個開源的工具,用於執行 javascript,且提供許多用於網頁後端的套件(ex. http server)
- 優點
- 前後端都用 js,比較好整合
- 大量 IO request 的情境下效能佳
- 
- https://medium.com/@mihaigeorge.c/web-rest-api-benchmark-on-a-real-life-application-ebb743a5d7a3
- npm
- nodejs 預設的套件管理系統
- 可用於更容易安裝、管理套件
- 安裝
- https://nodejs.org/en/download
- 初始化 nodejs 專案
- `cd` 到專案的資料夾
- 初始化 npm
- `npm init`
- ExpressJS
- 介紹
- 是一個基於 nodejs 的輕量級網頁框架,提供許多後端網頁會用到的套件
- 跟其他有完整 MVC 架構的框架相比,Express 其實鬆散(或者說自由)很多,許多地方並沒有強制規範,都只是按照前人的方法或者是慣例來實踐,十個人可能會有十種不同的寫法。
- 教學
- https://hackmd.io/@Heidi-Liu/note-be201-express-node
- 安裝
- `npm install express`
- request
- 預設只能拿到 get 的 query string,所以要拿到 post 的 request.body,就要用 `body-parser` 來 parse request 的 body
- `bodyParser.urlencoded()`
處理 UTF-8 編碼的資料,常見的表單(form)提交
例如:application/x-www-form-urlencoded
- `bodyParser.json()`
處理 JSON 格式的資料
例如:application/json
- `bodyParser.text()`
處理 type 為 text 的資料
例如:text/html, text/css
- `bodyParser.raw()`
處理 type 為 application 的資料
例如:application/pdf, application/zip
- ex.
```js=
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
```
- MVC in express
- 
- controller 就是 express router
- controller 可以再細分成 routing 和 邏輯處理的 middleware
- 所以 `index.js` 引入 `api` 中 routing 檔案只負責路由回傳由 middleware 處理完的資料
- `index.js`
- 引入 routing 的檔案
- routing
- 
- middleware
- 
- 範例
- https://github.com/tommygood/Express_Example
- 存取 db
- 先將 db schema dump into database
- 建立 db user 讓系統可以存取 db
- `CREATE USER '{username}'@'{host}' identified by '{password}';`
- ex. `CREATE USER 'test'@'%' identified by '123';`
- 給權限
- all table
- `GRANT ALL PRIVILEGES ON *.* TO '{username}'@'%';`
- one table, ex. wp table
- `GRANT ALL PRIVILEGES ON wp.* TO '{username}'@'%';`
- `flush privileges;`
- 建立 pool
```js=
const db = require("mariadb"); // 相容於 MySQL
// create pool
const pool = db.createPool({
connectionLimit : 50, // 這個 pool 占用的連線數量
host : 'localhost',
user : 'test',
password : '123',
database : 'scholarship'
});
```
- 可能遇到的問題
- `too many connections`
- 問題描述:因目前資料庫的連線數量超過 `max_connections` 這個最大連線數的變數的大小
- 查看目前資料庫的 `max_connections`
- 
- 查看目前資料庫的總連線數量
- 
- sol
1. 將目前的連線數量大小調整到足夠
2. 將建立的 pool 的連線數量調小
3. 檢查是否有不小心重複建立多個 pool
## Git
### 介紹
- 用於專案的版控,在多人開發專案時助於提升開發效率,降低溝通成本
- 平台
- ex. github, gitlab
- 可以利用 git 將專案的原始碼儲存於平台中
### 概論
- branch
- 一個專案可以有多個 branch,不同 branch 的 code 通常會不同,代表這個 branch 中的專案處在不同的情境
- ex.
- 
- 有 5 個 commit 的 branch
- commit
- 一個 branch 可以有多個 commit,當每次新增或更新完內容後,可以提交一次 commit,就可以將這次修改的部分的 code 更新到所處的 branch
### 常用指令
- 複製專案
- `git clone {repo}`
- 提交這次新的修改
- `git add .`
- 將目前所在的檔案有修正的部分全部新增到暫存區
- `git commit -m "{commit msg}"`
- 將暫存區的檔案更新的內容作為一個 commit 提交到 branch
- `git push {origin} {branch}`
- 將本地的 branch 的新 commit 推到來源端的 branch
- 本地更新雲端上的新的 commit 內容
- `git pull {origin} {branch}`
### 教學
- https://learngitbranching.js.org/?locale=zh_TW