MySQL:@переменная против.переменная.Какая разница?(Часть 2)
-
06-07-2019 - |
Вопрос
Хорошо, строим из последний вопрос, который я задал, Как Mysql обрабатывает операторwhere в следующем коде:
DELIMITER ;//
DROP PROCEDURE IF EXISTS `test`;//
CREATE PROCEDURE `test`
(
id INT
)
BEGIN
SELECT *
FROM some_table
WHERE id = id;
END;//
Что делает MySQL в этом случае?Рассматривает ли он предложениеwhere как
some_table.id = id
или он относится к этому как
some_table.id = some_table.id
Прямо сейчас я делаю что-то вроде
WHERE id = @id
потому что я не знал, что в MySQL есть переменные сеанса, и он не жаловался, и я подумал, что это явный способ сказать «где этот столбец равен этой переменной».
Кто-то может сказать: «Да..конечно, он рассматривает это как столбец = переменная», но я мог бы легко сказать, где «переменная = столбец». Так как же он с этим справляется?
Решение
Схема именования переменных MySQL на первый взгляд выглядит немного странной.Обычно MySQL различает три типа переменных:
- системные переменные (Глобальный или сессия в области видимости):
@@varname
- определяемые пользователем переменные (они относятся к сеансу):
@varname
- местный переменные в хранимых программах:
varname
Таким образом, конфликты имен, подобные тем, которые вы упомянули выше, возникают только внутри сохраненных программ.Поэтому сначала вам следует попытаться избежать этих конфликтов имен, назначая однозначные имена параметров, например.добавив к параметрам префикс p
такой как pId
.Если MySQL сталкивается с двусмысленностью он будет интерпретировать ссылку как имя переменной (глянь сюда):
[...] Имена локальных переменных не должны должны совпадать с именами столбцов.Если SQL оператор, такой как
SELECT ... INTO
содержит ссылку на column и объявленная локальная переменная с таким же названием, MySQL в настоящее время интерпретирует ссылку как имя переменной. [...]
Формулировка в настоящее время почему-то создается впечатление, что такое поведение может измениться в будущих версиях.
Другие советы
Я уверен, что @ означает, что это переменная в процедуре, а не ссылка на столбец таблицы. Существует только один столбец таблицы с именем id
, поэтому в этом случае он однозначен. Если вы выполняете объединение, вам необходимо добавить префикс:
select *
from table1, table2
where table1.id = @id
and table2.some_field = table1.id
Неважно, где она находится, для переменной всегда будет требоваться префикс @, как в этом запросе:
select id, @id
from table1
первый идентификатор - это однозначный столбец таблицы table1.id, а @id ссылается на переменную хранимой процедуры.