MySQL: @variable против переменной. Какая разница?

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

@variable

а также:

variable

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

5 ответов

Решение

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 (переменная, специфичная для сессии) - нет.

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

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

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

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

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

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

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

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

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

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

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

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

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

Замечание по PL / SQL (Oracle)

Преимущество можно увидеть в Oracle PL / SQL, где эти переменные имеют 3 разных области действия:

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

Мой опыт работы с PL / SQL

Я разработал архитектуру, в которой весь код написан на PL / SQL. Они вызываются из промежуточного программного обеспечения, написанного на Java. Есть два типа промежуточного программного обеспечения. Один для обслуживания звонков от клиента, который также написан на Java. Другой - для звонков из браузера. Клиентские возможности полностью реализованы на JavaScript. Набор команд используется вместо HTML и JavaScript для написания приложения на PL / SQL.

Я искал такое же средство для переноса кодов, написанных на PL / SQL, в другую базу данных. Ближайший, который я нашел, - это Postgres. Но у всех переменных есть функция.

Мнение в отношении MySQL

Я рад видеть, что хотя бы это средство есть в MySQL. Я не думаю, что Oracle создаст такое же средство, доступное в PL / SQL, для хранимых процедур MySQL, поскольку это может повлиять на продажи базы данных Oracle.

Другие вопросы по тегам