web-dev-qa-db-ja.com

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)
    );

問題の原因は何ですか?

10

問題は、1つのステートメントにselectsetを混在させることができないことです。確かに、構文エラーが発生します。

select*from t where 1 and set@a=1;

エラー1064(42000):SQL構文にエラーがあります。 1行目の「set @ a = 1」の近くで使用する正しい構文については、MySQLサーバーのバージョンに対応するマニュアルを確認してください。

set内でselectを実行する場合は、 コロンが等しい 構文を使用します。これを変える:

select*from t where 1 and set@a=1;

に:

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

変数を更新する方法は次のとおりですそれぞれに行:

create table t(id int); insert t values(1),(2),(3);
set@a=0;
select@a:=id from t;
+--------+
| @a:=id |
+--------+
|      1 |
|      2 |
|      3 |
+--------+

そして、あなたもconcatをすることができます:

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

または、先頭の0なしのconcat

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

ただし、マニュアル明示的にこれは危険であると記載されています: link

...必要があります決してユーザー変数に値を割り当て、同じステートメント内で値を読み取ります...

...期待どおりの結果が得られる可能性がありますが、これは保証されていませんです。

...ユーザー変数を含む式の評価の順序はndefinedです。

これも言及されています Xaprb上

最後に、変数に異なる値型を割り当てるなどの風変わりなことをしている場合は、 マニュアルをチェックしてください 複雑なメカニズムを確実に理解してください。

11
Pacerier

次に、このようにクエリを記述します。

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;
2