Устанавливать переменную в инструкции SELECT - MySQL

Я использую этот код с ошибкой:

SET @rejects = '';

SELECT *
FROM list
WHERE maker = 1
    AND by_ids IN ('10','11')
    AND country LIKE '%I%'
    AND (
        src IS NULL
        || src NOT IN (@rejects)
        AND checkSrc(src) = 'yes'
        AND SET @rejects = CONCAT(@rejects,',',src)
    );

Что вызывает проблему?

Ответ 1

Проблема заключается в том, что вы не можете смешивать select и set в одном из операторов, обязательно будет синтаксическая ошибка:

select*from t where 1 and [email protected]=1;

ОШИБКА 1064 (42000): У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с 'set @a = 1' в строке 1

Если вы хотите сделать set внутри select, используйте синтаксис двоеточия =. Измените это:

select*from t where 1 and [email protected]=1;

в

select*,@a:=1 from t where 1;

Здесь вы обновляете переменную в каждой строке:

create table t(id int); insert t values(1),(2),(3);
[email protected]=0;
[email protected]:=id from t;
+--------+
| @a:=id |
+--------+
|      1 |
|      2 |
|      3 |
+--------+

И вы даже можете сделать concat:

[email protected]='0';
select @a:=concat(@a,',',id)from t;
+-----------------------+
| @a:=concat(@a,',',id) |
+-----------------------+
| 0,1                   |
| 0,1,2                 |
| 0,1,2,3               |
+-----------------------+

Или concat без ведущего 0:

[email protected]='';
select @a:=concat(@a,if(@a='','',','),id)from t;
+------------------------------------+
| @a:=concat(@a,if(@a='','',','),id) |
+------------------------------------+
| 1                                  |
| 1,2                                |
| 1,2,3                              |
+------------------------------------+

Однако в руководстве явно указано, что это опасно: link

... вам следует никогда присваивать значение переменной пользователя и читать значение внутри одного и того же оператора...

... вы можете получить ожидаемые результаты, но это не гарантировано.

... порядок оценки выражений с использованием пользовательских переменных undefined.

Это также упоминалось на Xaprb.

Наконец, если вы делаете причудливые вещи, например, присваиваете переменные значения и т.д., проверить руководство, чтобы убедиться, что вы понимаете замысловатые механизмы.

Ответ 2

Затем вы можете написать свой запрос следующим образом.

SET @rejects = '';
SELECT @rejects = CONCAT(@rejects,',',src) FROM list WHERE maker = 1 AND by_ids IN ('10','11') AND country LIKE '%I%' AND 
(src IS NULL OR src NOT IN (@rejects) AND checkSrc(src) = 'yes');
SELECT @rejects;