fork download
  1. -- Tạo bảng accounts
  2. CREATE TABLE accounts (
  3. account_id VARCHAR(20) PRIMARY KEY,
  4. account_name VARCHAR(100) NOT NULL,
  5. balance DECIMAL(15,2) NOT NULL DEFAULT 0,
  6. status ENUM('active', 'frozen', 'closed') DEFAULT 'active',
  7. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  8. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  9. INDEX idx_balance (balance),
  10. CONSTRAINT check_balance CHECK (balance >= 0)
  11. );
  12.  
  13.  
  14. -- Tạo bảng transaction_log để ghi nhật ký
  15. CREATE TABLE transaction_log (
  16. transaction_id INT AUTO_INCREMENT PRIMARY KEY,
  17. from_account VARCHAR(20),
  18. to_account VARCHAR(20),
  19. amount DECIMAL(15,2) NOT NULL,
  20. transaction_type ENUM('transfer', 'deposit', 'withdrawal') NOT NULL,
  21. status ENUM('pending', 'completed', 'failed') NOT NULL,
  22. error_message TEXT,
  23. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  24. FOREIGN KEY (from_account) REFERENCES accounts(account_id),
  25. FOREIGN KEY (to_account) REFERENCES accounts(account_id)
  26. );
  27.  
  28.  
  29. -- Insert dữ liệu mẫu
  30. INSERT INTO accounts (account_id, account_name, balance, status) VALUES
  31. ('ACC001', 'Nguyễn Văn A', 50000.00, 'active'),
  32. ('ACC002', 'Trần Thị B', 25000.00, 'active'),
  33. ('ACC003', 'Lê Văn C', 10000.00, 'active'),
  34. ('ACC004', 'Phạm Thị D', 5000.00, 'frozen'),
  35. ('ACC005', 'Hoàng Văn E', 0.00, 'active');
  36.  
  37.  
  38. -- Kiểm tra dữ liệu
  39. SELECT * FROM accounts;
  40.  
  41. DELIMITER //
  42.  
  43.  
  44. CREATE PROCEDURE TransferMoney(
  45. IN p_from_account VARCHAR(20),
  46. IN p_to_account VARCHAR(20),
  47. IN p_amount DECIMAL(15,2),
  48. OUT p_status VARCHAR(20),
  49. OUT p_message TEXT
  50. )
  51. transfer_proc: BEGIN -- Thêm label 'transfer_proc'
  52. DECLARE v_from_balance DECIMAL(15,2);
  53. DECLARE v_from_status VARCHAR(10);
  54. DECLARE v_to_status VARCHAR(10);
  55.  
  56. -- Xử lý ngoại lệ
  57. DECLARE EXIT HANDLER FOR SQLEXCEPTION
  58. BEGIN
  59. ROLLBACK;
  60. SET p_status = 'ERROR';
  61. SET p_message = 'Database error occurred during transaction';
  62. RESIGNAL;
  63. END;
  64.  
  65. -- Validate input
  66. IF p_amount <= 0 THEN
  67. SET p_status = 'ERROR';
  68. SET p_message = 'Transfer amount must be greater than 0';
  69. LEAVE transfer_proc;
  70. END IF;
  71.  
  72. IF p_from_account = p_to_account THEN
  73. SET p_status = 'ERROR';
  74. SET p_message = 'Cannot transfer to the same account';
  75. LEAVE transfer_proc;
  76. END IF;
  77.  
  78. -- Bắt đầu transaction
  79. START TRANSACTION;
  80.  
  81. -- Kiểm tra tài khoản nguồn
  82. SELECT balance, status INTO v_from_balance, v_from_status
  83. FROM accounts
  84. WHERE account_id = p_from_account
  85. FOR UPDATE; -- Lock row để tránh concurrent modifications
  86.  
  87. IF v_from_balance IS NULL THEN
  88. SET p_status = 'ERROR';
  89. SET p_message = CONCAT('Source account ', p_from_account, ' does not exist');
  90. ROLLBACK;
  91. LEAVE transfer_proc;
  92. END IF;
  93.  
  94. IF v_from_status != 'active' THEN
  95. SET p_status = 'ERROR';
  96. SET p_message = CONCAT('Source account ', p_from_account, ' is not active (status: ', v_from_status, ')');
  97. ROLLBACK;
  98. LEAVE transfer_proc;
  99. END IF;
  100.  
  101. IF v_from_balance < p_amount THEN
  102. SET p_status = 'ERROR';
  103. SET p_message = CONCAT('Insufficient funds. Available: ', v_from_balance, ', Requested: ', p_amount);
  104. ROLLBACK;
  105. LEAVE transfer_proc;
  106. END IF;
  107.  
  108. -- Kiểm tra tài khoản đích
  109. SELECT status INTO v_to_status
  110. FROM accounts
  111. WHERE account_id = p_to_account
  112. FOR UPDATE; -- Lock row
  113.  
  114. IF v_to_status IS NULL THEN
  115. SET p_status = 'ERROR';
  116. SET p_message = CONCAT('Destination account ', p_to_account, ' does not exist');
  117. ROLLBACK;
  118. LEAVE transfer_proc;
  119. END IF;
  120.  
  121. IF v_to_status != 'active' THEN
  122. SET p_status = 'ERROR';
  123. SET p_message = CONCAT('Destination account ', p_to_account, ' is not active (status: ', v_to_status, ')');
  124. ROLLBACK;
  125. LEAVE transfer_proc;
  126. END IF;
  127.  
  128. -- Thực hiện chuyển tiền
  129. UPDATE accounts
  130. SET balance = balance - p_amount
  131. WHERE account_id = p_from_account;
  132.  
  133. UPDATE accounts
  134. SET balance = balance + p_amount
  135. WHERE account_id = p_to_account;
  136.  
  137. -- Commit transaction
  138. COMMIT;
  139.  
  140. SET p_status = 'SUCCESS';
  141. SET p_message = CONCAT('Successfully transferred ', p_amount, ' from ', p_from_account, ' to ', p_to_account);
  142.  
  143. END transfer_proc //
  144.  
  145.  
  146. DELIMITER ;
  147.  
  148.  
  149. -- Test với các trường hợp khác nhau
  150. CALL TransferMoney('ACC001', 'ACC002', 5000.00, @status, @message);
  151. SELECT @status, @message;
  152.  
  153.  
  154. -- Test với tài khoản không tồn tại
  155. CALL TransferMoney('ACC999', 'ACC002', 1000.00, @status, @message);
  156. SELECT @status, @message;
  157.  
  158.  
  159. -- Test với số tiền không hợp lệ
  160. CALL TransferMoney('ACC001', 'ACC002', -100.00, @status, @message);
  161. SELECT @status, @message;
Success #stdin #stdout #stderr 0.01s 5320KB
stdin
Standard input is empty
stdout
|
|
|
stderr
Error: near line 2: near "'active'": syntax error
Error: near line 15: near "'transfer'": syntax error
Error: near line 30: no such table: accounts
Error: near line 39: no such table: accounts
Error: near line 41: near "DELIMITER": syntax error
Error: near line 53: near "DECLARE": syntax error
Error: near line 54: near "DECLARE": syntax error
Error: near line 57: near "DECLARE": syntax error
Error: near line 60: near "SET": syntax error
Error: near line 61: near "SET": syntax error
Error: near line 62: near "RESIGNAL": syntax error
Error: near line 63: cannot commit - no transaction is active
Error: near line 66: near "IF": syntax error
Error: near line 68: near "SET": syntax error
Error: near line 69: near "LEAVE": syntax error
Error: near line 70: near "IF": syntax error
Error: near line 72: near "IF": syntax error
Error: near line 74: near "SET": syntax error
Error: near line 75: near "LEAVE": syntax error
Error: near line 76: near "IF": syntax error
Error: near line 79: near "START": syntax error
Error: near line 82: near "INTO": syntax error
Error: near line 87: near "IF": syntax error
Error: near line 89: near "SET": syntax error
Error: near line 90: cannot rollback - no transaction is active
Error: near line 91: near "LEAVE": syntax error
Error: near line 92: near "IF": syntax error
Error: near line 94: near "IF": syntax error
Error: near line 96: near "SET": syntax error
Error: near line 97: cannot rollback - no transaction is active
Error: near line 98: near "LEAVE": syntax error
Error: near line 99: near "IF": syntax error
Error: near line 101: near "IF": syntax error
Error: near line 103: near "SET": syntax error
Error: near line 104: cannot rollback - no transaction is active
Error: near line 105: near "LEAVE": syntax error
Error: near line 106: near "IF": syntax error
Error: near line 109: near "INTO": syntax error
Error: near line 114: near "IF": syntax error
Error: near line 116: near "SET": syntax error
Error: near line 117: cannot rollback - no transaction is active
Error: near line 118: near "LEAVE": syntax error
Error: near line 119: near "IF": syntax error
Error: near line 121: near "IF": syntax error
Error: near line 123: near "SET": syntax error
Error: near line 124: cannot rollback - no transaction is active
Error: near line 125: near "LEAVE": syntax error
Error: near line 126: near "IF": syntax error
Error: near line 129: no such table: accounts
Error: near line 133: no such table: accounts
Error: near line 138: cannot commit - no transaction is active
Error: near line 140: near "SET": syntax error
Error: near line 141: near "SET": syntax error
Error: near line 143: near "transfer_proc": syntax error
Error: near line 150: near "CALL": syntax error
Error: near line 155: near "CALL": syntax error
Error: near line 160: near "CALL": syntax error