ทำไมคนถึงเกลียดเคอร์เซอร์ SQL มาก? [ปิด]


127

ฉันเข้าใจได้ว่าต้องการหลีกเลี่ยงการใช้เคอร์เซอร์เนื่องจากอยู่เหนือศีรษะและความไม่สะดวก แต่ดูเหมือนว่าจะมีเคอร์เซอร์หวาดกลัว - คลั่งไคล้ที่ร้ายแรงเกิดขึ้นซึ่งผู้คนจะใช้เวลามากเพื่อหลีกเลี่ยงการใช้เคอร์เซอร์

ตัวอย่างเช่นคำถามหนึ่งถามว่าจะทำบางสิ่งที่ไม่สำคัญอย่างเห็นได้ชัดด้วยเคอร์เซอร์อย่างไรและคำตอบที่ยอมรับซึ่งเสนอโดยใช้แบบสอบถามเรียกซ้ำนิพจน์ตารางทั่วไป (CTE) ด้วยฟังก์ชันที่กำหนดเองแบบเรียกซ้ำแม้ว่าจะ จำกัด จำนวนแถวที่สามารถประมวลผลได้ถึง 32 (เนื่องจากขีด จำกัด การเรียกฟังก์ชันแบบเรียกซ้ำในเซิร์ฟเวอร์ sql) สิ่งนี้ทำให้ฉันเป็นทางออกที่น่ากลัวสำหรับการยืนยาวของระบบไม่ต้องพูดถึงความพยายามอย่างมากเพียงเพื่อหลีกเลี่ยงการใช้เคอร์เซอร์ธรรมดา

อะไรคือสาเหตุของความเกลียดชังที่บ้าคลั่งระดับนี้? 'ผู้มีอำนาจที่สังเกตเห็น' บางคนได้ออกคำสั่งต่อต้านเคอร์เซอร์หรือไม่? ความชั่วร้ายที่ไม่อาจบรรยายได้แฝงตัวอยู่ในหัวใจของเคอร์เซอร์ที่ทำลายศีลธรรมของเด็กหรืออะไรบางอย่างหรือไม่?

คำถามวิกิสนใจในคำตอบมากกว่าตัวแทน

ข้อมูลที่เกี่ยวข้อง:

เคอร์เซอร์ Fast Forward ของเซิร์ฟเวอร์ SQL

แก้ไข: ให้ฉันจะแม่นยำมากขึ้น: ผมเข้าใจว่าเคอร์เซอร์ไม่ควรนำมาใช้แทนของการดำเนินงานเชิงสัมพันธ์ปกติ ; นั่นไม่ใช่เกมง่ายๆ สิ่งที่ฉันไม่เข้าใจคือผู้คนออกนอกลู่นอกทางเพื่อหลีกเลี่ยงเคอร์เซอร์เช่นพวกเขามีคูตี้หรืออะไรบางอย่างแม้ว่าเคอร์เซอร์จะเป็นวิธีแก้ปัญหาที่ง่ายกว่าและ / หรือมีประสิทธิภาพมากกว่าก็ตาม มันเป็นความเกลียดชังที่ไร้เหตุผลที่ทำให้ฉันงงงวยไม่ใช่ประสิทธิภาพทางเทคนิคที่ชัดเจน


1
ฉันคิดว่าการแก้ไขของคุณพูดได้ทั้งหมด ... ในเกือบทุกสถานการณ์ (ที่ฉันเจอ) มีวิธีการแทนที่เคอร์เซอร์ด้วยสถานการณ์ตามชุดที่มีประสิทธิภาพดีกว่า คุณบอกว่าไม่มีเกมง่ายๆ แต่คุณเข้าใจความแตกต่าง
StingyJack

7
ฉันชอบแท็กของคำถามนี้!
ก.ย. 332

2
ส่วนที่เกี่ยวกับการ จำกัด CTE แบบเรียกซ้ำ32นั้นเป็นเรื่องไร้สาระ สันนิษฐานว่าคุณกำลังคิดของทริกเกอร์ recursive และสูงสุดของ@@NESTLEVEL 32สามารถตั้งค่าในแบบสอบถามOPTION (MAXRECURSION N)ด้วยค่าเริ่มต้น100และ0ความหมายไม่ จำกัด
Martin Smith

@MartinSmith: ขีด จำกัด เริ่มต้นตอนนี้คือ 100 และสูงสุดคือ 32K sql-server-helper.com/error-messages/msg-310.aspx
Steven A. Lowe

ไม่มันยังคงเหมือนกับตอนที่ฉันแสดงความคิดเห็นและใน SQL Server ทุกเวอร์ชันที่รองรับ CTE แบบเรียกซ้ำ ตามที่ลิงก์ของคุณระบุว่า "เมื่อระบุ 0 จะไม่มีการใช้ขีด จำกัด "
Martin Smith

คำตอบ:


74

"ค่าใช้จ่าย" ที่มีเคอร์เซอร์เป็นเพียงส่วนหนึ่งของ API เคอร์เซอร์คือการทำงานของส่วนต่างๆของ RDBMS ภายใต้ประทุน บ่อยครั้งCREATE TABLEและINSERTมีSELECTคำสั่งและการใช้งานคือการใช้เคอร์เซอร์ภายในที่ชัดเจน

การใช้ "ตัวดำเนินการตามชุด" ระดับที่สูงกว่าจะรวมผลเคอร์เซอร์ให้เป็นชุดผลลัพธ์เดียวซึ่งหมายถึง API ไปมาน้อยลง

เคอร์เซอร์มาก่อนภาษาสมัยใหม่ที่มีคอลเลกชันชั้นหนึ่ง C, COBOL, Fortran ฯลฯ แบบเก่าต้องประมวลผลทีละแถวเนื่องจากไม่มีแนวคิดเรื่อง "คอลเลกชัน" ที่สามารถใช้กันอย่างแพร่หลาย Java, C #, Python เป็นต้นมีโครงสร้างรายการชั้นหนึ่งที่มีชุดผลลัพธ์

ปัญหาที่ช้า

ในบางแวดวงการรวมเชิงสัมพันธ์เป็นเรื่องลึกลับและผู้คนจะเขียนเคอร์เซอร์แบบซ้อนกันแทนที่จะเป็นการรวมแบบธรรมดา ฉันเคยเห็นการดำเนินการลูปซ้อนที่ยิ่งใหญ่อย่างแท้จริงซึ่งเขียนเป็นเคอร์เซอร์จำนวนมาก การเอาชนะการเพิ่มประสิทธิภาพ RDBMS และวิ่งช้าจริงๆ

เขียน SQL ใหม่อย่างง่ายเพื่อแทนที่เคอร์เซอร์ลูปที่ซ้อนกันด้วยการรวมและการวนเคอร์เซอร์แบบแบนเดียวสามารถทำให้โปรแกรมทำงานได้ในครั้งที่ 100 [พวกเขาคิดว่าฉันเป็นเทพเจ้าแห่งการเพิ่มประสิทธิภาพ สิ่งที่ฉันทำคือแทนที่ลูปที่ซ้อนกันด้วยการรวม ยังคงใช้เคอร์เซอร์อยู่]

ความสับสนนี้มักนำไปสู่คำฟ้องของเคอร์เซอร์ อย่างไรก็ตามมันไม่ใช่เคอร์เซอร์ แต่เป็นการใช้เคอร์เซอร์ในทางที่ผิดที่เป็นปัญหา

ปัญหาขนาด

สำหรับชุดผลลัพธ์ที่ยิ่งใหญ่จริงๆ (เช่นการทิ้งตารางไปยังไฟล์) เคอร์เซอร์เป็นสิ่งจำเป็น การดำเนินการตามชุดไม่สามารถทำให้ชุดผลลัพธ์ที่มีขนาดใหญ่มากเป็นชุดเดียวในหน่วยความจำได้

ทางเลือก

ฉันพยายามใช้เลเยอร์ ORM ให้มากที่สุด แต่นั่นมีวัตถุประสงค์สองประการ ขั้นแรกเคอร์เซอร์ถูกจัดการโดยคอมโพเนนต์ ORM ประการที่สอง SQL ถูกแยกออกจากแอปพลิเคชันเป็นไฟล์กำหนดค่า ไม่ใช่ว่าเคอร์เซอร์ไม่ดี นั่นคือการเข้ารหัสการเปิดปิดและการดึงข้อมูลทั้งหมดนั้นไม่ใช่การเขียนโปรแกรมเพิ่มมูลค่า


3
"เคอร์เซอร์คือการทำงานของ RDBMS ภายใต้ประทุน" ถ้าคุณหมายถึง SQL Server โดยเฉพาะโอเคดีฉันไม่รู้เรื่องนั้น แต่ฉันได้ทำงานภายในของ RDBMS หลายตัว (และ ORDBMS) (ภายใต้ Stonebraker) และไม่มีใครทำเช่นนั้น ตัวอย่างเช่น: Ingres ใช้จำนวนเท่าใดในการ "เซตผลลัพธ์" ของทูเปิลภายใน
Richard T

@Richard T: ฉันกำลังหาข้อมูลมือสองเกี่ยวกับแหล่ง RDBMS ฉันจะแก้ไขคำชี้แจง
ล็อต

2
"ฉันเคยเห็นการดำเนินการลูปซ้อนที่ยิ่งใหญ่อย่างแท้จริงซึ่งเขียนเป็นเคอร์เซอร์จำนวนมาก" ฉันก็เห็นพวกเขาเช่นกัน มันยากที่จะเชื่อ
RussellH

41

เคอร์เซอร์ทำให้ผู้คนใช้ความคิดขั้นตอนมากเกินไปกับสภาพแวดล้อมแบบกำหนด

และพวกเขาช้า !!!

จากSQLTeam :

โปรดทราบว่าเคอร์เซอร์เป็นวิธีที่ช้าที่สุดในการเข้าถึงข้อมูลภายใน SQL Server ควรใช้เมื่อคุณต้องการเข้าถึงทีละแถวเท่านั้น เหตุผลเดียวที่ฉันคิดได้คือการเรียกใช้กระบวนงานที่เก็บไว้ในแต่ละแถว ในบทความเคอร์เซอร์ผลงานของผมค้นพบว่าเคอร์เซอร์ที่มีมานานกว่าสามสิบครั้งช้ากว่าตามกำหนดทางเลือก


6
บทความนั้นมีอายุ 7 ปีคุณคิดว่าบางทีสิ่งต่างๆอาจมีการเปลี่ยนแปลงในระหว่างนี้?
Steven A.Lowe

1
ฉันยังคิดว่าเคอร์เซอร์ช้ามากและโดยทั่วไปควรหลีกเลี่ยง อย่างไรก็ตามหาก OP อ้างถึงคำถามที่ฉันคิดว่าเขาเป็นแสดงว่าเคอร์เซอร์เป็นวิธีแก้ปัญหาที่ถูกต้อง (สตรีมมิ่งบันทึกทีละรายการเนื่องจากข้อ จำกัด ของหน่วยความจำ)
rmeador

บทความที่อัปเดตไม่ได้แก้ไขการวัดความเร็วสัมพัทธ์ แต่มีการเพิ่มประสิทธิภาพและทางเลือกที่ดีบางอย่าง โปรดทราบว่าบทความต้นฉบับบอกว่าเคอร์เซอร์เร็วกว่าในขณะที่ลูป 50 เท่าซึ่งน่าสนใจ
Steven A. Lowe

6
@BoltBait: โดยส่วนตัวแล้วฉันคิดว่าถ้าคุณทำคำยืนยันแบบคลุมเครือคุณจะอายุ 45 ปีไม่ได้จริงๆ :-P
Steven A. Lowe

4
@BoltBait: คุณเด็ก ๆ ออกจากสนามหญ้าของฉัน!
Steven A. Lowe

19

มีคำตอบด้านบนซึ่งระบุว่า "เคอร์เซอร์เป็นวิธีที่ช้าที่สุดในการเข้าถึงข้อมูลภายใน SQL Server ... เคอร์เซอร์ช้ากว่าทางเลือกที่ตั้งค่าไว้มากกว่าสามสิบเท่า"

คำแถลงนี้อาจเป็นจริงในหลาย ๆ สถานการณ์ แต่ในฐานะที่เป็นคำชี้แจงแบบครอบคลุมจึงเป็นปัญหา ตัวอย่างเช่นฉันได้ใช้ประโยชน์จากเคอร์เซอร์ในสถานการณ์ที่ฉันต้องการดำเนินการอัปเดตหรือลบที่มีผลต่อหลายแถวของตารางขนาดใหญ่ซึ่งได้รับการอ่านค่าการผลิตคงที่ การรันโพรซีเดอร์ที่เก็บไว้ซึ่งทำการอัปเดตทีละแถวจะเร็วกว่าการดำเนินการตามชุดเนื่องจากการดำเนินการตามชุดขัดแย้งกับการดำเนินการอ่านและจบลงทำให้เกิดปัญหาการล็อกที่น่ากลัว (และอาจฆ่าระบบการผลิตทั้งหมด ในกรณีที่รุนแรง)

ในกรณีที่ไม่มีกิจกรรมฐานข้อมูลอื่น ๆ การดำเนินการตามชุดจะเร็วกว่าในระดับสากล ในระบบการผลิตนั้นขึ้นอยู่กับ


1
ดูเหมือนข้อยกเว้นที่พิสูจน์กฎ
Joel Coehoorn

6
@ [Joel Coehoorn]: ฉันไม่เคยเข้าใจคำพูดนั้นเลย
Steven A. Lowe

2
@ [Steven A. Lowe] phrases.org.uk/meanings/exception-that-proves-the-rule.htmlเข้าใจข้อยกเว้นว่า "สิ่งที่เหลืออยู่" และโปรดทราบว่ากฎในที่นี้คือสิ่งที่ชอบ "ในสถานการณ์ส่วนใหญ่เคอร์เซอร์คือ ไม่ดี"
David Lay

1
@delm: ขอบคุณสำหรับลิงค์ตอนนี้ฉันเข้าใจวลีนี้แม้แต่น้อย!
Steven A. Lowe

5
@ [Steven A. Lowe] โดยพื้นฐานแล้วมันบอกว่าถ้าคุณ "แหกกฎ" ด้วยกรณีย่อยจะต้องมีกฎทั่วไปที่จะทำลายกฎก็มีอยู่ เช่นจากลิงก์: ("หากเรามีคำสั่งเช่น" การเข้าชมไม่เสียค่าใช้จ่ายในวันอาทิตย์ "เราสามารถสันนิษฐานได้อย่างสมเหตุสมผลว่าตามกฎทั่วไปค่าเข้าชมจะถูกเรียกเก็บเงิน")
ทอด

9

เคอร์เซอร์มักจะถูกใช้โดยเริ่มต้นนักพัฒนา SQL ในที่ที่การดำเนินการตามชุดจะดีกว่า โดยเฉพาะอย่างยิ่งเมื่อผู้คนเรียนรู้ SQL หลังจากเรียนรู้ภาษาการเขียนโปรแกรมแบบเดิมแล้วความคิด "วนซ้ำในบันทึกเหล่านี้" มีแนวโน้มที่จะทำให้ผู้คนใช้เคอร์เซอร์อย่างไม่เหมาะสม

หนังสือ SQL ที่ร้ายแรงที่สุด ได้แก่ บทที่เกี่ยวกับการใช้เคอร์เซอร์ คำที่เขียนดีทำให้ชัดเจนว่าเคอร์เซอร์มีตำแหน่ง แต่ไม่ควรใช้สำหรับการดำเนินการตามชุด

เห็นได้ชัดว่ามีสถานการณ์ที่เคอร์เซอร์เป็นตัวเลือกที่ถูกต้องหรืออย่างน้อยก็เป็นทางเลือกที่ถูกต้อง


9

เครื่องมือเพิ่มประสิทธิภาพมักไม่สามารถใช้พีชคณิตเชิงสัมพันธ์เพื่อเปลี่ยนปัญหาเมื่อใช้วิธีเคอร์เซอร์ บ่อยครั้งที่เคอร์เซอร์เป็นวิธีที่ดีในการแก้ปัญหา แต่ SQL เป็นภาษาที่เปิดเผยและมีข้อมูลมากมายในฐานข้อมูลตั้งแต่ข้อ จำกัด ไปจนถึงสถิติและดัชนีซึ่งหมายความว่าเครื่องมือเพิ่มประสิทธิภาพมีตัวเลือกมากมายในการแก้ปัญหา ปัญหาในขณะที่เคอร์เซอร์ค่อนข้างชี้นำการแก้ปัญหาอย่างชัดเจน


8

ในเคอร์เซอร์ Oracle PL / SQL จะไม่ส่งผลให้เกิดการล็อกตารางและสามารถใช้การรวบรวม / การดึงข้อมูลจำนวนมากได้

ใน Oracle 10 มักใช้เคอร์เซอร์โดยปริยาย

  for x in (select ....) loop
    --do something 
  end loop;

ดึงข้อมูลทีละ 100 แถวโดยปริยาย นอกจากนี้ยังสามารถรวบรวม / ดึงข้อมูลจำนวนมากได้อย่างชัดเจน

อย่างไรก็ตามเคอร์เซอร์ PL / SQL เป็นทางเลือกสุดท้ายให้ใช้เมื่อคุณไม่สามารถแก้ปัญหากับ SQL แบบตั้งค่าได้

อีกเหตุผลหนึ่งคือการขนานฐานข้อมูลจะทำให้คำสั่งที่ใช้ชุดใหญ่ขนานกันได้ง่ายกว่ารหัสความจำเป็นแบบแถวต่อแถว เป็นเหตุผลเดียวกับที่การเขียนโปรแกรมเชิงฟังก์ชันเป็นที่นิยมมากขึ้นเรื่อย ๆ (Haskell, F #, Lisp, C # LINQ, MapReduce ... ) การเขียนโปรแกรมเชิงฟังก์ชันทำให้การขนานง่ายขึ้น จำนวนซีพียูต่อคอมพิวเตอร์เพิ่มขึ้นดังนั้นการขนานจึงกลายเป็นปัญหามากขึ้นเรื่อย ๆ


6

โดยทั่วไปเนื่องจากบนฐานข้อมูลเชิงสัมพันธ์ประสิทธิภาพของโค้ดที่ใช้เคอร์เซอร์จะมีลำดับความสำคัญต่ำกว่าการดำเนินการตามชุด


คุณมีเกณฑ์มาตรฐานหรือข้อมูลอ้างอิงสำหรับสิ่งนี้หรือไม่? ฉันไม่ได้สังเกตเห็นการลดลงของประสิทธิภาพที่รุนแรงเช่นนี้ ... แต่บางทีตารางของฉันอาจมีแถวไม่เพียงพอสำหรับเรื่องนี้ (โดยปกติจะเป็นล้านหรือน้อยกว่า)?
Steven A.Lowe

เดี๋ยวก่อนฉันเข้าใจว่าคุณหมายถึงอะไร - แต่ฉันจะไม่สนับสนุนการใช้เคอร์เซอร์ในการทำงานของชุด แต่จะไม่สุดขั้วเพื่อหลีกเลี่ยงเคอร์เซอร์
Steven A. Lowe

3
ฉันจำได้ว่าครั้งแรกที่ฉันทำ SQL เราต้องนำเข้าไฟล์ข้อมูลรายวัน 50k จากเมนเฟรมไปยังฐานข้อมูล SQL Server ... ฉันใช้เคอร์เซอร์และพบว่าการนำเข้าใช้เวลาประมาณ 26 ชั่วโมงโดยใช้เคอร์เซอร์ .. เมื่อฉันเปลี่ยนเป็นการดำเนินการตามชุดขั้นตอนนี้ใช้เวลา 20 นาที
Charles Bretana

6

คำตอบข้างต้นยังไม่ได้เน้นความสำคัญของการล็อกมากพอ ฉันไม่ใช่แฟนตัวยงของเคอร์เซอร์เพราะมันมักจะส่งผลให้ล็อคระดับโต๊ะ


1
ใช่ขอบคุณ! หากไม่มีตัวเลือกในการป้องกัน (อ่านอย่างเดียวส่งต่อเท่านั้น ฯลฯ ) พวกเขาจะดำเนินการเช่นเดียวกับการดำเนินการ (เซิร์ฟเวอร์ sql) ที่ดำเนินการเพื่อครอบครองหลายแถวและหลายหน้าของแถว
Steven A.Lowe

?? นั่นเป็นปัญหากับกลยุทธ์การล็อคของคุณไม่ใช่เคอร์เซอร์ แม้แต่คำสั่ง SELECT ก็จะเพิ่มการล็อกการอ่าน
อดัม

3

สำหรับสิ่งที่คุ้มค่าฉันได้อ่านว่าตำแหน่ง "หนึ่ง" ที่เคอร์เซอร์จะออกมาทำงานคู่กันตามชุดนั้นอยู่ในผลรวมทั้งหมด บนตารางขนาดเล็กความเร็วในการสรุปแถวตามลำดับตามคอลัมน์จะสนับสนุนการดำเนินการตามชุด แต่เมื่อตารางเพิ่มขนาดของแถวเคอร์เซอร์จะเร็วขึ้นเพราะสามารถนำมูลค่ารวมที่รันไปยังรอบถัดไปของ ห่วง ตอนนี้ที่คุณควรทำผลรวมเป็นอาร์กิวเมนต์ที่แตกต่างกัน ...


1
หากคุณหมายถึงการ "รันผลรวม" การรวมบางประเภท (ต่ำสุดสูงสุดผลรวม) DBMS ที่มีความสามารถใด ๆ จะเอาชนะกางเกงออกจากโซลูชันที่ใช้เคอร์เซอร์ฝั่งไคลเอ็นต์หากเพียงเพราะฟังก์ชันทำงานในเครื่องยนต์และ ไม่มีไคลเอนต์ <--> เซิร์ฟเวอร์เหนือศีรษะ บางที SQL Server อาจไม่มีความสามารถ?
Richard T

1
@ [Richard T]: เรากำลังพูดถึงเคอร์เซอร์ฝั่งเซิร์ฟเวอร์ซึ่งอยู่ในขั้นตอนการจัดเก็บไม่ใช่เคอร์เซอร์ฝั่งไคลเอ็นต์ ขอโทษสำหรับความสับสน!
Steven A. Lowe

2

ฉันเห็นด้วยกับบทความในหน้านี้:

http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-cursor-removal.aspx


บทความดีๆ ผู้เขียนควรกล่าวด้วยว่าในขณะที่ลูปมีประสิทธิภาพน้อยกว่าเคอร์เซอร์มาก
Steven A. Lowe

2

นอกเหนือจากปัญหาด้านประสิทธิภาพ (ไม่) แล้วฉันคิดว่าเคอร์เซอร์ล้มเหลวครั้งใหญ่ที่สุดคือพวกเขาเจ็บปวดในการดีบัก โดยเฉพาะอย่างยิ่งเมื่อเทียบกับโค้ดในแอปพลิเคชันไคลเอนต์ส่วนใหญ่ที่การดีบักมีแนวโน้มที่จะค่อนข้างง่ายและคุณสมบัติภาษามักจะง่ายกว่ามาก ในความเป็นจริงฉันยืนยันว่าเกือบทุกอย่างที่ทำใน SQL ด้วยเคอร์เซอร์น่าจะเกิดขึ้นในแอปไคลเอนต์ตั้งแต่แรก


2
SQL มีความเจ็บปวดในการดีบักแม้ว่าจะไม่มีเคอร์เซอร์ก็ตาม เครื่องมือทีละขั้นตอน MS SQL ใน Visual Studio ดูเหมือนจะไม่ชอบฉัน (พวกมันแฮงค์มากหรือไม่ได้เดินทางไปที่จุดพักเลย) ดังนั้นฉันจึงมักจะลดเป็นคำสั่ง PRINT ;-)
Steven A. Lowe

1

คุณสามารถโพสต์ตัวอย่างเคอร์เซอร์นั้นหรือลิงก์ไปยังคำถามได้หรือไม่ อาจมีวิธีที่ดีกว่า CTE แบบเรียกซ้ำ

นอกเหนือจากความคิดเห็นอื่น ๆ แล้วเคอร์เซอร์เมื่อใช้ไม่ถูกต้อง (ซึ่งมักจะเป็น) จะทำให้เกิดการล็อกหน้า / แถวโดยไม่จำเป็น


1
มีวิธีที่ดีกว่า - เคอร์เซอร์ประหลาด ;-)
Steven A. Lowe

1

คุณอาจสรุปคำถามของคุณได้หลังจากย่อหน้าที่สองแทนที่จะเรียกคนว่า "บ้า" เพียงเพราะพวกเขามีมุมมองที่แตกต่างจากที่คุณทำและพยายามล้อเลียนมืออาชีพที่อาจมีเหตุผลที่ดีมากในการรู้สึกแบบนั้น

สำหรับคำถามของคุณในขณะที่มีบางสถานการณ์ที่อาจมีการเรียกเคอร์เซอร์ แต่จากประสบการณ์ของฉันนักพัฒนาตัดสินใจว่าเคอร์เซอร์ "ต้อง" ใช้ FAR บ่อยกว่าที่เป็นจริง โอกาสที่มีคนทำผิดพลาดจากการใช้เคอร์เซอร์มากเกินไปกับการไม่ใช้พวกเขาเมื่อพวกเขาควรจะสูงกว่ามากในความคิดของฉัน


8
โปรดอ่านให้ละเอียดยิ่งขึ้นทอม - วลีที่ถูกต้องคือ "ความเกลียดชังที่บ้าคลั่ง"; "เกลียด" เป็นเป้าหมายของคำคุณศัพท์ "บ้า" ไม่ใช่ "คน" ภาษาอังกฤษอาจเป็นเรื่องยากในบางครั้ง ;-)
Steven A. Lowe

0

Basicaly 2 บล็อกของโค้ดที่ทำสิ่งเดียวกัน อาจจะเป็นตัวอย่างที่แปลกไปหน่อย แต่ก็พิสูจน์ประเด็นได้ SQL Server 2005:

SELECT * INTO #temp FROM master..spt_values
DECLARE @startTime DATETIME

BEGIN TRAN 

SELECT @startTime = GETDATE()
UPDATE #temp
SET number = 0
select DATEDIFF(ms, @startTime, GETDATE())

ROLLBACK 

BEGIN TRAN 
DECLARE @name VARCHAR

DECLARE tempCursor CURSOR
    FOR SELECT name FROM #temp

OPEN tempCursor

FETCH NEXT FROM tempCursor 
INTO @name

SELECT @startTime = GETDATE()
WHILE @@FETCH_STATUS = 0
BEGIN

    UPDATE #temp SET number = 0 WHERE NAME = @name
    FETCH NEXT FROM tempCursor 
    INTO @name

END 
select DATEDIFF(ms, @startTime, GETDATE())
CLOSE tempCursor
DEALLOCATE tempCursor

ROLLBACK 
DROP TABLE #temp

การอัปเดตครั้งเดียวใช้เวลา 156 มิลลิวินาทีในขณะที่เคอร์เซอร์ใช้เวลา 2016 มิลลิวินาที


3
ใช่มันพิสูจน์ให้เห็นว่านี่เป็นวิธีที่โง่มากในการใช้เคอร์เซอร์! แต่จะเกิดอะไรขึ้นถ้าการอัปเดตของแต่ละแถวขึ้นอยู่กับค่าของแถวก่อนหน้าในลำดับวันที่?
Steven A. Lowe

BEGIN TRAN SELECT TOP 1 baseval จากตาราง ORDER BY timestamp ตาราง DESC INSERT (ช่อง) VALUES (vals รวมถึงค่าที่ได้รับจากบันทึกก่อนหน้า) COMMIT
TRAN

@doofledorfer: ซึ่งจะแทรกหนึ่งแถวตามแถวสุดท้ายตามวันที่ไม่อัปเดตทุกแถวตามค่าจากแถวก่อนหน้าตามลำดับวันที่
Steven A. Lowe

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