I have started maintaining a bunch of mysql stored procs. Some variables (created with decalare statements) are accessed with the # symbol and others without it. Whats the difference
A variable with the # at the beginning is session variable. It exists until the session end.
Related
Playing around with MariaDB I accidentally found out that it's possible to use # without giving a variable name. I executed following statement:
SELECT # INTO #;
I would have expected a syntax error since the variable name was omitted, but instead it executes just fine. Now I'm wondering what is happening.
How does MariaDB interpret the # symbol in this case? What does this SELECT actually do? Or is it just completely ignored without any further operation?
Although neither the MySQL nor MariaDB documentation specifically mentions it, apparently user-defined variable are allowed to have an empty name. # is the same as #'', and it's treated just like any other variable.
So
SELECT # INTO #;
is like
SELECT #myvar INTO #myvar;
It's a useless statement, since it's just assigning a variable to itself, equivalent to
SET # = #;
This question already has answers here:
MySQL: #variable vs. variable. What's the difference?
(5 answers)
Closed 2 years ago.
I am trying to learn MySQL and after doing some database, I am having the following questions.
When declaring a variable inside a procedure or in the function I can do it like this:
using # sign, like this: SET #varname = varcontent
using DECLARE keyword, like this: DECLARE varname vartype
using directly SET without DECLARE, like this SET varname = varcontent
My doubts are:
what type of syntax is correct, using DECLARE, # or SET?
what would be the correct form of doing it?
Also, I would like if you could recommend some good practices with MySQL.
varname and #varname are two DIFFERENT variables!
#varname - user-defined variable.
Exists always. Even when it was not initialized and/or used, in such case it has NULL value. I.e. it does not need in declaration.
Have no datatype (or it has dynamic datatype). Datatype may be easily changed by assigning the value of another datatype.
This variable has a scope of a connection. I.e. it exists until the connection exists, and its value is not altered until it is altered explicitly. Each connection has its own variavle with the same name, they do not interfere.
For example, you may set it to some value, then use/alter this value in called stored procedure, then use the value altered in the procedure in outer code after the procedure finished.
varname - local (declared) variable
Not exists in anonymous code, exists only within compound (BEGIN-END) code block. Must be declared explicitly at the beginning of the block. Is destroyed at the end of the block. Special type of local variable is function/procedure parameter - it is declared in function/procedure header and exists within the function/procedure code block.
Has definite datatype. Cannot be re-declared.
Has a scope of a block where it is defined.
If a variable and a column with the same name exists in some scope, then the variable has priority and masks the column, so if you need to access the column you must specify table alias.
In most constructions any variable type may be used. But sometimes only one of types may be used - consult User Manual.
1.using # like set #varname= varcontent
This statement initializes user-defined variable with some value.
2.using declare like declare varname vartype
This statement declares local variable. May posess at the beginning of BEGIN-END block. Does not set a value to the variable (it is NULL).
3.using directly set varname=varcontent without declare
Causes an error.
I am using classic ASP and MySQL (using PHP wouldn't change the point of the question).
I need to set a variable over my homepage:
SET block_encryption_mode = 'aes-256-cbc'
I can not set it as global variable as other users are using the server and may use the default block_encryption_mode.
I know I can use the statement using ASP/PHP on the beginning of each webpage, but that seems like using too much resources; every user will execute the SET statement on every page...
Is there a way to SET variable or execute some other SQL statement at the beggining on each session, like an onstart event like ASP has, maybe? Or how could I achieve my goal without executing the query for each user on every page I have?
You can use the init_connect variable.
A string to be executed by the server for each client that connects. The string consists of one or more SQL statements, separated by semicolon characters.
You can also distinguish the users with code like this:
IF (CURRENT_USER() = 'special_crypto_dude#localhost') THEN
SET SESSION block_encryption_mode = 'aes-256-cbc';
END IF;
It is safe to call SET on every page as it executes in orders of microseconds. There is literally no overhead calling SET on already open connection.
Unless you can apply this setting globally, I would not bother. Just set the block_encryption_mode (together with collation and timezone) directly after acquiring the database connection handle.
I'm using MySQL in localhost (in ubuntu and also in windows). I want to set a global variable, and I have tried in all ways but even though I get an "ok" message from mysql, then when I do the "select #var" it allways says "NULL".
I've tried:
set global var=17;
set #global.var=17;
set ##var=17;
Can anyone help me?
Thanks in advance.
ps: I have the SUPER privilege.
The variable name var does not reference a valid system variable. The GLOBAL and SESSION keywords in the SET statement are used for specifying the scope when setting MySQL system variables, not MySQL user variables.
Try for example:
SELECT ##global.net_read_timeout ;
SET GLOBAL net_read_timeout = 45 ;
SELECT ##global.net_read_timeout ;
http://dev.mysql.com/doc/refman/8.0/en/set-statement.html
http://dev.mysql.com/doc/refman/5.5/en/set-statement.html
According to the MySQL 5.0 Reference Manual:
User-defined variables are session-specific. That is, a user variable
defined by one client cannot be seen or used by other clients. All
variables for a given client session are automatically freed when that
client exits.
You could consider using an extension like MySQL Global User Variables UDF (old archived link) to use global (persistent shared) variables.
On MySQL, you cannot create custom global or session system variables but can change existed global or session system variables as shown below:
SET GLOBAL max_connections = 1000; -- Existed global system variable
SET SESSION sql_mode = 'TRADITIONAL'; -- Existed session system variable
And, you can create user-defined(custom) variables which are removed when you exit(log out) a session as shown below. User-defined variables exist only in the current session so they cannot be seen by other sessions unless you use performance_schema.user_variables_by_thread:
SET #first_name = 'John', #last_name = 'Smith';
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?
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.)
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.
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.
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)?
#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.