Search the MySQL manual:
Subscribe to the monthly
MySQL Newsletter!

6.1.4 Переменные пользователя

Для конкретного процесса пользователь может определить локальные переменные, которые в MySQL обозначаются как @variablename. Имя локальной переменной может состоять из буквенно-цифровых символов установленного в данное время алфавита и символов `_', `$', and `.'. Тип кодировки по умолчанию - ISO-8859-1 Latin1, он может быть изменен указанием иного типа в аргументе параметра --default-character-set mysqld (see section 4.6.1 Набор символов, применяющийся для записи данных и сортировки).

Локальные переменные не требуют инициализации. Они содержат значение NULL по умолчанию; в них могут храниться целые числа, вещественные числа или строковые величины. При запуске конкретного процесса все объявленные в нем локальные переменные автоматически активизируются.

Локальную переменную можно объявить, используя синтаксис команды SET:

SET @variable= { integer expression | real expression | string expression }
[,@variable= ...].

Можно также определить значение переменной иным способом, без команды SET. Однако в этом случае в качестве оператора присвоения более предпочтительно использовать оператор `:=', чем оператор `=', так как последний зарезервирован для сравнения выражений, не связанных с установкой переменных:

mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1  | @t2  | @t3  |
+----------------------+------+------+------+
|                    5 |    5 |    1 |    4 |
+----------------------+------+------+------+

Введенные пользователем переменные могут применяться только в составе выражений и там, где выражения допустимы. Заметим, что в область их применения в данное время не включается контекст, в котором явно требуется число, например, условие LIMIT в команде SELECT или выражение IGNORE number LINES в команде LOAD DATA.

Примечание: в команде SELECT каждое выражение оценивается только при отправлении клиенту. Это означает, что в условиях HAVING, GROUP BY, or ORDER BY не следует ссылаться на выражение, содержащее переменные, которые введены в части SELECT этой команды. Например, следующая команда НЕ будет выполняться так, как ожидалось:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

Причина в том, что переменная @aa не будет содержать значения текущей строки, в то время как значение id в предыдущем выражении является строкой.

Действует правило никогда не создавать и не использовать одну и ту же переменную в одном и том же выражении SQL.

User Comments

Posted by Christian Hammers on May 17 2002 6:24am[Delete] [Edit]

Be aware that the following does NOT work:
SET @TABLENAME="db";
SELECT * FROM @TABLENAME;


Posted by Ben Keene on May 17 2002 6:24am[Delete] [Edit]

Be warned that user variables also fail if they
are used in an aggregate function.

For example:

SELECT SUM(@myVal:=someDBfield * 2) AS field1,
SUM(@myVal * 2) AS field2 ...

will not return the answer that you are expecting!
Field2 will return with an incorrect value.

Posted by Alex Pavlovic on December 18 2002 5:29pm[Delete] [Edit]

Would be it useful to add ability to store
lists
of values inside user variables, this could
then
be expanded within IN statements for example.





For example:



SELECT @list:=id FROM t1 WHERE ....
SELECT id FROM t2 WHERE id IN ( @list ) .....





Posted by Ted Farndon on October 31 2002 11:03am[Delete] [Edit]

Re: User variables in aggregate functions... I was
able to use user variables in aggregate functions if I
submitted query twice in the same session / thread.
Perhaps this isn't the most stable method to use
user variables but for the moment it seems to work.
Only time and load will tell if this method holds up
reliably.

Posted by Ernie Hershey on March 25 2003 9:14pm[Delete] [Edit]

You can get a cumulative total this way, like so:

SET @runningTotal:=0;
SELECT *,@runningTotal:=transaction_amount+@runningTotal AS running_total FROM customer_transaction

Posted by [name withheld] on May 30 2003 9:46am[Delete] [Edit]

WOW, THIS IS GREAT!!! I just realized how powerful user variables are, especially when used with the IF command. Together, they basically give SQL some of the capabilities of a low-level procedural language! I'd used variables in MySQL before, but only for use on each row, not for use across multiple rows.

My mind's racing to come up with ways to apply this in my queries, but here's the first one I've come up with. We pull order data out of the database that has individual rows for each item ordered. The invoice number shows up on every row, but the client only wants it on the first line for each invoice. Till now I've had to dump the recordset into a file and process it with perl to take the duplicate invoice numbers out. But now, I can do that right in my SELECT statement:

SET @inv=0;
SELECT IF(@inv=invoice.id,'',@inv:=invoice.id), item.id, ...
FROM ...
WHERE ...
ORDER BY invoice.id, item.id;

Read the IF statement like this: IF the invoice number of the current line equals the variable value, THEN put an empty string in the field, ELSE put the invoice number in the field and set it as the new value for the variable. Note that the ORDER BY clause is important, as it assures that the rows will be processed in proper order - in this case, all the items for each invoice.

Posted by Ruslan Balanukhin on October 29 2003 4:07am[Delete] [Edit]

RE
SELECT @list:=id FROM t1 WHERE ....
SELECT id FROM t2 WHERE id IN ( @list ) .....

HOW ABOUT THIS:

set @list := ',';
select @list := CONCAT(@list, id, ',') from t1 where ....;
select id from t2 where @list LIKE CONCAT('%,', id,',%')

work perfectly

Posted by joshua brown on October 29 2003 7:26am[Delete] [Edit]

even though you cant pass variables to functions requiring numbers (ORDER BY etc), you can create an alias and pass that to the function instead.

eg,

SELECT id,@match:=(if($question = field,1,0)) AS matches FROM table ORDER BY matches DESC LIMIT 20;
note this query was written to basically return relevance on multiple field matches if that helps anyone :-)

Posted by Alex Green on January 20 2004 6:02am[Delete] [Edit]

select @a, table.*
from table
where (@a:=(IF(t_num1=1,10,0)+IF(t_num2=2,5,0))) >5

пЮАНРЮЕР!

Add your own comment.