後端相關名詞
NoSQL(Not Only SQL)
- 沒有 Schema,存 JSON 資料進 database (mongodb)
- key-value (一個東西對一大筆資料)
- 不支援 JOIN (非關聯式資料庫) 注:MySQL 是關聯式資料庫
- 存結構不固定的資料
Transaction 交易
- 牽涉到多個 query 的操作
- 實際應用:
- 轉帳
- 購物(確保有庫存)
- transaction 的正確性- ACID
- atmocity 原子性:全部失敗或全部成功(轉錢成功或失敗)
- consistency 一致性:維持資料總數相同(錢的總數一樣)
- isolation 隔離性:多筆交易不互相干擾(不同時進行交易)
- durability 持久性:寫入的資料不會不見
怎麼寫 transaction:
$conn->autocommit(false) //避免重新 commit
$conn->begin_transaction();
$conn->query("UPDATE FROM money SET amount = 20");
$conn->query("UPDATE FROM money SET sum = 10");
$conn->commit();
LOCK
race condition 競爭危害:
當兩個東西同時搶一個東西的時候會發生危害(東西會超賣 ex.門票)
- 利用 Lock 把東西鎖起來,這樣其他人就存取不到了
- 把 Lock 放在 transaction 裡面才有用,要指定 Lock 的 row
- 會有效能損耗
怎麼寫 Lock:
$conn->autocommit(false) //避免重新 commit
$conn->begin_transaction();
$conn->query("SELECT amount FROM products WHERE id = 1 for update");
$conn->commit();
View
- 虛擬 tabel,只能檢視的表格,不能做編輯刪除新增的操作
- 建立後 phpMyadmin 裡面會出現檢視表
- 語法跟 sql query 一樣
- 可以選擇對外給別人看的資料,就不用整個 tabel 都給別人看
怎麼寫 view:
CREATE VIEW view-name AS
SQL // 把建立的 SQL 貼在這裡
範例:
CREATE VIEW order_detail AS
SELECT o.id, o.user_id, u.username, p.name, p.quantity, p.price, o.quantity, o.price as total
FROM
orders AS o
JOIN
users AS u ON o.user_id = u.id
JOIN
products AS p o.product_id = p.id
ORDER BY o.id ASC
補充:
Q:為甚麼 order tabel 跟 product tabel 都有一個 price?
A:因為 product 的 price 有可能修正,order 要存當下賣出的價格
ex. 漲價或特價可能造成 order 當下的價格跟原本 product 訂的價格不一樣
Stored Procedure(SP)
像是 SQL 的 function 一樣
怎麼寫 procedure:
step.1
DELIMITER //
CREATE PROCEDURE procedure-name(參數名, 型態)
BEGIN
SQL
END //
DELIMITER ;
- delimiter:可以決定分界符號是甚麼,在這裡把分界符號改成 "//",寫在 END 後面,才不會出錯,等到完成 procedure,再把分界符號改回 ";"
step.2
在 SQL call 剛剛寫的 procedure
CALL procedure-name(參數)
範例:
DELIMITER //
CREATE PROCEDURE getOrder(id, INT)
BEGIN
SELECT * FROM orders WHERE user_id = id;
END
DELIMITER ;
CALL getOrder(1)
Triggers
在事件(新增、更新、刪除)發生之前或發生之後做點甚麼
怎麼寫 triggers:
DELIMITER //
CREATE TRIGGER trigger-name
BEFORE SQL(甚麼動作之前執行)
FOR EACH ROW
BEGIN
SQL
END
DELIMITER ;
範例:
DELIMITER //
CREATE TRIGGER before_product_update
BEFORE UPDATE ON products
FOR EACH ROW
BEGIN
INSERT INTO products_audit(product_id, name, price, action)
VALUES(OLD.id, OLD.name, OLD.price, "UPDATE")
DELIMITER ;
- before:old 跟 new 都是舊的資料
- after: 可以選擇要舊的還是新的資料
- 這裡用 before,在 products_audit 這個 tabel 顯示的是某個時間點 update 之前的資料
ex. update 前,價錢是 299, update 後價錢為 199,在 products 顯示的是 199 (新的資料),在 products_audit 顯示的是 299 (舊的資料)