SQL Serverでの奇妙な操作の問題:-100 / -100 * 10 = 0


106
  • 実行するSELECT -100/-100*10と結果はになり0ます。
  • 実行するSELECT (-100/-100)*10と結果はになり10ます。
  • 実行するSELECT -100/(-100*10)と結果はになり0ます。
  • 実行するSELECT 100/100*10と結果はになり10ます。

BOLの状態:

式内の2つの演算子の優先順位が同じ場合、それらは式内での位置に基づいて左から右に評価されます。

そして

Level   Operators
  1     ~ (Bitwise NOT)
  2     * (Multiplication), / (Division), % (Modulus)
  3     + (Positive), - (Negative), + (Addition), + (Concatenation), - (Subtraction), & (Bitwise AND), ^ (Bitwise Exclusive OR), | (Bitwise OR)

BOLは間違っていますか、それとも何か不足していますか?そうです-(予想される)の優先順位をオフに投げています。


7
あなたの質問は何ですか?
Ilyes

14
なぜビットを扱う必要があると思いますか?整数を扱っています。そしてinteger / integer = integerです。したがって、-100 / -1000は0です
Sepupic 2019

5
OK、そうです、それ-がフローを「間違った」方向に動かしているように思われます。試してみると-100/(-100)*10結果が出10ます。が方程式の/-に適用されているようで、方程式100*10が決定されています。これがBOLのエラーであるかどうかはわかりませんが、SQL Serverが期待どおりに動作していないことは間違いありません。sql-docsで問題を提起し、その応答を確認することは価値があるかもしれません。おそらく「機能」についてのアドバイスをドキュメントに追加することができます。
Larnu

3
SELECT -100/(-100)*10また、10を返します。これは、計算後にのみ適用される演算子-として扱われるように見えます-100*10
Panagiotis Kanavos

7
A / -B * CですA <div> <negate> B <multiply> C。ドキュメントごとに、Negateは乗算よりも優先順位が低いため、結果はになりA / -(B * C)ます。浮動定数を使用することでこれをより明確に見ることができます:vs . 12e / -13e * 14evs. これが私たちを捨てる理由は、通常、単項マイナスがリテラルの一部になるか、少なくとも非常に優先順位が高いと予想されるためですが、それはT-SQLではありません動作します。12e / (-13e) * 14e12e / 13e * 14e
Jeroen Mostert

回答:


96

優先順位表によると、これ予想される動作です。優先順位の高い演算子(/and *)は、優先順位の低い演算子(単項-)より先に評価されます。したがって、この:

-100 / -100 * 10

次のように評価されます。

-(100 / -(100 * 10))

この動作は、単項否定が乗算や除算よりも優先されるほとんどのプログラミング言語とは異なることに注意してください。 VBJavaScriptます


38
うわー、T-SQLのもう1つのgem機能:)バグを検索するために、今すぐすべてのコードを監査する必要があると思います。
usr

14
ちょっと、あなた。これは、さまざまなPHPの三項演算子のバグ bugs.php.net/bug.php?id=61915よりもさらに悪いものです。単項演算子は2項演算子よりも優先順位が低くなければならないと考える正気な人々は何でしょうか。
phuclv

12
実際の違いは-、がで演算子と見なされるかどうかです-100。一部の言語では、整数の構文の一部です。
Barmar

7
したがって、それらはunaryの優先順位のバグ-です。
ケビン

4
そして、直感に反するデザインの勝者は...:マイクロソフト-もう一度
rexkogitans

34

BOLは正しいです。-はより優先順位が低い*ため、

-A * B

として解析されます

-(A * B)

乗算はそれが何であるか、同じ優先順位で他の2つの2項演算子を混合する場合を除いて、通常はこれに気付きません:/および%%このような複合式ではめったに使用されません)。そう

C / -A * B

として解析されます

C / -(A * B)

結果の説明。他のほとんどの言語では、単項マイナスは*and より優先さ/れますが、T-SQLでは優先されないため、これは直観に反しています。これは正しく文書化されています。

それを説明する素晴らしい(?)方法:

SELECT -1073741824 * 2

ので、算術オーバーフローを生成する-(1073741824 * 2)生成2147483648に適合しない、中間体としてINT、しかし

SELECT (-1073741824) * 2

期待どおりの結果-2147483648が得られます。


「マイナス」はバイナリです。単項-は「負」です。「マイナス10」の意味で「マイナス10」のように言う人は不正確です。
蓄積

11
@累積:不正確さは私のものではありません。-単一のオペランドに適用される演算子は、呼び出されたMINUSSQLクエリ計画に。そのバイナリ対応はと呼ばれSUBます。必要に応じて、「単項マイナス」を「マイナス記号で表される単項演算子」の省略表現として解釈してください。
Jeroen Mostert

3
「negative 10」はアメリカの標準的な使用法です(私はそう思います)が、イギリスでは標準的ではありません。
アルキミスト

12

ドキュメントでは、(おそらく直感的には)優先順位- (Negative)が3番目であることに注意してください。

だからあなたは効果的に得る:

-(100/-(100*10)) = 0

これらを変数に配置すると、乗算の後に発生する単項演算がないため、これが発生することはありません。

したがって、ここではAとBは同じですが、C、D、Eは表示されている結果を示しています(Eには完全なブラケットがあります)。

DECLARE @i1 int, @i2 int, @i3 int;

SELECT @i1 = -100,
       @i2 = -100,
       @i3 = 10;

SELECT @i1/@i2*@i3      [A],
       -100/(-100)*10   [B],
       -100/-100*10     [C],
       -100/-(100*10)   [D],
       -(100/-(100*10)) [E];

A - 10
B - 10
C - 0
D - 0
E - 0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.