SQL Server - ทำไมฟังก์ชั่นของหน้าต่างจึงไม่ได้รับอนุญาตให้อัพเดทได้?


10

เมื่อใช้คำสั่งอัปเดตเช่นข้อความด้านล่างฉันได้รับข้อผิดพลาดที่แจ้งให้ฉันทราบ

ฟังก์ชั่นที่มีหน้าต่างสามารถปรากฏได้ในคำสั่ง SELECT หรือ ORDER BY

UPDATE dbo.Dim_Chart_of_Account
SET Account_Order = LAG([Account_Order]) OVER (ORDER BY [Account_SKey])

ฉันรู้ว่านี่สามารถทำงานได้อย่างง่ายดายโดยใช้ cte ที่อัพเดตได้เช่นด้านล่าง

 WITH my_cte AS (
     SELECT [Account_Order], LAG([Account_Order]) OVER (ORDER BY [Account_SKey]) AS acc_order_lag
     FROM Dim_Chart_of_Account
)
UPDATE my_cte
SET [Account_Order] = acc_order_lag

คำถามของฉันคือมีเหตุผลใดบ้างที่ทำให้สิ่งนี้ไม่ได้รับอนุญาตในคำแถลงการปรับปรุงฉันควรหลีกเลี่ยงการใช้ cte ที่อัพเดตได้เป็นวิธีแก้ปัญหาหรือไม่

ความกังวลของฉันคือว่ามีปัญหาเมื่อใช้ฟังก์ชั่นหน้าต่างที่มีคำสั่งปรับปรุงและดังนั้นฉันต้องการที่จะเข้าใจว่านี่เป็นวิธีที่ยอมรับได้หรือควรหลีกเลี่ยง


1
CTE ที่อัพเดตได้นั้นเป็นที่ยอมรับและใช้ได้ ไม่ทราบว่าทำไมจึงไม่อนุญาตให้อัปเดต
ypercubeᵀᴹ

2
บางที Hallowe'en จะได้รับความคุ้มครองบ้างไหม?
Aaron Bertrand

คำตอบ:


5

ไม่อนุญาตให้ใช้ฟังก์ชั่นหน้าต่างในคำสั่ง UPDATE เนื่องจาก UPDATE เข้ากันไม่ได้กับ SELECT หรือ ORDER BY

ฟังก์ชั่นหน้าต่างเป็นเหมือนคำสั่ง SELECT ที่กำหนดขอบเขตซึ่งตรวจสอบแถวที่เกี่ยวข้องอีกครั้งและใช้เงื่อนไขเช่น PARTITION BY และ ORDER BY นอกจากนี้ฟังก์ชั่นหน้าต่างจำนวนมากต้องการ ORDER BY clause (ROW_NUMBER, LAG และ FIRST_VALUE เป็นต้น)

คำสั่ง UPDATE ใช้ SET แทน SELECT ดังนั้น SELECT จึงไม่ได้รับอนุญาตจากทุกที่ในระดับการสืบค้นเดียวกัน SELECT ใด ๆ ที่ปรากฏพร้อมกับ UPDATE จะต้องอยู่ในแบบสอบถามย่อย

ไม่อนุญาตให้ใช้คำสั่งซื้อตามสมควรเมื่อพิจารณาถึงคำสั่ง UPDATE จะไม่สนใจลำดับที่อัปเดตแถว

ไม่มีข้อเสียโดยธรรมชาติในการใช้ CTE หรือแบบสอบถามย่อยอื่น ๆ เป็นวิธีแก้ปัญหาเพื่อรับการปรับปรุงเพื่อใช้ฟังก์ชั่นหน้าต่าง นั่นเป็นวิธีปฏิบัติทั่วไปที่สนับสนุนโดยผู้เชี่ยวชาญ T-SQL อย่าง Itzik Ben-Gan (ดูหน้า 29 ของหนังสือของเขา, Microsoft SQL Server 2012 T-SQL ประสิทธิภาพสูงโดยใช้ฟังก์ชั่นหน้าต่างที่เขาครอบคลุมสถานการณ์ที่แน่นอนนี้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.