ปัญหาการดำเนินการแปลก ๆ ใน SQL Server: -100 / -100 * 10 = 0


106
  • หากคุณดำเนินการผลที่ได้คือSELECT -100/-100*100
  • หากคุณดำเนินการผลที่ได้คือSELECT (-100/-100)*1010
  • หากคุณดำเนินการผลที่ได้คือSELECT -100/(-100*10)0
  • หากคุณดำเนินการผลที่ได้คือSELECT 100/100*1010

สถานะBOL :

เมื่อตัวดำเนินการสองตัวในนิพจน์มีระดับความสำคัญของตัวดำเนินการเหมือนกันระบบจะประเมินจากซ้ายไปขวาตามตำแหน่งในนิพจน์

และ

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
ทำไมคุณถึงคิดว่าคุณต้องทำกับบิตคุณกำลังทำงานกับจำนวนเต็ม และจำนวนเต็ม / จำนวนเต็ม = จำนวนเต็ม ดังนั้น -100 / -1000 คือ 0
กันยายน

5
ตกลงฉันเห็นด้วยที่-ดูเหมือนจะทำให้กระแส "ผิด" ถ้าคุณพยายามที่คุณจะได้รับผลที่ตามมา-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. A / -(B * C)ลบล้างมีความสำคัญต่ำกว่าคูณต่อเอกสารดังนั้นผลที่ได้คือ คุณสามารถดูนี้ชัดเจนมากขึ้นโดยใช้ค่าคงลอย: 12e / -13e * 14eเทียบกับ12e / (-13e) * 14eเทียบกับ12e / 13e * 14eเหตุผลได้โดยเริ่มต้นนี้เราพ่นออกเป็นเพราะเรามักคาดหวังลบเอกที่จะกลายเป็นส่วนหนึ่งของตัวอักษรหรืออย่างน้อยมีความสำคัญสูงมาก แต่นั่นไม่ใช่วิธี T-SQL ได้ผล
Jeroen Mostert

คำตอบ:


96

ตามตารางลำดับความสำคัญนี่คือพฤติกรรมที่คาดหวัง ตัวดำเนินการที่มีลำดับความสำคัญสูงกว่า ( /และ*) จะได้รับการประเมินก่อนตัวดำเนินการที่มีลำดับความสำคัญต่ำกว่า (ยูนารี-) ดังนั้นสิ่งนี้:

-100 / -100 * 10

ได้รับการประเมินเป็น:

-(100 / -(100 * 10))

โปรดทราบว่าการทำงานนี้จะแตกต่างจากภาษาโปรแกรมส่วนใหญ่ที่ปฏิเสธเอกมีความสำคัญสูงกว่าคูณและหารเช่นVB , JavaScript


38
ว้าวคุณสมบัติอัญมณีอื่นใน T-SQL :) ฉันเดาว่าฉันต้องตรวจสอบโค้ดทั้งหมดของฉันตอนนี้เพื่อค้นหาจุดบกพร่อง
usr

14
โอ้มนุษย์ นี่คือเลวร้ายยิ่งกว่าต่างๆ PHP ternary ข้อบกพร่องประกอบ bugs.php.net/bug.php?id=61915 คนมีสติคิดอย่างไรว่าตัวดำเนินการยูนารีต้องมีความสำคัญต่ำกว่าไบนารี?
phuclv

12
ความแตกต่างที่แท้จริงอาจถือได้ว่า-เป็นตัวดำเนินการใน-100. ในบางภาษาเป็นส่วนหนึ่งของไวยากรณ์ของจำนวนเต็ม
Barmar

7
-ดังนั้นจึงเป็นข้อผิดพลาดในความสำคัญของพวกเขาเอก
Kevin

4
และผู้ชนะในการออกแบบเคาน์เตอร์ที่ใช้งานง่ายคือ ... : Microsoft - อีกครั้ง
rexkogitans

34

BOL ถูกต้อง -มีความสำคัญต่ำกว่า*ดังนั้น

-A * B

แยกวิเคราะห์เป็น

-(A * B)

การคูณคืออะไรโดยทั่วไปคุณจะไม่สังเกตเห็นสิ่งนี้ยกเว้นเมื่อผสมในตัวดำเนินการไบนารีอีกสองตัวที่มีลำดับความสำคัญเท่ากัน: /และ%(และ%ไม่ค่อยใช้ในนิพจน์สารประกอบเช่นนี้) ดังนั้น

C / -A * B

แยกวิเคราะห์เป็น

C / -(A * B)

อธิบายผลลัพธ์ สิ่งนี้ใช้งานได้ง่ายเนื่องจากในภาษาอื่น ๆ ส่วนใหญ่ unary ลบมีลำดับความสำคัญสูงกว่า*และ/แต่ไม่ใช่ใน T-SQL และมีการจัดทำเอกสารอย่างถูกต้อง

วิธีที่ดี (?) ในการอธิบาย:

SELECT -1073741824 * 2

ก่อให้เกิดการล้นทางคณิตศาสตร์เนื่องจาก-(1073741824 * 2)สร้าง2147483648เป็นตัวกลางซึ่งไม่พอดีกับ an INTแต่

SELECT (-1073741824) * 2

ก่อให้เกิดผลลัพธ์ที่คาดหวัง-2147483648ซึ่งทำ


"ลบ" คือไบนารี ยูนารี-เป็น "ลบ" คนที่พูดอย่าง "ลบ 10" เมื่อหมายถึง "ลบ 10" นั้นไม่แน่ชัด
สรุปยอด

11
@ การสะสม: ความไม่แม่นยำไม่ใช่ของฉัน ตัว-ดำเนินการเมื่อนำไปใช้กับตัวถูกดำเนินการเดียวจะถูกเรียกMINUSในแผนแบบสอบถาม SQL SUBคู่ไบนารีของมันจะถูกเรียกว่า หากคุณต้องการให้ตีความว่า "unary minus" เป็นชวเลขสำหรับ "ตัวดำเนินการยูนารีที่มีความหมายโดยเครื่องหมายลบ" ซึ่งเป็นรูปแบบวากยสัมพันธ์แทนที่จะเป็นการกำหนดความหมาย
Jeroen Mostert

3
"ค่าลบ 10" คือการใช้งานแบบอเมริกันมาตรฐาน (ฉันเชื่อว่า) แต่ไม่ใช่มาตรฐานในสหราชอาณาจักร
Alchymist

12

โปรดสังเกตในเอกสารว่า (อาจจะสวนทางกันโดยสังหรณ์ใจ) ลำดับความสำคัญ- (Negative)เป็นอันดับสาม

เพื่อให้คุณได้รับ:

-(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.