2016-08-12 3 views
0

MySQL Manualから、次のクエリの出力は常に同じであるとは限りません。マニュアルから引用なぜユーザー変数を含む式の評価順序が未定義ですか?

first second third fourth fifth sixth 
    0  1  2  3  4  5 


出力

SET @a := 0; 

SELECT 
@a AS first, 
@a := @a + 1 AS second, 
@a := @a + 1 AS third, 
@a := @a + 1 AS fourth, 
@a := @a + 1 AS fifth, 
@a := @a + 1 AS sixth; 

ただし、ユーザー 変数を含む式の評価順序が定義されていません。

私はその背後にある物語を知りたい。

私の質問は次のとおりです。なぜユーザー変数に関する式の評価順序が未定義ですか?

答えて

0

selectの式の評価順序は未定義です。ほとんどの場合、エラーが発生すると誤った情報が返されるため、変数があるときにのみこれが認識されます。

なぜですか? SQL標準は評価の順序を必要としないので、各データベースは式の評価方法を自由に決めることができます。通常、そのような決定はオプティマイザに委ねられます。

+0

追加するだけで、選択式の評価の順序は通常は左から右になります。人々は 'IF(x、@i、@i:= @i + 1)'のようなものをやろうとすると問題に遭遇し、xが真のときにMySQLが代入式を評価しないと仮定します。 – Uueerdo

+0

危険な理由についてのご意見はありますか? 'case'(これは逐次的であると書かれています)を使うだけで十分ですが、' if() 'と同じセマンティクスがあると思いました。 –

+0

私は100%確信しているわけではありません。具体的には危険です。それは一般的なものです... ... "形式"(より良い言葉がないため)セッション変数の問題に遭遇したときを見ています。 – Uueerdo

0

これは、データベースのオプティマイザの決定に依存します。それが不確かな理由です。しかし、ほとんどの場合、オプティマイザは結果を予測する方法を決定します。

0

TL; DR MySQLユーザ定義変数は、そのように使用することを意図していません。 SQL文は一連の操作ではなく、結果セットを記述します。変数の割り当てが何を意味するのかについてのドキュメントは明確ではありません。しかし、変数を読み書きすることはできません。 SELECT句内の代入順序は定義されていません。また、外側のSELECT句の代入は、出力行のうちの1つに対して実行されます。


あなたのように見えるコードのほとんどは、未定義の動作です。いくつかの賢明な人々は、特定の実装が実際に何を実行しているかを演算子&の実装コードによって実証しています。しかし、その動作は次のリリースでは信頼できません。

documentationをお読みください。同じ変数を読み書きすることは定義されていません。実行されていないときは、読み込み変数はステートメント内で固定されます。割り当ての順序はありません。 DETERMINISTIC関数のみ(値が引数値によって決定される)を持つSELECTの場合、結果は概念的な評価の実行によって定義されます。しかし、その変数とユーザー変数の間には何の関係もありません。どのような割り当てでもの意味は明確ではありません。ドキュメントには「各選択式はクライアントに送信されたときにのみ評価されます」と表示されています。これは、一番外側のSELECT句にの結果セットを入れた場合を除いて、行が「選択」されていることを保証するものではありません。つまり、という意味です。 SELECT内の代入の順序は定義されていません。さらにの場合は、の割り当てがすべての行について概念的に行われている場合は、行の値にのみ依存するため、と同じと同じです。また、割り当て順序が定義されていないため、その行は任意の行になります。つまり、それがドキュメントの意味であると仮定すると、SELECTステートメントで同じ変数から読み書きしないと、最も外側のSELECTの各変数代入が1つの出力行に対して何らかの順序で起こっている。

関連する問題