551

In another question I posted someone told me that there is a difference between:

@variable

and:

variable

in MySQL. He also mentioned how MSSQL has batch scope and MySQL has session scope. Can someone elaborate on this for me?

Cœur
  • 37,241
  • 25
  • 195
  • 267
aarona
  • 35,986
  • 41
  • 138
  • 186
  • 1
    I am familiar with MsSQL and so the thought never dawned on me to ask such a question. The answers provided here clued me in to something I had no IDEA about!! Thx .. – Ken Apr 20 '20 at 17:50

5 Answers5

669

MySQL has a concept of user-defined variables.

They are loosely typed variables that may be initialized somewhere in a session and keep their value until the session ends.

They are prepended with an @ sign, like this: @var

You can initialize this variable with a SET statement or inside a query:

SET @var = 1

SELECT @var2 := 2

When you develop a stored procedure in MySQL, you can pass the input parameters and declare the local variables:

DELIMITER //

CREATE PROCEDURE prc_test (var INT)
BEGIN
    DECLARE  var2 INT;
    SET var2 = 1;
    SELECT  var2;
END;
//

DELIMITER ;

These variables are not prepended with any prefixes.

The difference between a procedure variable and a session-specific user-defined variable is that a procedure variable is reinitialized to NULL each time the procedure is called, while the session-specific variable is not:

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

As you can see, var2 (procedure variable) is reinitialized each time the procedure is called, while @var2 (session-specific variable) is not.

(In addition to user-defined variables, MySQL also has some predefined "system variables", which may be "global variables" such as @@global.port or "session variables" such as @@session.sql_mode; these "session variables" are unrelated to session-specific user-defined variables.)

Community
  • 1
  • 1
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • 51
    Also take note, that there are global variables available: See `SELECT @@version;` for example. This is also a reason, why using `DELIMITER @@` is not really a good idea. – Mchl Feb 02 '11 at 14:10
  • 17
    it makes new questions for newcomes... is there any difference between "var = var" and "var := var" as in your example? – confiq May 13 '12 at 13:45
  • 13
    Another question for a newcomer. When is it recommended to use `@` vs not? – pixelfreak Nov 27 '12 at 00:46
  • @pixelfreak: what kind of an answer do you expect? – Quassnoi Dec 07 '12 at 09:17
  • 4
    @Quassnoi If you define a user variable as session variables and set a value, wouldn't it contaminate the next stored proc call that happens to use the same variable name? – pixelfreak Dec 07 '12 at 19:23
  • 4
    @Quassnoi Then wouldn't it better **not** to use session variables at all? Why is everyone using it? – pixelfreak Dec 07 '12 at 22:24
  • @pixelfreak: sometimes it's useful to save state between function calls. For instance, it lets running hierarchical queries. – Quassnoi Dec 07 '12 at 23:07
  • 4
    @Quassnoi Right...sometimes. I guess where I am getting at is, is there any harm in not using "@"? – pixelfreak Dec 08 '12 at 07:20
  • @pixelfreak: again, what kind of an answer do you expect for this? – Quassnoi Dec 08 '12 at 13:28
  • 3
    So @variables are `static` variables. Got it. – bobobobo Apr 13 '13 at 20:59
  • 3
    @Mchl `DELIMITER //` is cooler (for C++ programmers). `DELIMITER $$` is for the worldly. – bobobobo Jun 02 '13 at 10:07
  • 83
    @confiq, @Quassnoi: there is one significant difference between `:=` and `=`, and that is that `:=` works as a variable-assignment operator everywhere, while `=` only works that way in `SET` statements, and is a comparison operator everywhere else. So `SELECT @var = 1 + 1;` will leave @var unchanged and return a boolean (1 or 0 depending on the current value of @var), while `SELECT @var := 1 + 1;` will change @var to 2, and return 2. – Dewi Morgan Apr 16 '14 at 23:36
  • @bobobobo, Why two characters? One is easier: `delimiter $`. – Pacerier Apr 16 '15 at 10:18
  • Thank you. clarified my doubt and improved my knowledge well – apr Oct 14 '22 at 09:13
80

In MySQL, @variable indicates a user-defined variable. You can define your own.

SET @a = 'test';
SELECT @a;

Outside of stored programs, a variable, without @, is a system variable, which you cannot define yourself.

The scope of this variable is the entire session. That means that while your connection with the database exists, the variable can still be used.

This is in contrast with MSSQL, where the variable will only be available in the current batch of queries (stored procedure, script, or otherwise). It will not be available in a different batch in the same session.

LarsH
  • 27,481
  • 8
  • 94
  • 152
molf
  • 73,644
  • 13
  • 135
  • 118
  • 2
    Not be confused with session variables, which have the shorthand `SET @@a = 'test';`, cf. http://dev.mysql.com/doc/refman/5.1/en/set-statement.html – RobM Jun 12 '12 at 21:08
  • @RobM, They are called **system** variables, not session variables. – Pacerier Apr 16 '15 at 10:31
  • 1
    @Pacerier: Am I reading the docs wrong? """To indicate explicitly that a variable is a session variable, precede its name by SESSION, @@session., or @@.""" – RobM Apr 25 '15 at 16:32
  • It may be true that you cannot define system variables yourself, but this answer makes it sound like all variables without `@` are system variables. That contradicts Quassnoi's accepted answer, where `var2` is a variable defined by the user, without `@`. Am I missing something? – LarsH Apr 30 '15 at 15:11
  • @LarsH, In Quassnoi's answer, `var2` is a sproc variable, not a session variable. Session variables that are user-defined must start with `@`. – Pacerier May 24 '15 at 23:10
  • 7
    @RobM, You're reading it wrongly. Read through the whole paragraph, not just the paragraph within the bullet point. Simply put, there are two kinds of session variables: 1) User-defined session variables, and 2) **system** -defined session variables. You cannot set a user-defined session variable by using `@@`. For example, `set@@my_var=1`, `set@@session.my_var=1`, and `set session my_var=1` wouldn't work because `my_var` is not a **system** variable, whereas we can do `set@@big_tables=1`, `set@@session.big_tables=1`, and `set session big_tables=1` because `big_tables` is a system variable. – Pacerier May 24 '15 at 23:10
  • @Pacerier: then it sounds like this answer should say something like "*Outside of stored programs,* a `variable`, without @, is a system variable, which you cannot define yourself." I'll make that edit, and hope that if I'm still misunderstanding something, a more knowledgeable person will correct me. – LarsH May 25 '15 at 20:51
  • @LarsH what do you mean by "Outside of stored programs"? That is the only line in the answer that I am having a hard time grasping. Thanks! – Govind Rai Sep 14 '16 at 05:56
  • 1
    @GovindRai: In Quassnoi's answer, `var2` is a variable without a `@` prefix, but it is not a system variable: it's a procedure variable. This is allowed because it's in a stored procedure (a.k.a. stored program). Outside of stored procedures, a variable without `@` is a system variable. – LarsH Sep 14 '16 at 15:58
12

MSSQL requires that variables within procedures be DECLAREd and folks use the @Variable syntax (DECLARE @TEXT VARCHAR(25) = 'text'). Also, MS allows for declares within any block in the procedure, unlike MySQL which requires all the DECLAREs at the top.

While good on the command line, I feel using the set = @variable within stored procedures in MySQL is risky. There is no scope and variables live across scope boundaries. This is similar to variables in JavaScript being declared without the var prefix, which are then the global namespace and create unexpected collisions and overwrites.

I am hoping that the good folks at MySQL will allow DECLARE @Variable at various block levels within a stored procedure. Notice the @ (at sign). The @ sign prefix helps to separate variable names from table column names - as they are often the same. Of course, one can always add an "v" or "l_" prefix, but the @ sign is a handy and succinct way to have the variable name match the column you might be extracting the data from without clobbering it.

MySQL is new to stored procedures and they have done a good job for their first version. It will be a pleasure to see where they take it form here and to watch the server side aspects of the language mature.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Xybo
  • 131
  • 1
  • 4
4

In principle, I use UserDefinedVariables (prepended with @) within Stored Procedures. This makes life easier, especially when I need these variables in two or more Stored Procedures. Just when I need a variable only within ONE Stored Procedure, than I use a System Variable (without prepended @).

@Xybo: I don't understand why using @variables in StoredProcedures should be risky. Could you please explain "scope" and "boundaries" a little bit easier (for me as a newbe)?

Peter
  • 1,224
  • 3
  • 16
  • 28
  • 5
    This violates basic software engineering principles. Please don't write anther line of code until you know exactly what scope is, and why using using global variables is generally a terrible idea. When I took 101 programming classes, as I remember using a global for pretty much anything would result in an automatic "F". There are special exceptions, but as a general rule - just don't do it! – BuvinJ Sep 22 '17 at 13:04
  • Why? - @Variables are absolutely common in every MySQL-Book. – Peter Sep 24 '17 at 14:43
  • Sure, in a "flat" script with no function calls, procedures, triggers, etc. and if you're just going to execute that simple script, or a limited set of commands and then end the session (thereby destroying your globals). It that case, go ahead and use them if you want. But DO NOT use them inside a function! If you simply Google global variables or scope you'll instantly find vast support for the idea that they are universally frowned upon. Here's a starting point: http://wiki.c2.com/?GlobalVariablesAreBad or for a more general explanation: https://en.wikipedia.org/wiki/Global_variable – BuvinJ Sep 24 '17 at 21:44
  • Note that SQL, especially MySQL, is something even very entry level "programmers" use. So your SQL for Dummies books aren't going to address more serious engineering principles. You can, however, write extremely powerful and complex SQL if you know how. If you are going to, you should heed these sorts universal principles to avoid shooting yourself in the foot. – BuvinJ Sep 24 '17 at 21:50
  • Good to know that I do not use global variables. As far as I know, they can be identified by the keyword `GLOBALS` or `@@` before variable name. – Peter Sep 25 '17 at 05:58
  • 2
    In MySQL, @variables are global. This is easily confirmed. Set one outside of a function and then evaluate it inside of one. Conversely, set one inside of a function and evaluate it outside of it. You will see the function does not protect the scope of such. They step on one another's toes. – BuvinJ Sep 25 '17 at 12:24
  • Direct from the primary source: `You can store a value in a user-defined variable in one statement and refer to it later in another statement. This enables you to pass values from one statement to another...User variables are written as @var_name` https://dev.mysql.com/doc/refman/5.7/en/user-variables.html – BuvinJ Sep 25 '17 at 12:26
  • 1
    Using MySQL terminology, `@@GLOBAL` variables are even more "global" and insidious. They cross sessions! `@variables` have "session scope", so at least they they stay confined in that manner. In any normal language that is what you call "global" scope however (when they cross functions etc). The MySQL concept of "global" should perhaps be called "universal", in that it extends beyond the boundaries of the process running it. A "global" cannot normally do that in a standard language, as processes do not share memory space. This stems from the persistent (vs volatile) tendency of SQL. – BuvinJ Sep 25 '17 at 12:34
  • If I designed the MySQL language, I'd allow the use of @var without a declaration, but with implicit local scope, @@GLOBALS would cross functions but have sessions scope, @@PERSISTS would cross sessions. Unfortunately, that's not what they did... – BuvinJ Sep 25 '17 at 12:52
  • The quote from the MySQL source This `enables you to pass values from one statement to another` has an important nuance. The point is to share values across `statements`. For whatever bone headed reason, they extended that to crossing functions. – BuvinJ Sep 25 '17 at 12:59
1

@variable is very useful if calling stored procedures from an application written in Java , Python etc. There are ocassions where variable values are created in the first call and needed in functions of subsequent calls.

Side-note on PL/SQL (Oracle)

The advantage can be seen in Oracle PL/SQL where these variables have 3 different scopes:

  • Function variable for which the scope ends when function exits.
  • Package body variables defined at the top of package and outside all functions whose scope is the session and visibility is package.
  • Package variable whose variable is session and visibility is global.

My Experience in PL/SQL

I have developed an architecture in which the complete code is written in PL/SQL. These are called from a middle-ware written in Java. There are two types of middle-ware. One to cater calls from a client which is also written in Java. The other other one to cater for calls from a browser. The client facility is implemented 100 percent in JavaScript. A command set is used instead of HTML and JavaScript for writing application in PL/SQL.

I have been looking for the same facility to port the codes written in PL/SQL to another database. The nearest one I have found is Postgres. But all the variables have function scope.

Opinion towards @ in MySQL

I am happy to see that at least this @ facility is there in MySQL. I don't think Oracle will build same facility available in PL/SQL to MySQL stored procedures since it may affect the sales of Oracle database.

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 2
    PLSQL (Oracle) out-of-question. Could you focus more on the question and elaborate `@variable` in context of either __MS-SQL or MySQL__, please! – hc_dev Feb 26 '21 at 19:42