Trong một câu hỏi khác, tôi đã đăng một người nói với tôi rằng có một sự khác biệt giữa:
@variable
và:
variable
trong MySQL. Ông cũng đề cập đến cách MSSQL có phạm vi lô và MySQL có phạm vi phiên. Ai đó có thể giải thích về điều này cho tôi?
Trong một câu hỏi khác, tôi đã đăng một người nói với tôi rằng có một sự khác biệt giữa:
@variable
và:
variable
trong MySQL. Ông cũng đề cập đến cách MSSQL có phạm vi lô và MySQL có phạm vi phiên. Ai đó có thể giải thích về điều này cho tôi?
Câu trả lời:
MySQL
có khái niệm về các biến do người dùng định nghĩa .
Chúng là các biến được gõ lỏng lẻo có thể được khởi tạo ở đâu đó trong phiên và giữ giá trị của chúng cho đến khi phiên kết thúc.
Chúng được đặt trước một @
dấu hiệu, như thế này:@var
Bạn có thể khởi tạo biến này bằng một SET
câu lệnh hoặc bên trong một truy vấn:
SET @var = 1
SELECT @var2 := 2
Khi bạn phát triển một thủ tục được lưu trữ trong MySQL
, bạn có thể truyền các tham số đầu vào và khai báo các biến cục bộ:
DELIMITER //
CREATE PROCEDURE prc_test (var INT)
BEGIN
DECLARE var2 INT;
SET var2 = 1;
SELECT var2;
END;
//
DELIMITER ;
Các biến này không được đặt trước với bất kỳ tiền tố nào.
Sự khác biệt giữa biến thủ tục và biến do người dùng xác định theo phiên là biến thủ tục được khởi tạo lại cho NULL
mỗi lần thủ tục được gọi, trong khi biến cụ thể theo phiên không phải là:
CREATE PROCEDURE prc_test ()
BEGIN
DECLARE var2 INT DEFAULT 1;
SET var2 = var2 + 1;
SET @var2 = @var2 + 1;
SELECT var2, @var2;
END;
SET @var2 = 1;
CALL prc_test();
var2 @var2
--- ---
2 2
CALL prc_test();
var2 @var2
--- ---
2 3
CALL prc_test();
var2 @var2
--- ---
2 4
Như bạn có thể thấy, var2
(biến thủ tục) được khởi tạo lại mỗi lần thủ tục được gọi, trong khi @var2
(biến cụ thể theo phiên) thì không.
(Ngoài các biến do người dùng xác định, MySQL cũng có một số "biến hệ thống" được xác định trước, có thể là "biến toàn cục", chẳng hạn như @@global.port
"biến phiên", chẳng hạn như @@session.sql_mode
"các biến phiên" này không liên quan đến định nghĩa người dùng theo phiên cụ thể biến.)
SELECT @@version;
ví dụ. Đây cũng là một lý do, tại sao sử dụng DELIMITER @@
không thực sự là một ý tưởng tốt.
@
vs không?
:=
và =
, đó là :=
hoạt động như một toán tử gán biến ở khắp mọi nơi, trong khi =
chỉ hoạt động theo cách đó trong các SET
câu lệnh và là toán tử so sánh ở mọi nơi khác. Vì vậy, SELECT @var = 1 + 1;
sẽ giữ nguyên @var và trả về boolean (1 hoặc 0 tùy thuộc vào giá trị hiện tại của @var), trong khi SELECT @var := 1 + 1;
sẽ thay đổi @var thành 2 và trả về 2.
Trong MySQL, @variable
chỉ ra một biến do người dùng định nghĩa . Bạn có thể xác định của riêng bạn.
SET @a = 'test';
SELECT @a;
Bên ngoài các chương trình được lưu trữ, a variable
, không có @
, là một biến hệ thống , mà bạn không thể tự xác định.
Phạm vi của biến này là toàn bộ phiên. Điều đó có nghĩa là trong khi kết nối của bạn với cơ sở dữ liệu tồn tại, biến vẫn có thể được sử dụng.
Điều này trái ngược với MSSQL, trong đó biến sẽ chỉ khả dụng trong lô truy vấn hiện tại (thủ tục được lưu trữ, tập lệnh hoặc cách khác). Nó sẽ không có sẵn trong một lô khác nhau trong cùng một phiên.
SET @@a = 'test';
, cf dev.mysql.com/doc/refman/5.1/en/set-statement.html
@@
. Ví dụ, set@@my_var=1
, set@@session.my_var=1
, và set session my_var=1
sẽ không hoạt động vì my_var
không phải là một hệ thống biến, trong khi chúng ta có thể làm set@@big_tables=1
, set@@session.big_tables=1
và set session big_tables=1
vì big_tables
là một biến hệ thống.
var2
là một biến không có @
tiền tố, nhưng nó không phải là biến hệ thống: đó là biến thủ tục. Điều này được cho phép bởi vì nó trong một thủ tục được lưu trữ (còn gọi là chương trình được lưu trữ). Ngoài các thủ tục được lưu trữ, một biến không có @
là một biến hệ thống.
MSSQL yêu cầu các biến trong quy trình là DECLAREd và mọi người sử dụng cú pháp @Variable (DECLARE @TEXT VARCHAR (25) = 'text'). Ngoài ra, MS cho phép khai báo trong bất kỳ khối nào trong quy trình, không giống như myQuery yêu cầu tất cả các DECLARE ở trên cùng.
Mặc dù tốt trên dòng lệnh, tôi cảm thấy việc sử dụng "set = @variable" trong các thủ tục được lưu trữ trong myQuery là rủi ro. Không có phạm vi và biến số sống qua ranh giới phạm vi. Điều này tương tự với các biến trong JavaScript được khai báo mà không có tiền tố "var", sau đó là không gian tên toàn cục và tạo ra các xung đột và ghi đè bất ngờ.
Tôi hy vọng rằng những người giỏi tại myQuery sẽ cho phép DECLARE @Variable ở nhiều cấp độ khối khác nhau trong một quy trình được lưu trữ. Lưu ý @ (tại dấu). Tiền tố dấu @ giúp tách các tên biến khỏi tên cột trong bảng - vì chúng thường giống nhau. Tất nhiên, người ta luôn có thể thêm tiền tố "v" hoặc "l_", nhưng dấu @ là một cách tiện dụng và ngắn gọn để có tên biến khớp với cột mà bạn có thể trích xuất dữ liệu mà không bị ghi đè.
MySQL là mới đối với các thủ tục được lưu trữ và họ đã làm một công việc tốt cho phiên bản đầu tiên của họ. Sẽ là một niềm vui khi thấy nơi họ hình thành ở đây và để xem các khía cạnh phía máy chủ của ngôn ngữ trưởng thành.
Về nguyên tắc, tôi sử dụng UserDefinedVariabled (được thêm trước @) trong Thủ tục lưu trữ. Điều này làm cho cuộc sống dễ dàng hơn, đặc biệt là khi tôi cần các biến này trong hai hoặc nhiều Thủ tục lưu trữ. Chỉ khi tôi cần một biến chỉ trong MỘT Thủ tục được lưu trữ, hơn là tôi sử dụng Biến hệ thống (không có tiền tố @).
@Xybo: Tôi không hiểu tại sao sử dụng @variable trong StoredProcedures lại có rủi ro. Bạn có thể vui lòng giải thích "phạm vi" và "ranh giới" dễ dàng hơn một chút (đối với tôi là một người mới)?
@@GLOBAL
các biến thậm chí còn "toàn cầu" và quỷ quyệt hơn. Họ giao nhau! @variables
có "phạm vi phiên", vì vậy ít nhất họ vẫn bị giới hạn theo cách đó. Tuy nhiên, trong bất kỳ ngôn ngữ bình thường nào là phạm vi mà bạn gọi là phạm vi "toàn cầu" (khi chúng giao nhau chức năng, v.v.). Khái niệm "toàn cầu" của MySQL có lẽ nên được gọi là "phổ quát", theo đó nó vượt ra ngoài ranh giới của quá trình vận hành nó. Một "toàn cầu" thường không thể làm điều đó trong một ngôn ngữ tiêu chuẩn, vì các quy trình không chia sẻ không gian bộ nhớ. Điều này xuất phát từ xu hướng liên tục (so với biến động) của SQL.