後端相關名詞

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 (舊的資料)

#Web #Backend #NoSQL #Transaction #Lock #View #Stored Procedure #Triggers







Related Posts

CS50 Lec7 - SqLite SameTime Update Error - Transaction

CS50 Lec7 - SqLite SameTime Update Error - Transaction

[BE201] 後端中階:ORM 與 Sequelize

[BE201] 後端中階:ORM 與 Sequelize

DE2_115(DAY1)以niosii去控制板子上的led燈

DE2_115(DAY1)以niosii去控制板子上的led燈


Comments