Day 14 - Pro: Stored Procedures, Transactions & User-Defined Functions

Bối cảnh: Hệ thống E-commerce (Thương mại điện tử) - Tương tự Shopee


1. User-defined functions

  • User-defined functions (UDFs): Cho phép tạo các hàm tùy chỉnh để thực hiện các tính toán phức tạp hoặc lặp đi lặp lại.

  • Ví dụ: Tạo hàm tính tổng giá trị đơn hàng sau khi áp dụng thuế:

      CREATE FUNCTION calculate_total_with_tax(total_amount DECIMAL, tax_rate DECIMAL)
      RETURNS DECIMAL
      AS $$
      BEGIN
        RETURN total_amount * (1 + tax_rate);
      END;
      $$ LANGUAGE plpgsql;
    

    Sử dụng hàm:

      SELECT order_id, total_amount, calculate_total_with_tax(total_amount, 0.1) AS total_with_tax
      FROM orders;
    

2. User-defined functions - Example

  • Ví dụ khác: Tạo hàm để kiểm tra xem một sản phẩm có thuộc danh mục "Electronics" hay không:

      CREATE FUNCTION is_electronics(category VARCHAR)
      RETURNS BOOLEAN
      AS $$
      BEGIN
        RETURN category = 'Electronics';
      END;
      $$ LANGUAGE plpgsql;
    

    Sử dụng hàm:

      SELECT product_name, is_electronics(category) AS is_electronics
      FROM products;
    

3. Challenge: User-defined functions

  • Yêu cầu: Tạo hàm để tính tổng số lượng sản phẩm đã bán của một khách hàng cụ thể (customer_id).

4. Solution: User-defined functions

  • Giải pháp:

      CREATE FUNCTION total_quantity_sold(customer_id INT)
      RETURNS INT
      AS $$
      BEGIN
        RETURN (SELECT SUM(quantity) FROM orders WHERE orders.customer_id = total_quantity_sold.customer_id);
      END;
      $$ LANGUAGE plpgsql;
    

    Sử dụng hàm:

      SELECT customer_name, total_quantity_sold(customer_id) AS total_quantity
      FROM customers;
    

5. Transactions

  • Transactions: Một nhóm các câu lệnh SQL được thực hiện như một đơn vị công việc duy nhất.

  • ACID Properties:

    • Atomicity: Tất cả các thao tác trong transaction phải thành công hoặc không có gì xảy ra.

    • Consistency: Dữ liệu phải ở trạng thái hợp lệ trước và sau transaction.

    • Isolation: Các transaction độc lập với nhau.

    • Durability: Kết quả của transaction phải được lưu trữ vĩnh viễn.

  • Ví dụ:

      BEGIN;
      UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
      UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
      COMMIT;
    

6. Challenge: Transactions

  • Yêu cầu: Tạo transaction để cập nhật số lượng sản phẩm trong kho (inventory) sau khi đặt hàng.

7. Solution: Transactions

  • Giải pháp:

      BEGIN;
      UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 101;
      INSERT INTO orders (order_id, customer_id, product_id, quantity, total_amount, order_date)
      VALUES (1001, 1, 101, 1, 50.00, NOW());
      COMMIT;
    

8. Rollbacks

  • Rollback: Hủy bỏ các thay đổi trong transaction nếu có lỗi xảy ra.

  • Ví dụ:

      BEGIN;
      UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
      UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
      ROLLBACK;
    

9. Stored procedures

  • Stored Procedures: Một nhóm các câu lệnh SQL được lưu trữ trong database và có thể được gọi lại nhiều lần.

  • Ví dụ: Tạo stored procedure để thêm một đơn hàng mới:

      CREATE PROCEDURE add_order(
        IN p_order_id INT,
        IN p_customer_id INT,
        IN p_product_id INT,
        IN p_quantity INT,
        IN p_total_amount DECIMAL,
        IN p_order_date DATE
      )
      AS $$
      BEGIN
        INSERT INTO orders (order_id, customer_id, product_id, quantity, total_amount, order_date)
        VALUES (p_order_id, p_customer_id, p_product_id, p_quantity, p_total_amount, p_order_date);
      END;
      $$ LANGUAGE plpgsql;
    

    Gọi stored procedure:

      CALL add_order(1002, 2, 102, 2, 100.00, NOW());
    

10. Challenge: Stored procedures

  • Yêu cầu: Tạo stored procedure để cập nhật giá của một sản phẩm (product_id) và ghi lại lịch sử thay đổi giá.

11. Solution: Stored procedures

  • Giải pháp:

      CREATE PROCEDURE update_product_price(
        IN p_product_id INT,
        IN p_new_price DECIMAL
      )
      AS $$
      BEGIN
        -- Lưu giá cũ vào bảng lịch sử
        INSERT INTO price_history (product_id, old_price, new_price, change_date)
        SELECT product_id, price, p_new_price, NOW()
        FROM products
        WHERE product_id = p_product_id;
    
        -- Cập nhật giá mới
        UPDATE products SET price = p_new_price WHERE product_id = p_product_id;
      END;
      $$ LANGUAGE plpgsql;
    

    Gọi stored procedure:

      CALL update_product_price(101, 55.00);
    

12. Today's slides

  • Tổng kết lại các kiến thức về User-defined functions, Transactions, và Stored Procedures.

  • Slide tham khảo cung cấp ví dụ chi tiết và ứng dụng trong hệ thống E-commerce.


13. Today's summary

  • Hôm nay, bạn đã học:

    • Cách tạo và sử dụng User-defined functions để thực hiện các tính toán tùy chỉnh.

    • Cách quản lý Transactions để đảm bảo tính toàn vẹn dữ liệu.

    • Cách tạo và gọi Stored Procedures để tự động hóa các tác vụ phức tạp.

  • Hẹn gặp lại bạn vào ngày 15 với chủ đề Pro: Indexes, Partitioning & Query Optimization!


14. Today's challenges

  • Thử thách 1: Tạo hàm để tính tổng doanh thu của một khách hàng (customer_id) trong một khoảng thời gian cụ thể.

  • Thử thách 2: Tạo transaction để cập nhật số lượng sản phẩm trong kho (inventory) và thêm đơn hàng mới.

  • Thử thách 3: Tạo stored procedure để xóa một sản phẩm (product_id) và ghi lại lịch sử xóa.