Вопрос по mysql, sql – MySQL: @variable против переменной. Какая разница?

473

В другом вопросе я написал, кто-то сказал мне, что есть разница между:

<code>@variable
</code>

а также:

<code>variable
</code>

в MySQL. Он также упомянул, как у MSSQL есть пакетная область, а у MySQL есть область сеанса. Может кто-нибудь уточнить это для меня?

Ваш Ответ

4   ответа
593

MySQL имеет понятиепользовательские переменные.

Они являются свободно типизированными переменными, которые могут быть инициализированы где-то в сеансе и сохраняют свое значение до завершения сеанса.

Они дополнены@ знак, как это:@var

Вы можете инициализировать эту переменную с помощьюSET оператор или внутри запроса:

SET @var = 1

SELECT @var2 := 2

Когда вы разрабатываете хранимую процедуру вMySQLВы можете передать входные параметры и объявить локальные переменные:

DELIMITER //

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

DELIMITER ;

Эти переменные не содержат префиксов.

Разница между процедурной переменной и пользовательской переменной, определенной для сеанса, состоит в том, что переменная процедуры повторно инициализируется вNULL каждый раз, когда процедура вызывается, а переменная, относящаяся к сеансу, не является:

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

Как вы видете,var2 (переменная процедуры) переинициализируется при каждом вызове процедуры, в то время как@var2 (переменная, специфичная для сессии) - нет.

(В дополнение к пользовательским переменным, MySQLalso имеет некоторые предварительно определенные «системные переменные», которые могут быть «глобальными переменными»; такие как@@global.port или «переменные сеанса» такие как@@session.sql_mode; эти «переменные сеанса» не связаны с пользовательскими переменными, специфичными для сессии.)

@confiq, @Quassnoi: есть одно существенное различие между:= а также=и это то, что:= везде работает как оператор присваивания переменных, а= работает только такSET заявления, и является оператором сравнения везде. ТакSELECT @var = 1 + 1; оставит @var без изменений и вернет логическое значение (1 или 0 в зависимости от текущего значения @var), аSELECT @var := 1 + 1; изменит @var на 2 и вернет 2.
Еще один вопрос для новичка. Когда рекомендуется использовать@ против нет?
это создает новые вопросы для новичков ... есть ли разница между & quot; var = var & quot; и & quot; var: = var & quot; как в твоем примере?
@confiq: нет ни одного.
Также обратите внимание, что доступны глобальные переменные: см.SELECT @@version; например. Это также причина, почему использованиеDELIMITER @@ это не очень хорошая идея.
3

я использую UserDefinedVariables (с префиксом @) в хранимых процедурах. Это облегчает жизнь, особенно когда мне нужны эти переменные в двух или более хранимых процедурах. Просто когда мне нужна переменная только в ОДНОЙ хранимой процедуре, тогда я использую системную переменную (без префикса @).

@Xybo: Я не понимаю, почему использование @variables в StoredProcedures должно быть рискованным. Не могли бы вы объяснить "область применения"? и "границы" немного проще (для меня как новичка)?

Зачем? - @Variables абсолютно обычны в каждой книге MySQL.
В MySQL @variables являются глобальными. Это легко подтверждается. Установите один за пределами функции, а затем оцените его внутри одного. И наоборот, установите один внутри функции и оцените его за ее пределами. Вы увидите, что функция не защищает область таких. Они наступают друг другу на пальцы ног.
Это нарушает основные принципы разработки программного обеспечения. Пожалуйста, не пишите другую строку кода, пока вы точно не поймете, что такое область действия и почему использование глобальных переменных - вообще ужасная идея. Когда я взял 101 класс программирования, насколько я помню, использование глобальных программ для чего угодно, приводило к автоматическому & quot; F & quot ;. Есть особые исключения, но, как правило, просто не делайте этого!
Конечно, в «плоском» сценарий без вызовов функций, процедур, триггеров и т. д. и если вы просто собираетесь выполнить этот простой сценарий или ограниченный набор команд, а затем завершить сеанс (тем самым уничтожив глобальные переменные). В таком случае, продолжайте и используйте их, если хотите. Но НЕ используйте их внутри функции! Если вы просто используете глобальные переменные или область действия Google, вы мгновенно найдете широкую поддержку идеи, что они повсеместно осуждаются. Вот отправная точка:wiki.c2.com/?GlobalVariablesAreBad или для более общего объяснения:en.wikipedia.org/wiki/Global_variable
Обратите внимание, что SQL, особенно MySQL, является чем-то даже «программистами» начального уровня. использовать. Таким образом, в ваших книгах по SQL для чайников не рассматриваются более серьезные инженерные принципы. Однако вы можете написать чрезвычайно мощный и сложный SQL, если знаете как. Если вы собираетесь, вы должны прислушиваться к этим универсальным принципам, чтобы не выстрелить себе в ногу.
10

чтобы переменные в процедурах были DECLAREd, и люди используют синтаксис @Variable (DECLARE @TEXT VARCHAR (25) = 'текст'). Кроме того, MS допускает объявления в любом блоке процедуры, в отличие от mySQL, который требует всех DECLARE вверху.

Хотя это хорошо для командной строки, я чувствую, что использую & quot; set = @ variable & quot; в хранимых процедурах в MySQL рискованно. Там нет области видимости и переменные живут за пределами границ области видимости. Это похоже на переменные в JavaScript, которые объявляются без & quot; var & quot; префикс, который затем является глобальным пространством имен и создает неожиданные коллизии и перезаписывает.

Я надеюсь, что хорошие люди в mySQL разрешат DECLARE @Variable на различных уровнях блоков в хранимой процедуре. Обратите внимание на @ (на знак). Префикс @ sign помогает отделить имена переменных от имен столбцов таблицы, поскольку они часто совпадают. Конечно, всегда можно добавить «v» или & lt; l_ & quot; префикс, но знак @ - это удобный и лаконичный способ, чтобы имя переменной совпадало со столбцом, из которого вы могли бы извлекать данные, не забивая их.

MySQL является новым для хранимых процедур, и они сделали хорошую работу для своей первой версии. Будет приятно посмотреть, где они принимают форму, и посмотреть, как развиваются аспекты серверной части языка.

67

В MySQL@variable указывает наопределяемая пользователем переменная, Вы можете определить свой собственный.

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

За пределами хранимых программ,variableбез@, этосистемная переменная, который вы не можете определить сами.

Область действия этой переменной - весь сеанс. Это означает, что, хотя ваше соединение с базой данных существует, переменная все еще может использоваться.

Это отличается от MSSQL, где переменная будет доступна только в текущем пакете запросов (хранимая процедура, сценарий или другое). Он не будет доступен в другой партии в том же сеансе.

@GovindRai: в ответе Quassnoi,var2 переменная без@ префикс, но это не системная переменная: это переменная процедуры. Это разрешено, потому что оно находится в хранимой процедуре (например, в хранимой программе). Вне хранимых процедур, переменная без@ системная переменная
@RobM, они называютсяsystem переменные, а не переменные сеанса.
Не следует путать с переменными сеанса, которые имеют сокращениеSET @@a = 'test';ср.dev.mysql.com/doc/refman/5.1/en/set-statement.html
@RobM, Вы читаете это неправильно. Прочитайте весь абзац, а не только абзац внутри маркированного списка. Проще говоря, существует два вида переменных сеанса: 1) пользовательские переменные сеанса и 2)system& # x200A; -определенные переменные сеанса. Вы не можете установить пользовательскую переменную сеанса, используя@@, Например,[email protected]@my_var=1, [email protected]@session.my_var=1, а такжеset session my_var=1 не будет работать, потому чтоmy_var это неsystem переменная, тогда как мы можем сделать[email protected]@big_tables=1, [email protected]@session.big_tables=1, а такжеset session big_tables=1 так какbig_tables системная переменная
@Pacerier: я неправильно читаю документы? & quot; & quot; Чтобы явно указать, что переменная является переменной сеанса, перед ее именем следует указать SESSION, @@ session. или @@. & quot; & quot;

Похожие вопросы