MySQL có 2 loại biến chính: **Biến người dùng (User-defined variables / Session variables)** và **Biến cục bộ (Local variables)**. Chúng khác biệt về phạm vi, vòng đời và cách khai báo.
Bảng so sánh nhanh
| Đặc điểm | Biến người dùng (@var) | Biến cục bộ (DECLARE) |
|---|---|---|
| Ký hiệu | Bắt đầu bằng @ (vd: @x) | Không có @ (vd: x) |
| Phạm vi | Session (kết nối) | Trong block BEGIN...END (stored proc, function, trigger) |
| Vòng đời | Tồn tại suốt session, hủy khi ngắt kết nối | Tồn tại trong lần gọi procedure, hủy khi kết thúc |
| Khởi tạo lại | Giữ giá trị giữa các lần gọi proc | Khởi tạo lại mỗi lần gọi proc |
| Khai báo | SET @x = 1 hoặc SELECT @x := 1 | DECLARE x INT DEFAULT 1 |
| Độ kiểu (typing) | Loosely typed (tự động) | Strongly typed (phải khai báo kiểu) |
| Truy cập chéo session | Không (session A không thấy @x của session B) | N/A |
Biến người dùng (User-defined variables)
Cách gán giá trị
-- Cách 1: SET (khuyên dùng)
SET @ten_bien = gia_tri;
SET @x = 10, @y = 'hello', @z = NOW();
-- Cách 2: SELECT với := (phép gán)
SELECT @x := 10;
SELECT @ten := 'Nguyen Van A', @tuoi := 25;
-- ⚠️ Sai: SELECT @x = 10 → Đây là SO SÁNH (trả về 0/1), KHÔNG gán giá trị
SELECT @x = 10; -- Kết quả: 0 (FALSE) vì @x chưa có giá trị
Ví dụ: Giá trị giữ lại giữa các lần gọi
SET @counter = 0;
SELECT @counter := @counter + 1 AS lan_1; -- 1
SELECT @counter := @counter + 1 AS lan_2; -- 2
SELECT @counter := @counter + 1 AS lan_3; -- 3
Biến cục bộ (Local variables)
Chỉ dùng trong Stored Program (Procedure, Function, Trigger)
DELIMITER //
CREATE PROCEDURE DemoLocalVariable()
BEGIN
DECLARE x INT DEFAULT 10; -- Khai báo + khởi tạo
DECLARE y VARCHAR(20); -- Khai báo, mặc định NULL
SET x = x + 5; -- Gán giá trị
SELECT x AS ket_qua; -- 15
END //
DELIMITER ;
CALL DemoLocalVariable(); -- Mỗi lần gọi, x luôn bắt đầu = 10
Ví dụ so sánh trực tiếp trong Stored Procedure
Tạo procedure demo cả 2 loại
DELIMITER //
CREATE PROCEDURE sp_LocalVsUserVariable()
BEGIN
DECLARE local_var INT DEFAULT 10; -- Local variable
SET local_var = local_var + 10; -- 20
SET @user_var = @user_var + 10; -- User variable (cần SET trước)
SELECT local_var AS local_variable;
SELECT @user_var AS user_variable;
END //
DELIMITER ;
Khởi tạo user variable
SET @user_var = 10;
Lần gọi thứ 1
CALL sp_LocalVsUserVariable();
-- local_variable = 20 (10+10)
-- user_variable = 20 (10+10)
Lần gọi thứ 2
CALL sp_LocalVsUserVariable();
-- local_variable = 20 (Khởi tạo lại 10, +10 = 20)
-- user_variable = 30 (Giữ 20 từ lần trước, +10 = 30)
Lần gọi thứ 3
CALL sp_LocalVsUserVariable();
-- local_variable = 20 (Luôn reset về 10+10)
-- user_variable = 40 (Tích lũy: 30+10)
Khi nào dùng loại nào?
Dùng biến người dùng (@var) khi:
- Cần chia sẻ giá trị giữa nhiều stored procedure trong cùng session
- Truyền giá trị từ client → stored proc → client
- Tính toán tích lũy qua nhiều bước/lần gọi
- Debug:
SELECT @var;bất cứ đâu trong session
Dùng biến cục bộ (DECLARE) khi:
- Logic nội bộ stored procedure/function
- Cần kiểu dữ liệu chặt chẽ (INT, VARCHAR(50), DECIMAL(10,2)...)
- Tránh xung đột tên biến giữa các procedure
- Code an toàn, dễ bảo trì, tuân thủ chuẩn SQL
Lưu ý quan trọng
- Biến người dùng không thể dùng trong Function (chỉ Procedure)
- Biến cục bộ phải khai báo ở đầu block BEGIN (trước mọi statement khác)
- Tên biến không phân biệt hoa/thường:
@X=@x - Giá trị mặc định của DECLARE là NULL nếu không có DEFAULT