ลบออกจากเคอร์เซอร์ ms sql เคอร์เซอร์ในขั้นตอนการจัดเก็บ MySQL A. การใช้เคอร์เซอร์และไวยากรณ์อย่างง่าย

มีการกำหนดคำจำกัดความของเคอร์เซอร์ มีการจัดเตรียมคำอธิบายประเภทและลักษณะการทำงาน: เคอร์เซอร์แบบคงที่ ไดนามิก ลำดับ และคีย์ มีการอธิบายหลักการของการควบคุมเคอร์เซอร์: การสร้างและการเปิดเคอร์เซอร์ การอ่านข้อมูล การปิดเคอร์เซอร์ มีตัวอย่างการเขียนโปรแกรมเคอร์เซอร์ให้

แนวคิดของเคอร์เซอร์

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

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

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

ตามมาตรฐาน SQL เมื่อทำงานกับเคอร์เซอร์สามารถแยกแยะการกระทำหลักดังต่อไปนี้:

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

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

ในบางกรณี การใช้เคอร์เซอร์เป็นสิ่งที่หลีกเลี่ยงไม่ได้ อย่างไรก็ตาม หากเป็นไปได้ ควรหลีกเลี่ยงและทำงานกับคำสั่งการประมวลผลข้อมูลมาตรฐาน: SELECT, UPDATE, INSERT, DELETE นอกเหนือจากข้อเท็จจริงที่ว่าเคอร์เซอร์ไม่อนุญาตให้มีการปรับเปลี่ยนปริมาณข้อมูลทั้งหมด ความเร็วของการดำเนินการประมวลผลข้อมูลโดยใช้เคอร์เซอร์ยังต่ำกว่าอย่างเห็นได้ชัด วิธีการมาตรฐาน SQL.

การใช้งานเคอร์เซอร์ในสภาพแวดล้อม MS SQL Server

เซิร์ฟเวอร์ SQLรองรับเคอร์เซอร์สามประเภท:

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

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

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

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

SQL Server รองรับสแตติก ไดนามิก ตามลำดับและควบคุมด้วยชุดกุญแจ

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

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

ใน เคอร์เซอร์แบบคงที่ไม่สามารถทำการเปลี่ยนแปลงได้ ดังนั้นจึงเปิดในโหมดอ่านอย่างเดียวเสมอ

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

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

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

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

การจัดการเคอร์เซอร์ในสภาพแวดล้อม MS SQL Server

การควบคุมเคอร์เซอร์ดำเนินการโดยดำเนินการคำสั่งต่อไปนี้:

  • ประกาศ - การสร้างหรือ การประกาศเคอร์เซอร์;
  • เปิด - เคอร์เซอร์เปิด, เช่น. กรอกข้อมูล;
  • ดึงข้อมูล การเลือกจากเคอร์เซอร์และการเปลี่ยนแถวข้อมูลโดยใช้เคอร์เซอร์
  • ปิด - ปิดเคอร์เซอร์;
  • จัดสรรคืน – ปล่อยเคอร์เซอร์, เช่น. การลบเคอร์เซอร์เป็นวัตถุ

ประกาศเคอร์เซอร์

มาตรฐาน SQL จัดเตรียมคำสั่งต่อไปนี้เพื่อสร้างเคอร์เซอร์:

การใช้คำสำคัญ INSENSITIVE จะสร้าง เคอร์เซอร์แบบคงที่. การเปลี่ยนแปลงข้อมูลไม่ได้รับอนุญาต นอกจากนี้ การเปลี่ยนแปลงที่ทำโดยผู้ใช้รายอื่นจะไม่แสดง หากไม่มีคำหลัก INSENSITIVE ก เคอร์เซอร์แบบไดนามิก.

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

คำสั่ง SELECT ระบุเนื้อความของคำขอ SELECT ซึ่งกำหนดผลลัพธ์ชุดแถวของเคอร์เซอร์

การระบุ FOR READ_ONLY จะสร้างเคอร์เซอร์แบบอ่านอย่างเดียวและไม่อนุญาตให้มีการแก้ไขข้อมูลใดๆ มันแตกต่างจากแบบคงที่แม้ว่าอย่างหลังจะไม่อนุญาตให้เปลี่ยนแปลงข้อมูลก็ตาม สามารถประกาศเป็นเคอร์เซอร์แบบอ่านอย่างเดียวได้ เคอร์เซอร์แบบไดนามิกซึ่งจะอนุญาตให้แสดงการเปลี่ยนแปลงที่ทำโดยผู้ใช้รายอื่น

การสร้างเคอร์เซอร์ด้วยอาร์กิวเมนต์ FOR UPDATE ช่วยให้คุณสามารถดำเนินการในเคอร์เซอร์ได้ การเปลี่ยนแปลงข้อมูลในคอลัมน์ที่ระบุ หรือในกรณีที่ไม่มีอาร์กิวเมนต์ OF column_name ในทุกคอลัมน์

ในสภาพแวดล้อม MS SQL Server ยอมรับไวยากรณ์ต่อไปนี้สำหรับคำสั่งสร้างเคอร์เซอร์:

<создание_курсора>::= ประกาศ cursor_name เคอร์เซอร์สำหรับ SELECT_statement ]]

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

หากระบุคีย์เวิร์ด GLOBAL เคอร์เซอร์ส่วนกลางจะถูกสร้างขึ้น มีอยู่จนกว่าการเชื่อมต่อปัจจุบันจะปิด

การระบุ FORWARD_ONLY จะสร้าง เคอร์เซอร์อนุกรม; ข้อมูลสามารถสุ่มตัวอย่างได้ในทิศทางจากแถวแรกไปสุดท้ายเท่านั้น

ระบุการสร้าง SCROLL เคอร์เซอร์แบบเลื่อนได้; สามารถเข้าถึงข้อมูลได้ในลำดับและทิศทางใดก็ได้

ระบุการสร้าง STATIC เคอร์เซอร์แบบคงที่.

การระบุ KEYSET จะสร้างเคอร์เซอร์คีย์

ระบุการสร้าง DYNAMIC เคอร์เซอร์แบบไดนามิก.

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

เคอร์เซอร์ที่สร้างขึ้นด้วยอาร์กิวเมนต์ OPTIMISTIC จะป้องกันการแก้ไขหรือการลบแถวที่ถูกแก้ไขหลังจากนั้น การเปิดเคอร์เซอร์.

โดยการระบุอาร์กิวเมนต์ TYPE_WARNING เซิร์ฟเวอร์จะแจ้งให้ผู้ใช้ทราบถึงการเปลี่ยนแปลงโดยนัยของประเภทเคอร์เซอร์ หากเข้ากันไม่ได้กับแบบสอบถาม SELECT

การเปิดเคอร์เซอร์

สำหรับ การเปิดเคอร์เซอร์และกรอกข้อมูลจากการสืบค้น SELECT ที่ระบุเมื่อสร้างเคอร์เซอร์ ให้ใช้คำสั่งต่อไปนี้:

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

การดึงข้อมูลจากเคอร์เซอร์

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

การระบุ FIRST จะส่งกลับแถวแรกของชุดผลลัพธ์ที่สมบูรณ์ของเคอร์เซอร์ ซึ่งจะกลายเป็นแถวปัจจุบัน

การระบุ LAST จะส่งกลับแถวล่าสุดของเคอร์เซอร์ มันยังกลายเป็นเส้นปัจจุบัน

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

คีย์เวิร์ด PRIOR ส่งคืนแถวก่อนหน้าแถวปัจจุบัน มันจะกลายเป็นปัจจุบัน

การโต้แย้ง สัมบูรณ์ (line_number | @line_number_variable)ส่งคืนแถวด้วยเลขลำดับสัมบูรณ์ในชุดผลลัพธ์ที่สมบูรณ์ของเคอร์เซอร์ หมายเลขบรรทัดสามารถระบุได้โดยใช้ค่าคงที่หรือเป็นชื่อของตัวแปรที่ใช้จัดเก็บหมายเลขบรรทัด ตัวแปรจะต้องเป็นชนิดข้อมูลจำนวนเต็ม ระบุทั้งค่าบวกและค่าลบ เมื่อระบุค่าบวก สตริงจะถูกนับจากจุดเริ่มต้นของชุด ในขณะที่ค่าลบจะถูกนับจากจุดสิ้นสุด เส้นที่เลือกจะกลายเป็นเส้นปัจจุบัน หากมีการระบุค่า Null จะไม่มีการส่งคืนแถว

การโต้แย้ง RELATIVE (จำนวนแถว | @จำนวนแถวของตัวแปร)ส่งคืนบรรทัดที่เป็นจำนวนบรรทัดที่ระบุหลังจากบรรทัดปัจจุบัน หากคุณระบุจำนวนแถวที่เป็นลบ แถวที่เป็นจำนวนแถวที่ระบุก่อนแถวปัจจุบันจะถูกส่งกลับ การระบุค่าว่างจะส่งกลับแถวปัจจุบัน แถวที่ส่งคืนจะกลายเป็นแถวปัจจุบัน

ถึง เปิดเคอร์เซอร์ส่วนกลางคุณต้องระบุคีย์เวิร์ด GLOBAL หน้าชื่อ ชื่อเคอร์เซอร์สามารถระบุได้โดยใช้ตัวแปร

ในการออกแบบ เข้า @variable_name [,...n]มีการระบุรายการตัวแปรโดยจะจัดเก็บค่าคอลัมน์ที่สอดคล้องกันของแถวที่ส่งคืน ลำดับการระบุตัวแปรจะต้องตรงกับลำดับของคอลัมน์ในเคอร์เซอร์ และประเภทข้อมูลของตัวแปรจะต้องตรงกับประเภทข้อมูลในคอลัมน์เคอร์เซอร์ หากไม่ได้ระบุโครงสร้าง INTO พฤติกรรมของคำสั่ง FETCH จะคล้ายคลึงกับพฤติกรรมของคำสั่ง SELECT - ข้อมูลจะแสดงบนหน้าจอ

การเปลี่ยนแปลงและการลบข้อมูล

หากต้องการเปลี่ยนแปลงโดยใช้เคอร์เซอร์ คุณต้องออกคำสั่ง UPDATE ในรูปแบบต่อไปนี้:

คอลัมน์หลายคอลัมน์ของแถวเคอร์เซอร์ปัจจุบันสามารถเปลี่ยนแปลงได้ในการดำเนินการครั้งเดียว แต่คอลัมน์ทั้งหมดจะต้องอยู่ในตารางเดียวกัน

หากต้องการลบข้อมูลโดยใช้เคอร์เซอร์ ให้ใช้คำสั่ง DELETE ในรูปแบบต่อไปนี้:

เป็นผลให้บรรทัดที่ตั้งค่าปัจจุบันในเคอร์เซอร์จะถูกลบ

การปิดเคอร์เซอร์

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

ปล่อยเคอร์เซอร์

การปิดเคอร์เซอร์ไม่จำเป็นต้องเพิ่มหน่วยความจำที่เกี่ยวข้อง การใช้งานบางอย่างต้องจัดสรรคืนอย่างชัดเจนโดยใช้คำสั่ง DEALLOCATE หลังจาก ปล่อยเคอร์เซอร์หน่วยความจำยังว่าง ทำให้สามารถใช้ชื่อเคอร์เซอร์ซ้ำได้

เพื่อควบคุมว่าจะถึงจุดสิ้นสุดของเคอร์เซอร์หรือไม่ ขอแนะนำให้ใช้ฟังก์ชัน: @@FETCH_STATUS

ฟังก์ชัน @@FETCH_STATUS ส่งคืน:

0 หากการดึงข้อมูลสำเร็จ

1 หากการดึงข้อมูลล้มเหลวเนื่องจากพยายามดึงข้อมูลบรรทัดนอกเคอร์เซอร์

2 หากการดึงข้อมูลล้มเหลวเนื่องจากพยายามเข้าถึงแถวที่ถูกลบหรือแก้ไข

ประกาศ @id_kl INT, @firm VARCHAR(50), @fam VARCHAR(50), @ข้อความ VARCHAR(80), @nam VARCHAR(50), @d DATETIME, @p INT, @s INT SET @s=0 พิมพ์ "รายการช็อปปิ้ง" ประกาศ klient_cursor เคอร์เซอร์ท้องถิ่นสำหรับเลือกรหัสลูกค้า บริษัท นามสกุลจากลูกค้า WHERE City="Moscow" เรียงลำดับตามบริษัท นามสกุลเปิด klient_cursor ดึงข้อมูลถัดไปจาก klient_cursor เข้าสู่ @id_kl, @firm, @fam ในขณะที่ @@FETCH_STATUS =0 BEGIN SELECT @message="Client "+@fam+ "Company "+ @firm PRINT @message SELECT @message="ชื่อผลิตภัณฑ์ วันที่ซื้อ ต้นทุน" PRINT @message DECLARE tovar_cursor CURSOR FOR SELECT Product.Name, Transaction.Date, Product .ราคา* ธุรกรรม ปริมาณตามต้นทุนจากธุรกรรมเข้าร่วมภายในผลิตภัณฑ์บนผลิตภัณฑ์ Product Code=Transaction.Product Code WHERE Transaction.Customer Code=@id_kl OPEN tovar_cursor FETCH NEXT FROM tovar_cursor INTO @nam, @d, @p IF @@FETCH_STATUS<>0 พิมพ์ "ไม่มีการซื้อ" ในขณะที่ @@FETCH_STATUS=0 BEGIN SELECT @message=" "+@nam+" "+ CAST(@d AS CHAR(12))+" "+ CAST(@p AS CHAR(6)) PRINT @message SET @s=@s+@p ดึงข้อมูลถัดไปจาก tovar_cursor เข้าสู่ @nam, @d, @p END ปิด tovar_cursor DEALLOCATE tovar_cursor SELECT @message="Total cost "+ CAST(@s AS CHAR(6)) PRINT @message -- ย้ายไปยังไคลเอนต์ถัดไป-- ดึงข้อมูลถัดไปจาก klient_cursor เข้าสู่ @id_kl, @firm, @fam END CLOSE klient_cursor DEALLOCATE klient_cursor ตัวอย่างที่ 13.6 เคอร์เซอร์สำหรับแสดงรายการสินค้าที่ลูกค้าซื้อจากมอสโกและต้นทุนรวม

ตัวอย่างที่ 13.7พัฒนาเคอร์เซอร์แบบเลื่อนได้สำหรับลูกค้าจากมอสโก หากหมายเลขโทรศัพท์ขึ้นต้นด้วย 1 ให้ลบไคลเอ็นต์ด้วยหมายเลขนั้น และในรายการเคอร์เซอร์แรกให้แทนที่หลักแรกในหมายเลขโทรศัพท์ด้วย 4

ประกาศ @firm VARCHAR(50), @fam VARCHAR(50), @tel VARCHAR(8), @message VARCHAR(80) พิมพ์ "รายชื่อลูกค้า" ประกาศ klient_cursor เคอร์เซอร์ GLOBAL SCROLL KEYSET สำหรับเลือกบริษัท นามสกุล โทรศัพท์จากไคลเอ็นต์ WHERE City ="Moscow" เรียงลำดับตามบริษัท นามสกุลสำหรับการอัปเดต OPEN klient_cursor FETCH NEXT จาก klient_cursor INTO @firm, @fam, @tel ในขณะที่ @@FETCH_STATUS=0 BEGIN SELECT @message="Client "+@fam+ " Company "+ @firm " Phone "+ @tel PRINT @message -- หากหมายเลขโทรศัพท์ขึ้นต้นด้วย 1, -- ลบไคลเอ็นต์ด้วยหมายเลขนั้น IF @tel LIKE '1%' DELETE Client WHERE CURRENT OF klient_cursor ELSE -- ย้ายไปที่ถัดไป ลูกค้า FETCH NEXT จาก klient_cursor เข้าสู่ @firm, @fam, @tel END FETCH ABSOLUTE 1 จาก klient_cursor เข้าสู่ @firm, @fam, @tel - ในรายการแรก แทนที่หลักแรกในหมายเลขโทรศัพท์ด้วย 4 UPDATE Client SET Phone ='4' + RIGHT(@ tel,LEN(@tel)-1)) โดยที่ปัจจุบันของ klient_cursor SELECT @message="Client "+@fam+" Firm "+ @firm "Phone "+ @tel PRINT @message CLOSE klient_cursor ยกเลิกการจัดสรร klient_cursor ตัวอย่างที่ 13.7 เคอร์เซอร์แบบเลื่อนได้สำหรับลูกค้าจากมอสโก

ตัวอย่างที่ 13.8การใช้งาน เคอร์เซอร์เป็นพารามิเตอร์เอาท์พุทของขั้นตอน. ขั้นตอนส่งคืนชุดข้อมูล - รายการผลิตภัณฑ์

การเรียกขั้นตอนและการพิมพ์ข้อมูลจากเคอร์เซอร์เอาต์พุตจะดำเนินการดังนี้:

ประกาศ @my_cur CURSOR ประกาศ @n VARCHAR(20) EXEC my_proc @cur=@my_cur เอาต์พุตดึงข้อมูลถัดไปจาก @my_cur เข้าสู่ @n SELECT @n ในขณะที่ (@@FETCH_STATUS=0) เริ่มดึงข้อมูลถัดไปจาก @my_cur เข้าสู่ @n SELECT @n จบ ปิด @my_cur ยกเลิกทั้งหมด @my_cur


เคอร์เซอร์คือลิงก์ไปยังพื้นที่หน่วยความจำตามบริบท ในการใช้งานภาษาโปรแกรม SQL บางอย่าง (Oracle, ไมโครซอฟต์ เอสคิวแอลเซิร์ฟเวอร์) - ชุดผลลัพธ์ที่ได้รับเมื่อดำเนินการค้นหาและตัวชี้บันทึกปัจจุบันที่เกี่ยวข้อง ฉันจะบอกว่าเคอร์เซอร์คือ ตารางเสมือนซึ่งเป็นแหล่งเก็บข้อมูลทางเลือก ในกรณีนี้ เคอร์เซอร์ช่วยให้คุณเข้าถึงข้อมูลได้เหมือนกับว่าเป็นข้อมูลของอาร์เรย์ปกติ
เคอร์เซอร์ถูกใช้ในขั้นตอนการจัดเก็บ ทฤษฎีพอแล้ว ลองดูตัวอย่าง:
เรามีฐานข้อมูล (ฐานข้อมูลไม่ดีนิดหน่อย นี่เป็นหนึ่งในฐานข้อมูลของฉัน) งานห้องปฏิบัติการแต่ครูฐานข้อมูลของเรายืนยันโครงสร้างดังกล่าว)
/*ข้อมูลธนาคาร*/
สร้างตาราง `ธนาคาร` (

`ชื่อธนาคาร` VARCHAR (50) COLLATE utf8_bin ไม่เป็นค่าเริ่มต้น ""


คีย์หลัก (`BankId`)

)เครื่องยนต์=อินโนดีบี
ชุดตัวละคร "utf8" เรียงกัน "utf8_bin" ;
/*ข้อมูลเกี่ยวกับเงินฝาก */
สร้างตาราง `การกระจายธนาคาร` (
`BankId` จำนวนเต็ม (11) ไม่เป็นโมฆะ
`จำนวนเต็มถาวร (11) ค่าเริ่มต้น NULL
`จำนวนการมีส่วนร่วม` ทศนิยม (10,0) ไม่เป็นโมฆะ
`ClientId` จำนวนเต็ม (11) ไม่เป็นโมฆะ
คีย์หลัก(`BankId`, `ClientId`),
คีย์ `BankId` (`BankId`)
คีย์ `ClientId` (`ClientId`)
ข้อจำกัด `bankdistribution_fk` คีย์ต่างประเทศ (`BankId`) การอ้างอิง `bank` (`BankId`)
ข้อจำกัด `bankdistribution_fk1` คีย์ต่างประเทศ (`ClientId`) การอ้างอิง `client` (`ClientId`)
)เครื่องยนต์=อินโนดีบี
/*ข้อมูลเกี่ยวกับนักลงทุน*/
สร้างตาราง `ลูกค้า` (
`ClientId` จำนวนเต็ม (3) ไม่เป็นโมฆะ AUTO_INCREMENT
`CreditCardId` BIGINT(10) ไม่เป็นโมฆะ
`นามสกุล` VARCHAR (50) COLLATE utf8_bin ไม่ใช่ค่าเริ่มต้น "" ,
`ชื่อ` VARCHAR (50) COLLATE utf8_bin ไม่เป็นค่าเริ่มต้น ""
`ชื่อ` VARCHAR (50) COLLATE utf8_bin ไม่เป็นค่าเริ่มต้น "" ,
`โทรศัพท์` VARCHAR (50) COLLATE utf8_bin ไม่เป็นค่าเริ่มต้น ""
`ที่อยู่ ` VARCHAR (50) COLLATE utf8_bin ไม่เป็นค่าเริ่มต้น "" ,
`SafeId` จำนวนเต็ม (5) ไม่เป็นโมฆะ
คีย์หลัก(`ClientId`, `CreditCardId`),
คีย์ `รหัสลูกค้า` (`รหัสลูกค้า`)

)เครื่องยนต์=อินโนดีบี
AUTO_INCREMENT=ชุดอักขระ 11 ตัว "utf8" COLLATE "utf8_bin"

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

เลือก `ธนาคาร`* จาก `ธนาคาร` จำกัดจำนวน THE_RECORD_WE NEED,1
. ดังนั้น เมื่อใช้ LIMIT WE NEED_RECORD NUMBER, 1 เราจะแยกแต่ละระเบียนในรอบจากตารางธนาคารตามลำดับและดำเนินการตามที่เราต้องการ ในขณะที่เพิ่มค่าของ WE NEED_RECORD NUMBER ขึ้น 1 ตอนนี้เราจะทำเช่นเดียวกัน แต่ โดยใช้เคอร์เซอร์
เริ่ม
/* ตัวแปรที่เราดึงข้อมูลออกมา */
ประกาศจำนวนเต็ม vBankId ;
ประกาศ vBankName VARCHAR(50);
ประกาศ vAddress VARCHAR(50);
ประกาศ vPhone VARCHAR (50);
/* ตัวแปรแฮดเลอร์ - a*/
ประกาศค่าเริ่มต้นจำนวนเต็มเสร็จสิ้น 0;
/*ประกาศเคอร์เซอร์*/
ประกาศเคอร์เซอร์ BankCursor เพื่อเลือก `bank`.`BankId`,`bank`.`BankName`,`bank`.`Address`,`bank`.`Phone`, จาก `bank` โดยที่ 1;
/*วัตถุประสงค์ของ HANDLER ซึ่งจะอธิบายด้านล่าง*/
ประกาศตัวจัดการต่อสำหรับ SQLSTATE "02000" SET เสร็จสิ้น = 1;
/* เปิดเคอร์เซอร์ */
เปิดเคอร์เซอร์ธนาคาร;
/*ดึงข้อมูล*/
ในขณะที่ทำเสร็จ = 0 DO

เราดำเนินการตามที่เราต้องการ
สิ้นสุดในขณะที่ ;
/*ปิดเคอร์เซอร์*/
ปิดเคอร์เซอร์ธนาคาร;
จบ ;

* ซอร์สโค้ดนี้ถูกเน้นด้วย Source Code Highlighter

ข้อผิดพลาด: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)

ข้อความ: ไม่มีข้อมูล - ดึง เลือก หรือประมวลผลแถวเป็นศูนย์

SQLSTATE: 02000 เริ่มทำงานเมื่อถึงจุดสิ้นสุดของเคอร์เซอร์ หรือเมื่อการเลือกหรืออัปเดตส่งคืนสตริงว่าง

บรรทัดถัดไปเราประกาศเคอร์เซอร์ DECLARE cursor_name CURSOR FOR select_statement;
เปิดเคอร์เซอร์ เปิด cursor_name;
จากนั้นจนกว่าเราจะไปถึงจุดสิ้นสุดของเคอร์เซอร์ (ในขณะที่ทำ = 0 DO) เราจะแยกข้อมูลและประมวลผล
คุณต้องปิดเคอร์เซอร์ก่อนที่จะออกจากขั้นตอนการจัดเก็บ ปิด cursor_name;

ดูเหมือนจะไม่ซับซ้อน แต่มีข้อผิดพลาดมากมายที่เกี่ยวข้องกับ SQLSTATE "02000"

ในขณะที่ทำเสร็จ = 0 DO
ดึง BankCursor เข้าสู่ vBankId, vBankName, vAddress, vPhone;

เลือก (ContributeAmount) ลงใน vContributeAmountSUM จากการกระจายทางธนาคาร โดยที่ BankId = vBankId จำกัด 1;
เราดำเนินการบางอย่าง
สิ้นสุดในขณะที่ ;

* ซอร์สโค้ดนี้ถูกเน้นด้วย Source Code Highlighter


ทุกอย่างเรียบร้อยดีและถูกต้องจากมุมมองทางไวยากรณ์ แต่จากมุมมองเชิงตรรกะไม่มี อาจเกิดขึ้นได้ว่าผู้ฝากเงินยังไม่ได้เปิดบัญชีในบางธนาคาร ดังนั้นสำหรับเลือก (ContributeAmount) เข้าสู่ vContributeAmountSUM จากการกระจายของธนาคาร โดยที่ BankId = vBankId จำกัด 1; SQLSTATE: 02000 จะเริ่มทำงาน ตัวแปรที่ทำเสร็จแล้วจะถูกตั้งค่าเป็น 1 และ ในขณะที่วนซ้ำสิ้นสุดเร็วกว่าที่เราคาดไว้ สิ่งนี้สามารถหลีกเลี่ยงได้โดยทำดังต่อไปนี้
ในขณะที่ทำเสร็จ = 0 DO
ดึง BankCursor เข้าสู่ vBankId, vBankName, vAddress, vPhone;
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */


ถ้า (vContributeAmountSUM > 0) แล้ว
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */

สิ้นสุดถ้า ;
เราดำเนินการบางอย่าง
สิ้นสุดในขณะที่ ;

* ซอร์สโค้ดนี้ถูกเน้นด้วย Source Code Highlighter


ในคำขอแรก เราจะตรวจสอบว่ามีส่วนสนับสนุนหรือไม่ (หากไม่มี จากนั้น vContributeAmountSUM == 0) และหากมี เราจะดึงข้อมูลเท่านั้น

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

ประกาศเคอร์เซอร์ ClientSummCursor สำหรับผลรวมที่เลือก (`bankdistribution`.`ContributeAmount`), `bankdistribution`.`ClientId` จาก `bankdistribution` เข้าร่วมภายในไคลเอนต์บน (client.ClientId = bankdistribution.`ClientId`) โดยที่ 1 กลุ่มโดย `bankdistribution` `รหัสลูกค้า`;

เปิด ClientSummCursor;
ในขณะที่ทำเสร็จ = 0 DO
ดึง BankCursor เข้าสู่ vBankId, vBankName, vAddress, vPhone;
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */
เลือกจำนวน(ContributeAmount) ลงใน vContributeAmountSUM จากการกระจายทางธนาคาร โดยที่ BankId = vBankId จำกัด 1;
/* ตรวจสอบว่ามีเงินฝากในธนาคารนี้จริงหรือไม่ */
ถ้า (vContributeAmountSUM > 0) แล้ว
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */
เลือก ContributeAmount ลงใน vContributeAmountSUM จากการกระจายทางธนาคาร โดยที่ BankId = ขีดจำกัด vBankId 1;
สิ้นสุดถ้า ;


เราดำเนินการบางอย่าง
สิ้นสุดในขณะที่ ;

* ซอร์สโค้ดนี้ถูกเน้นด้วย Source Code Highlighter

สถานการณ์เดียวกันอาจเกิดขึ้นเมื่อข้อมูลในเคอร์เซอร์ ClientSummCursor สิ้นสุดเร็วกว่าข้อมูลใน BankCursor, SQLSTATE: 02000 ถูกทริกเกอร์, ตัวแปรที่ทำเสร็จแล้วถูกตั้งค่าเป็น 1 และลูป while สิ้นสุดเร็วกว่าที่เราคาดไว้ สิ่งนี้สามารถหลีกเลี่ยงได้โดยทำดังต่อไปนี้

เปิด ClientSummCursor;
ในขณะที่ทำเสร็จ = 0 DO
ดึง BankCursor เข้าสู่ vBankId, vBankName, vAddress, vPhone;
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */
เลือกจำนวน(ContributeAmount) ลงใน vContributeAmountSUM จากการกระจายทางธนาคาร โดยที่ BankId = vBankId จำกัด 1;
/* ตรวจสอบว่ามีเงินฝากในธนาคารนี้จริงหรือไม่ */
ถ้า (vContributeAmountSUM > 0) แล้ว
/* แยกจำนวนเงินฝากใด ๆ ให้กับธนาคาร */
เลือก ContributeAmount ลงใน vContributeAmountSUM จากการกระจายทางธนาคาร โดยที่ BankId = ขีดจำกัด vBankId 1;
สิ้นสุดถ้า ;
/* ก่อนที่จะแยกข้อมูลจากเคอร์เซอร์ตัวที่สอง ให้จำสถานะ sqlstate */
SET old_status = เสร็จสิ้น;
/* ดึงข้อมูลที่เราต้องการ */
ดึง ClientSummCursor เข้าสู่ vSum, vClientId;
/* ตรวจสอบว่าข้อมูลถูกดึงมาหรือไม่ และ sqlstate 0200 ล้มเหลวหรือไม่ */
ถ้า (เสร็จสิ้น = 0) แล้ว
เราดำเนินการบางอย่าง
สิ้นสุดถ้า ;
/* ก่อนสิ้นสุด while ให้คืนค่าของตัวแปรที่ทำเสร็จแล้ว */
ตั้งค่าเสร็จแล้ว = old_status;
สิ้นสุดในขณะที่ ;

* ซอร์สโค้ดนี้ถูกเน้นด้วย Source Code Highlighter

ขอบคุณทุกคนที่อ่านมาจนถึงตอนนี้ ฉันหวังว่าสิ่งนี้จะเป็นประโยชน์กับใครบางคน

มันใช้กับ: SQL Server (ตั้งแต่ปี 2551) ฐาน ข้อมูล SQLคลังข้อมูล Azure SQLคลังข้อมูลคู่ขนาน

กำหนดคุณลักษณะของเคอร์เซอร์เซิร์ฟเวอร์ Transact-SQL เช่น คุณสมบัติมุมมอง และแบบสอบถามที่ใช้ในการสร้างชุดผลลัพธ์ที่เคอร์เซอร์ทำงาน คำสั่ง DECLARE CURSOR รองรับทั้งไวยากรณ์มาตรฐาน ISO และไวยากรณ์ที่ใช้ชุดส่วนขยายภาษา Transact-SQL

ไวยากรณ์ ISO ประกาศ cursor_name [ INSENSITIVE ] [ SCROLL ] เคอร์เซอร์สำหรับ select_statement [ สำหรับ ( อ่านอย่างเดียว | อัปเดต [ OF column_name [ ,...n ] ) ] [;] ไวยากรณ์เพิ่มเติมของ Transact-SQL ประกาศ cursor_name เคอร์เซอร์ [ ท้องถิ่น | ทั่วโลก ] [ FORWARD_ONLY | เลื่อน ] [ คงที่ | คีย์เซ็ต | ไดนามิก | FAST_FORWARD ] [ อ่าน_เท่านั้น | SCROLL_LOCKS | มองในแง่ดี ] [ TYPE_WARNING ] สำหรับ select_statement [ สำหรับการอัปเดต [ ของ column_name [ ,...n ] ] ] [;]

เคอร์เซอร์_ชื่อ
เคอร์เซอร์_ชื่อ

ไร้ความรู้สึก
tempdb; ดังนั้นการเปลี่ยนแปลงตารางด้านล่างจะไม่สะท้อนให้เห็นในข้อมูลที่ส่งคืนโดยการเลือกของเคอร์เซอร์นี้ และเคอร์เซอร์นี้ไม่สามารถเปลี่ยนแปลงได้ เมื่อใช้ไวยากรณ์ ISO เว้นแต่จะระบุตัวเลือก INSENSITIVE การอัปเดตและการลบที่ทำกับตารางฐานจะปรากฏในการเลือกที่ตามมา

เลื่อน
บ่งชี้ว่ามีตัวเลือกการสุ่มตัวอย่างทั้งหมด (FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE) หากคำสั่ง ISO DECLARE CURSOR ไม่ได้ระบุตัวเลือก SCROLL ระบบจะรองรับเฉพาะตัวเลือกการดึงข้อมูล NEXT เท่านั้น ไม่สามารถระบุตัวเลือก SCROLL ด้วยตัวเลือก FAST_FORWARD

select_statement
มาตรฐาน คำสั่งเลือกซึ่งกำหนดชุดผลลัพธ์ของเคอร์เซอร์ คำหลัก FOR Browse และ INTO ไม่ได้รับอนุญาต select_statementการประกาศเคอร์เซอร์

select_statementขัดแย้งกับเคอร์เซอร์ของประเภทที่ร้องขอ

อ่านเท่านั้น

อัปเดต ]
คอลัมน์_ชื่อ [, .. .n] ถูกระบุ เฉพาะคอลัมน์ที่อยู่ในรายการเท่านั้นที่อนุญาตการเปลี่ยนแปลง หากใช้คำสั่ง UPDATE โดยไม่มีรายการคอลัมน์ แสดงว่าสามารถอัพเดตได้ทุกคอลัมน์

เคอร์เซอร์_ชื่อ
ชื่อ Transact-SQL ของเคอร์เซอร์เซิร์ฟเวอร์เฉพาะ เคอร์เซอร์_ชื่อจะต้องปฏิบัติตามกฎสำหรับตัวระบุ

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

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

ส่งต่อ_เท่านั้น
ระบุว่าเคอร์เซอร์สามารถดูได้จากบรรทัดแรกถึงบรรทัดสุดท้ายเท่านั้น รองรับเฉพาะตัวเลือกการดึงข้อมูล FETCH NEXT เท่านั้น หากระบุ FORWARD_ONLY โดยไม่มีคำหลัก STATIC, KEYSET หรือ DYNAMIC เคอร์เซอร์จะทำงานเป็นเคอร์เซอร์ DYNAMIC ถ้าไม่ได้ระบุอาร์กิวเมนต์ FORWARD_ONLY หรืออาร์กิวเมนต์ SCROLL ค่าเริ่มต้นจะเป็นอาร์กิวเมนต์ FORWARD_ONLY เว้นแต่จะมีคีย์เวิร์ด STATIC, KEYSET หรือ DYNAMIC เคอร์เซอร์แบบคงที่, คีย์เซ็ต และไดนามิกมีค่าเริ่มต้นเป็น SCROLL ต่างจาก API ฐานข้อมูล เช่น ODBC และ ADO โหมด FORWARD_ONLY ได้รับการสนับสนุนโดยเคอร์เซอร์ Transact-SQL ต่อไปนี้: STATIC, KEYSET และ DYNAMIC

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

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

การเปลี่ยนแปลงค่าที่ไม่ใช่คีย์ในตารางฐานที่ทำโดยเจ้าของเคอร์เซอร์หรือกระทำโดยผู้ใช้รายอื่นจะปรากฏขึ้นเมื่อเจ้าของเคอร์เซอร์ดู การเปลี่ยนแปลงที่ทำโดยผู้ใช้รายอื่นจะไม่สะท้อนให้เห็น (การเปลี่ยนแปลงไม่สามารถทำได้โดยใช้เคอร์เซอร์เซิร์ฟเวอร์ Transact-SQL) หากแถวถูกลบ การพยายามดึงแถวจะส่งคืน @@FETCH_STATUS -2 การอัปเดตค่าคีย์เนื่องจากขอบเขตเคอร์เซอร์จะคล้ายกับการลบแถวเก่าแล้วแทรกเข้าไป บรรทัดใหม่. มองไม่เห็นแถวที่มีค่าใหม่ และพยายามดึงแถวที่มีค่าเก่าส่งคืน @@FETCH_STATUS -2 การอัพเดตจะมองเห็นได้ทันทีหากทำผ่านเคอร์เซอร์โดยใช้ WHERE CURRENT OF clause

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

เร็ว_ไปข้างหน้า
บ่งชี้เคอร์เซอร์ FORWARD_ONLY, READ_ONLY ที่เปิดใช้งานการปรับประสิทธิภาพให้เหมาะสม ไม่สามารถระบุตัวเลือก FAST_FORWARD ด้วยตัวเลือก SCROLL หรือ FOR_UPDATE

อ่านเท่านั้น
ป้องกันการเปลี่ยนแปลงที่ทำผ่านเคอร์เซอร์นี้ ส่วนคำสั่ง WHERE CURRENT OF ไม่สามารถอ้างอิงเคอร์เซอร์ในคำสั่ง UPDATE หรือ DELETE ตัวเลือกนี้จะมีความสำคัญเหนือกว่าคุณลักษณะการรีเฟรชเคอร์เซอร์เริ่มต้น

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

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

TYPE_คำเตือน
ระบุว่าคำเตือนจะถูกส่งไปยังไคลเอ็นต์หากเคอร์เซอร์ถูกแปลงจากประเภทที่ร้องขอไปเป็นประเภทอื่นโดยปริยาย

select_statement
คำสั่ง SELECT มาตรฐานที่ระบุชุดผลลัพธ์ของเคอร์เซอร์ ไม่อนุญาตให้ใช้คีย์เวิร์ด COMPUTE, COMPUTE BY, FOR BROWSE และ INTO select_statementการประกาศเคอร์เซอร์

SQL Server แปลงเคอร์เซอร์ไปเป็นประเภทอื่นโดยปริยายหากมีส่วนคำสั่งอยู่ select_statementขัดแย้งกับเคอร์เซอร์ของประเภทที่ร้องขอ สำหรับข้อมูลเพิ่มเติม โปรดดูที่ การแปลงเคอร์เซอร์โดยนัย

สำหรับการอัปเดต ]
กำหนดคอลัมน์ในเคอร์เซอร์ที่จะอัพเดต ถ้าของ คอลัมน์_ชื่อ [, ... n] มีให้ไว้ เฉพาะคอลัมน์ที่อยู่ในรายการเท่านั้นที่อนุญาตการเปลี่ยนแปลง หากใช้คำสั่ง UPDATE โดยไม่มีรายการคอลัมน์ การอัพเดตจะเป็นไปได้สำหรับคอลัมน์ทั้งหมด เว้นแต่จะระบุตัวเลือกการทำงานพร้อมกัน READ_ONLY

คำสั่ง DECLARE CURSOR กำหนดคุณลักษณะของเคอร์เซอร์เซิร์ฟเวอร์ Transact-SQL เช่น คุณสมบัติมุมมอง และแบบสอบถามที่ใช้ในการสร้างชุดผลลัพธ์ที่เคอร์เซอร์ทำงาน คำสั่ง OPEN จะเติมชุดผลลัพธ์ และคำสั่ง FETCH จะส่งคืนแถวจากนั้น คำสั่ง CLOSE จะล้างชุดผลลัพธ์ปัจจุบันที่เกี่ยวข้องกับเคอร์เซอร์ คำสั่ง DEALLOCATE จะเผยแพร่ทรัพยากรที่เคอร์เซอร์ใช้

รูปแบบแรกของคำสั่ง DECLARE CURSOR ใช้ไวยากรณ์ ISO เพื่อระบุพารามิเตอร์เคอร์เซอร์ รูปแบบที่สองของคำสั่ง DECLARE CURSOR ใช้ส่วนขยายของภาษา Transact-SQL ที่ช่วยให้คุณสามารถกำหนดเคอร์เซอร์โดยใช้ประเภทเดียวกันกับที่ใช้ในฟังก์ชันเคอร์เซอร์ของ API ฐานข้อมูล เช่น ODBC และ ADO

ทั้งสองรูปแบบนี้ไม่สามารถผสมกันได้ หากคุณระบุ SCROLL หรือละเว้นคำหลักก่อนคำหลัก CURSOR คุณจะไม่สามารถใช้คำหลักระหว่าง CURSOR และสำหรับ select_statementคำหลัก เมื่อระบุคำหลักระหว่างเคอร์เซอร์เช่นเดียวกับสำหรับ select_statementคุณไม่สามารถระบุ SCROLL หรือ INSENSITIVE ก่อนคีย์เวิร์ด CURSOR ได้

ถ้าคุณใช้ไวยากรณ์ Transact-SQL สำหรับคำสั่ง DECLARE CURSOR และไม่ได้ระบุตัวเลือก READ_ONLY, OPTIMISTIC หรือ SCROLL_LOCKS ระบบจะถือว่าค่าเริ่มต้นต่อไปนี้

    หากคำสั่ง SELECT ไม่รองรับการอัปเดต (หรือมีสิทธิ์ไม่เพียงพอ หรือกำลังเข้าถึงตารางระยะไกลที่ไม่รองรับการอัปเดต ฯลฯ) เคอร์เซอร์จะถูกตั้งค่าเป็น READ_ONLY

    เคอร์เซอร์ STATIC และ FAST_FORWARD มีค่าเริ่มต้นเป็น READ_ONLY

    เคอร์เซอร์ DYNAMIC และ KEYSET มีค่าเริ่มต้นเป็น OPTIMISTIC

เคอร์เซอร์สามารถอ้างอิงได้โดยคำสั่ง Transact-SQL อื่นๆ เท่านั้น ฟังก์ชัน API ของฐานข้อมูลไม่สามารถอ้างอิงเคอร์เซอร์ได้ ตัวอย่างเช่น เมื่อมีการประกาศเคอร์เซอร์ ฟังก์ชันและวิธีการของ OLE DB, ODBC หรือ ADO จะไม่สามารถอ้างอิงถึงชื่อเคอร์เซอร์ได้ ไม่สามารถเลือกแถวเคอร์เซอร์โดยใช้ฟังก์ชันและวิธีการ API ที่เกี่ยวข้อง เพื่อจุดประสงค์นี้ คุณต้องใช้คำสั่ง Transact-SQL FETCH

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

สามารถใช้ตัวแปรเป็นส่วนหนึ่งได้ select_statementซึ่งมีการประกาศเคอร์เซอร์ ค่าของตัวแปรเคอร์เซอร์จะไม่เปลี่ยนแปลงหลังจากประกาศแล้ว

ตามค่าเริ่มต้น สิทธิ์ DECLARE CURSOR จะมอบให้กับผู้ใช้ทั้งหมดที่มีสิทธิ์ SELECT บนมุมมอง ตาราง และคอลัมน์ที่เคอร์เซอร์ใช้

คุณไม่สามารถใช้เคอร์เซอร์หรือทริกเกอร์บนตารางที่มีดัชนี columnstore แบบคลัสเตอร์ ข้อจำกัดนี้ใช้ไม่ได้กับดัชนีที่ไม่เป็นคลัสเตอร์ คุณสามารถใช้เคอร์เซอร์และทริกเกอร์บนตารางที่มีดัชนี columnstore ที่ไม่คลัสเตอร์ได้

A. การใช้เคอร์เซอร์และไวยากรณ์อย่างง่าย

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

ประกาศ vend_cursor เคอร์เซอร์สำหรับ SELECT * จากการจัดซื้อ ผู้ขายเปิด vend_cursor ดึงข้อมูลถัดไปจาก vend_cursor;

B. การใช้เคอร์เซอร์ที่ซ้อนกันเพื่อแสดงรายงาน

ตัวอย่างต่อไปนี้ใช้เคอร์เซอร์แบบซ้อนเพื่อแสดงรายงานที่ซับซ้อน มีการประกาศเคอร์เซอร์ภายในสำหรับผู้ให้บริการแต่ละราย

ตั้งหมายเลขบน ; ประกาศ @vendor_id int , @vendor_name nvarchar ( 50 ), @message varchar ( 80 ), @product nvarchar ( 50 );พิมพ์" -------- รายงานผลิตภัณฑ์ของผู้ขาย --------"; ประกาศ vendor_cursor เคอร์เซอร์สำหรับ SELECT VendorID, ชื่อจาก Purchasing.Vendor WHERE PreferredVendorStatus = 1 ORDER BY VendorID;เปิด vendor_cursor ดึงข้อมูลถัดไปจาก vendor_cursor เข้าสู่ @vendor_id, @vendor_name ในขณะที่ @@FETCH_STATUS = 0 เริ่มพิมพ์ " " SELECT @message = "----- สินค้าจากผู้ขาย: "+ @vendor_name พิมพ์ @ข้อความ -- ประกาศเคอร์เซอร์ภายในตาม -- บน vendor_id จากเคอร์เซอร์ด้านนอกประกาศ product_cursor เคอร์เซอร์สำหรับการเลือก v.Name จาก Purchasing.ProductVendor pv, Production.Product v WHERE pv.ProductID = v.ProductID และ pv.VendorID = @vendor_id -- ค่าตัวแปรจากเคอร์เซอร์ด้านนอกเปิด product_cursor ดึงข้อมูลถัดไปจาก product_cursor เข้าสู่ @product IF @@FETCH_STATUS<>0 พิมพ์ "<>" WHILE @@FETCH_STATUS = 0 BEGIN SELECT @message = " " + @product PRINT @message ดึงข้อมูลถัดไปจาก product_cursor เข้าสู่ @product END CLOSE product_cursor DEALLOCATE product_cursor -- รับผู้ขายรายถัดไป ดึงข้อมูลถัดไปจาก vendor_cursor เข้าสู่ @vendor_id, @vendor_name END ปิด vendor_cursor; DEALLOCATE vendor_cursor;

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

เคอร์เซอร์ช่วยให้คุณทำงานกับแถวของตารางโดยระบุหมายเลขซีเรียลในชุดข้อมูล

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

วงจรชีวิตของเคอร์เซอร์:

การสร้างเคอร์เซอร์:ประกาศ<имя курсора>[ ไม่รู้สึก ] [ เลื่อน ] เคอร์เซอร์เพื่อ< SELECT -оператор>สำหรับ (อ่านอย่างเดียว | อัปเดต)

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

เคอร์เซอร์เปิด:เปิด [ทั่วโลก]<имя курсора>. เคอร์เซอร์ที่ระบุเป็น GLOBAL จะไม่ถูกลบโดยอัตโนมัติเมื่อขั้นตอนหรือแพ็คเกจที่ถูกเรียกว่าสิ้นสุด

การอ่านข้อมูล : ดึงข้อมูล [[ ถัดไป | ก่อน | ครั้งแรก | สุดท้าย | สัมบูรณ์ n | n ที่เกี่ยวข้อง ] จาก ] [ ทั่วโลก ]<имя курсора>[INTO@variable_name,...] SQL Server 2000 อนุญาตให้คุณอ่านเพียงแถวเดียวจากเคอร์เซอร์ คำหลัก FIRST คือการส่งคืนแถวแรกของเคอร์เซอร์ LAST – บรรทัดสุดท้ายของเคอร์เซอร์ NEXT – บรรทัดถัดไปหลังจากบรรทัดปัจจุบัน บรรทัดที่ส่งคืนจะกลายเป็นบรรทัดปัจจุบัน PRIOR – ก่อนหน้าก่อนปัจจุบัน; ABSOLUTE n – ส่งคืนบรรทัดด้วยหมายเลขลำดับสัมบูรณ์ในเคอร์เซอร์ RELATIVE – n บรรทัดหลังจากบรรทัดปัจจุบัน ข้อมูลคอลัมน์จะถูกจัดเก็บไว้ในตัวแปรที่ระบุแต่ละตัวตามลำดับที่แสดง

เปลี่ยนข้อมูล:รันคำสั่ง UPDATE ด้วยไวยากรณ์ที่ออกแบบมาเพื่อทำงานกับเคอร์เซอร์

การลบข้อมูล:รันคำสั่ง DELETE ด้วยไวยากรณ์ที่ออกแบบมาเพื่อทำงานกับเคอร์เซอร์

การปิดเคอร์เซอร์:ปิด [ทั่วโลก]<имя курсора>

ปล่อยเคอร์เซอร์:จัดสรรคืน [ทั่วโลก]<имя курсора>

ตัวอย่างการใช้เคอร์เซอร์:

ประกาศ fo_curs เคอร์เซอร์คงที่สำหรับ

เลือก name_rus จากสำหรับ ORDER BY name_rus

ประกาศ @name varchar(50)

ดึงข้อมูลจาก fo_curs เข้าสู่ @name ก่อน

ในขณะที่ @@FETCH_STATUS=0

ดึงข้อมูลถัดไปจาก fo_curs เข้าสู่ @name

ยกเลิกการจัดสรร fo_curs

2.7. มั่นใจในความปลอดภัยของข้อมูลและความสมบูรณ์ใน Microsoft SQL Server การจัดการฐานข้อมูล บทบาท การกำหนดสิทธิ์ให้กับผู้ใช้ (GRANT, DENY, REVOKE) วิธีการและเทคโนโลยีสำหรับการปกป้องข้อมูลใน SQL Server

การรักษาความปลอดภัยและการดูแลระบบเซิร์ฟเวอร์ SQL .

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

การจัดการฐานข้อมูล

หากต้องการสร้างฐานข้อมูลโดยใช้ TSQL ให้ใช้คำสั่ง CREATE DATABASE แต่โดยปกติแล้วความสามารถของ SQL Server Management Studio จะถูกนำมาใช้เพื่อจุดประสงค์นี้ ใน เซิร์ฟเวอร์ SQLมีการกำหนดการดำเนินการฐานข้อมูลค่อนข้างมาก: การเพิ่ม (ลด) ขนาดไฟล์, การเปลี่ยนการกำหนดค่า (คำสั่ง ALTER), การแนบและการแยกออก, การโอนความเป็นเจ้าของ, การเปลี่ยนชื่อ, การดูคุณสมบัติและสุดท้ายคือการลบ (DROP DATABASE)

เช่นเดียวกับเซิร์ฟเวอร์ฐานข้อมูลส่วนใหญ่ SQL Server มีผู้ใช้ที่มีสิทธิ์การดูแลระบบเต็มรูปแบบ - นี่คือ ผู้ดูแลระบบหรือ 'sa'. หลังจากการติดตั้งเซิร์ฟเวอร์ครั้งแรก รหัสผ่าน sa จะว่างเปล่า ผู้ใช้ที่สร้างฐานข้อมูลใหม่จะกลายเป็นเจ้าของโดยอัตโนมัติ ('dbo' - เจ้าของฐานข้อมูล) ในขณะที่สร้างฐานข้อมูล ผู้ใช้ "แขก" จะถูกกำหนดด้วย หากบัญชีผู้ใช้ไม่ได้รับการแมปอย่างชัดเจนกับผู้ใช้ของ ฐานข้อมูลเฉพาะ ผู้ใช้จะได้รับอนุญาตให้เข้าถึงโดยนัยโดยใช้ชื่อแขก แขก แขกมักถูกห้าม

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

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

db_owner. มีสิทธิทั้งหมดในฐานข้อมูล

Db_accessadmin. สามารถเพิ่มหรือลบผู้ใช้ได้

db_securityadmin. จัดการสิทธิ์ วัตถุ บทบาท และผู้ใช้ทั้งหมด

Db_ddladmin. สามารถดำเนินการคำสั่ง DDL ทั้งหมด ยกเว้น GRANT, DENY, REVOKE

Db_backupoperator. Archiver สามารถรันคำสั่งได้ ข้อมูล

db_datareader. บางทีก็ดู.. ข้อมูลใด ๆ ในตารางใด ๆ

db_datawriter บางทีอาจมีการปรับเปลี่ยน ข้อมูลใด ๆ ในตารางใด ๆ

Db_denydatareader ต้องห้าม ดู รัก ข้อมูลในใด ๆ ตาราง

Db_denydatawriter ห้ามแก้ไขข้อมูลใดๆ ในตารางใดๆ

การกำหนดสิทธิ์ให้กับผู้ใช้ รากฐานของการรักษาความปลอดภัย SQL Server คือ (1) บัญชี(บัญชี); (2) ผู้ใช้; (3) บทบาท; (4) กลุ่ม

เมื่อผู้ใช้เชื่อมต่อกับ SQL Server การกระทำที่เขาสามารถทำได้จะถูกกำหนดโดยสิทธิ์ที่มอบให้แก่เขาในฐานะผู้ใช้และสมาชิกของบทบาท สิทธิ์จะได้รับจากผู้ดูแลระบบ DBMS เจ้าของฐานข้อมูล หรือเจ้าของออบเจ็กต์ฐานข้อมูลเฉพาะ สิทธิ์ในฐานข้อมูลสามารถแบ่งออกเป็นสามประเภท: (1) สิทธิ์ในการเข้าถึงวัตถุฐานข้อมูล; (2) สิทธิ์ในการรันคำสั่ง TSQL; (3) สิทธิโดยนัย เซิร์ฟเวอร์อนุญาตให้คุณโอนความเป็นเจ้าของจากผู้ใช้รายหนึ่งไปยังอีกรายหนึ่ง

คำสั่งต่อไปนี้ใช้ในการจัดการสิทธิ์ของผู้ใช้ในการเข้าถึงวัตถุฐานข้อมูล:

ยินยอม(ทั้งหมด |< вид действия >,…}

( บน (<имя таблицы или представления>} [(<имя столбца>,…)]

| บน (< имя хранимой процедуры >}

| บน (< имя пользовательской функции >}

ถึง ( สาธารณะ |<имя объекта системы безопасности>,…}

[ เช่น<имя группы> | <имя роли>]

การกำหนดสิทธิ์ให้กับผู้ใช้, ที่ไหน

ทั้งหมด – ผู้ใช้จะได้รับสิทธิ์ที่เป็นไปได้ทั้งหมด มิฉะนั้นจะระบุ

<вид действия>– สิทธิ์ในการดำเนินการที่มีให้กับผู้ใช้ ได้แก่ :

SELECT – สำหรับมุมมอง สำหรับคอลัมน์ตาราง และสำหรับตาราง (มุมมอง)

INSERT – เพื่อเพิ่มสำหรับตาราง (มุมมอง) โดยรวม

UPDATE – สำหรับการเปลี่ยนแปลง สำหรับคอลัมน์ตาราง และสำหรับตาราง (มุมมอง)

DELETE – เพื่อลบตาราง (มุมมอง) โดยรวม

EXECUTE – เพื่อดำเนินการตามขั้นตอนที่เก็บไว้

การอ้างอิง - ความสามารถในการอ้างอิงถึงวัตถุที่ระบุ (รวมเป็นส่วนหนึ่งของคีย์ต่างประเทศ)

<имя объекта системы безопасности>– บัญชี SQL Server, ผู้ใช้โดเมน Windows; สาธารณะ – สำหรับผู้ใช้ทุกคน

ด้วยตัวเลือกการให้สิทธิ์ - อนุญาตให้ผู้ใช้ที่ได้รับสิทธิ์ในปัจจุบันสามารถกำหนดสิทธิ์การเข้าถึงวัตถุให้กับผู้ใช้รายอื่น

เช่น<имя группы> | <имя роли>– การมีส่วนร่วมของผู้ใช้ในบทบาทที่ได้รับความสามารถในการให้สิทธิ์แก่ผู้ใช้รายอื่น

ให้สิทธิ์เลือกแก่ผู้เขียนสู่สาธารณะ

ให้สิทธิ์แทรก อัปเดต ลบผู้เขียนถึง Mary, John, Tom

ให้สิทธิ์เลือกบน Plan_Data ให้กับการบัญชีด้วยตัวเลือกการให้สิทธิ์

ให้สิทธิ์เลือก Plan_Data ให้กับ Jack AS Accounting

แจ็คไม่ใช่สมาชิกของบทบาทการบัญชี แต่มีคนในบทบาทนั้นสามารถให้สิทธิ์ได้

ปฏิเสธ(ทั้งหมด |< вид действия >,…}

( บน (<имя таблицы или представления>} [(<имя столбца>,…)]

| บน (<имя хранимой процедуры>}

| บน (<имя пользовательской функции>}

ถึง ( สาธารณะ |<имя объекта системы безопасности>,…}

การปฏิเสธการเข้าถึงผู้ใช้ไปยังวัตถุฐานข้อมูล CASCADE เพิกถอนสิทธิ์ไม่เพียงแต่จาก ผู้ใช้ที่กำหนดแต่สำหรับทุกคนที่เขาให้สิทธิ์ด้วย

ตัวอย่าง (บน คำสั่งห้าม TSQL):

ปฏิเสธการสร้างตารางให้กับ Jack CASCADE

ทีม ถอนใช้เพื่อปฏิเสธการเข้าถึงวัตถุฐานข้อมูลโดยปริยาย ไวยากรณ์เหมือนกับคำสั่ง DENY การปฏิเสธโดยนัยนั้นคล้ายคลึงกับการปฏิเสธการเข้าถึง ยกเว้นว่าจะใช้เฉพาะในระดับที่กำหนดไว้เท่านั้น ตัวอย่าง: ผู้ใช้ Jack ซึ่งเป็นสมาชิกของบทบาท GoodUsers ได้รับสิทธิ์ในการเข้าถึงตาราง XFiles หาก REVOKE ถูกปฏิเสธสำหรับบทบาท GoodUsers ในการเข้าถึงตารางนี้ Jack ยังคงสามารถเข้าถึงตารางนี้ได้เนื่องจากสิทธิ์สำหรับเขาถูกกำหนดไว้อย่างชัดเจน หากคุณใช้ REVOKE เป็นการส่วนตัว เขาจะเสียสิทธิ์ในการเข้าถึง XFiles

สิทธิ์ที่มอบให้กับบทบาทนั้นสืบทอดมาจากสมาชิก หากผู้ใช้ได้รับอนุญาตให้เข้าถึงออบเจ็กต์ผ่านการเป็นสมาชิกในบทบาทหนึ่ง แต่ถูกปฏิเสธในอีกบทบาทหนึ่ง ข้อขัดแย้งในการเข้าถึงจะได้รับการแก้ไขด้วยการปฏิเสธเสมอ

เทคโนโลยีการปกป้องข้อมูลใน MS SQL Server

1.กลไก จุดตรวจ- จุดตรวจสอบที่สร้างขึ้นหลังจาก ~ 60 วินาทีเพื่อเขียนหน้าที่อัพเดตลงดิสก์ (จุดตรวจสอบสามารถบังคับได้ด้วยคำสั่ง CHECKPOINT)

2. กลไกในตัวและภายนอกสำหรับการตรวจสอบความสมบูรณ์ของฐานข้อมูล (เปิดใช้งานโดยอัตโนมัติหรือเช่นยูทิลิตี้ DBCC - ตัวตรวจสอบความสอดคล้องของฐานข้อมูล - ด้วยตนเอง)

3. การทำสำเนาทางกายภาพ (หากอนุญาต) ของไฟล์ฐานข้อมูลโดยใช้ระบบปฏิบัติการ (รวมถึงกลไกของฮาร์ดไดรฟ์แบบมิเรอร์)

4. การสำรองฐานข้อมูลและบันทึกธุรกรรม - โดยการเขียนดัมพ์ฐานข้อมูลไปยังอุปกรณ์สำรองข้อมูล (เทปแม่เหล็กหรือฮาร์ดไดรฟ์)

5. การจำลองแบบ – ความสามารถในการทำซ้ำข้อมูลเป็นระยะ (ในบางกรณี พร้อมกัน) โดยถ่ายโอนข้อมูลจากเซิร์ฟเวอร์ SQL หนึ่งไปยังอีกเซิร์ฟเวอร์หนึ่ง

6. การเข้ารหัสการรับส่งข้อมูลระหว่างไคลเอนต์และเซิร์ฟเวอร์ รวมถึงการเข้ารหัสรหัสที่ใช้ในการทำงานกับออบเจ็กต์ฐานข้อมูล (ขั้นตอนที่เก็บไว้ ทริกเกอร์ ฯลฯ)

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

2) การประกาศเคอร์เซอร์

ประกาศ [{}] [[เลขที่] เลื่อน] เคอร์เซอร์ [{ด้วย|ไม่มี} ถือ] สำหรับ [สำหรับ {อ่านอย่างเดียว|อัปเดต [ของ ]}]

3) คำหลัก
. ละเอียดอ่อน | ไม่ละเอียดอ่อน | ไม่ละเอียดอ่อน– การเปลี่ยนแปลงในชุดผลลัพธ์จะมองเห็นได้ | ห้าม (แก้ไขโดยใช้สำเนาของชุดข้อมูล) | DBMS เองจะตัดสินใจว่าจะทำสำเนาหรือไม่ (ทำงานตามค่าเริ่มต้น)
. ด้วย|โดยไม่ต้องถือ– เปิดทิ้งไว้ | ปิดเคอร์เซอร์หากพบคำสั่ง COMMIT
. เลื่อน– [ป้องกัน] แยกแถวผลลัพธ์ตามลำดับแบบสุ่ม
. สำหรับการอ่านเท่านั้น– กำหนดเคอร์เซอร์แบบอ่านอย่างเดียว
. สำหรับการอัปเดตของ– บล็อกเฉพาะคอลัมน์ที่ระบุไม่ให้อัปเดต

4) ประกาศเคอร์เซอร์ใน SQL Server

ประกาศ เคอร์เซอร์ [ท้องถิ่น|ทั่วโลก] [FORWARD_ONLY|เลื่อน] [คงที่|ชุดคีย์|ไดนามิก|FAST_FORWARD] [อ่าน_เท่านั้น|SCROLL_LOCKS|ในแง่ดี] สำหรับ [สำหรับการอัปเดต [ของ ]]

. คงที่– กำหนดเคอร์เซอร์ที่สร้างสำเนาข้อมูลชั่วคราวสำหรับเคอร์เซอร์ใช้งาน แบบสอบถามทั้งหมดที่เทียบกับเคอร์เซอร์จะเข้าถึงตารางชั่วคราวที่ระบุในฐานข้อมูล tempdb ดังนั้นการเปลี่ยนแปลงตารางฐานจะไม่ส่งผลกระทบต่อข้อมูลที่ส่งกลับโดยตัวอย่างสำหรับเคอร์เซอร์นั้น และตัวเคอร์เซอร์เองก็ไม่อนุญาตให้ทำการเปลี่ยนแปลง
. คีย์เซ็ต– ระบุว่าสมาชิกหรือลำดับของแถวในเคอร์เซอร์ไม่เปลี่ยนแปลงหลังจากเปิด ชุดคีย์ที่ระบุแถวโดยไม่ซ้ำกันถูกสร้างขึ้นในตารางในฐานข้อมูล tempdb ที่เรียกว่าชุดคีย์
. พลวัต– กำหนดเคอร์เซอร์ที่แสดงการเปลี่ยนแปลงข้อมูลทั้งหมดที่ทำกับแถวของชุดผลลัพธ์เมื่อดูเคอร์เซอร์นี้ ค่าข้อมูล ลำดับ และสมาชิกแถวในการเลือกแต่ละรายการอาจแตกต่างกันไป ตัวเลือกการเลือกแบบสัมบูรณ์ไม่ได้รับการสนับสนุนโดยเคอร์เซอร์แบบไดนามิก
. เร็ว_ไปข้างหน้า– ระบุเคอร์เซอร์ FORWARD_ONLY, READ_ONLY ซึ่งเปิดใช้งานการปรับประสิทธิภาพให้เหมาะสม ไม่สามารถระบุตัวเลือก FAST_FORWARD ด้วยตัวเลือก SCROLL หรือ FOR_UPDATE
. SCROLL_LOCKS– บ่งชี้ว่าการอัปเดตหรือการลบตำแหน่งที่ทำผ่านเคอร์เซอร์นั้นรับประกันว่าจะสำเร็จ SQL Server จะล็อกแถวขณะที่อ่านลงในเคอร์เซอร์เพื่อให้แน่ใจว่าแถวเหล่านั้นพร้อมสำหรับการเปลี่ยนแปลงในภายหลัง ไม่สามารถระบุตัวเลือก SCROLL_LOCKS ด้วยตัวเลือก FAST_FORWARD หรือ STATIC
. มองโลกในแง่ดี– ระบุว่าการอัปเดตหรือการลบตำแหน่งที่ทำผ่านเคอร์เซอร์จะล้มเหลวหากแถวได้รับการอัปเดตนับตั้งแต่เวลาที่อ่านในเคอร์เซอร์ SQL Server ไม่ล็อกแถวเมื่อมีการอ่านลงในเคอร์เซอร์ แต่จะมีการเปรียบเทียบค่าของคอลัมน์การประทับเวลา (หรือเช็คซัมหากตารางไม่มีคอลัมน์การประทับเวลา) เพื่อพิจารณาว่าแถวมีการเปลี่ยนแปลงหรือไม่นับตั้งแต่อ่านลงในเคอร์เซอร์ หากมีการแก้ไขแถว จะไม่สามารถแก้ไขหรือลบตำแหน่งได้ ไม่สามารถระบุตัวเลือก OPTIMISTIC ด้วยตัวเลือก FAST_FORWARD

5) การเปิดเคอร์เซอร์

6) การดึงแถวจากเคอร์เซอร์

ดึงข้อมูล [{ถัดไป|ก่อนหน้า|ครั้งแรก|สุดท้าย|{สัมบูรณ์ | ญาติ }}]
จาก เข้าไปข้างใน

7) ตัวเลือกการวางตำแหน่งเคอร์เซอร์
. ถัดไป|ก่อนหน้า|ครั้งแรก|สุดท้าย– ไปที่บรรทัดถัดไป|ก่อนหน้า|แรก|สุดท้ายของชุดผลลัพธ์
. ญาติ ±N– เป็นเส้นที่มีการชดเชยบวกหรือลบสัมพันธ์กับเส้นปัจจุบัน
. สัมบูรณ์ ±N– ไปยังบรรทัดที่มีหมายเลขตำแหน่งสัมบูรณ์ที่ระบุอย่างชัดเจนจากจุดเริ่มต้นหรือจุดสิ้นสุดของเคอร์เซอร์

บันทึก: SQL Server อนุญาตให้ใช้ตัวแปรจำนวนเต็ม @N แทน N

8) การปิดเคอร์เซอร์

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

10) ตัวอย่างการลบข้อมูลจากเคอร์เซอร์

exec sql ประกาศเคอร์เซอร์ Cur1 เพื่อเลือก * จากลูกค้า
เรตติ้งที่ไหน
// พิมพ์ (@f1+’ ‘+ แปลง (Varchar (5),@f2))
exec sql ลบออกจากลูกค้า
โดยที่กระแสของ Cur1; ) – นำข้อมูลที่จะลบออกจากเคอร์เซอร์
ยังไม่เสร็จ:
exec sql ปิดเคอร์เซอร์ Cur1; — ปิดเคอร์เซอร์
ออก();

11) ตัวอย่างการเพิ่มค่าคอมมิชชั่น

exec sql ประกาศเคอร์เซอร์ CurCust สำหรับ select * จาก SalesPeople
โดยที่ SNum ใน (เลือก SNum จากลูกค้าโดยที่ Rating=300) — กำหนดเคอร์เซอร์
exec sql เปิดเคอร์เซอร์ CurCust; - ดำเนินการเคอร์เซอร์
while (sqlca.sqlcode==0) ( — สร้างลูปเพื่ออัพเดตข้อมูลในตาราง
exec sql ดึง CurCust เข้าสู่: Id_num, :SalesPerson, :Loc, :Comm;
exec sql อัพเดต SalesPeople ตั้งค่า Comm=Comm+.01 โดยที่ปัจจุบัน
ของเคอร์คัส; ) – นำข้อมูลสำหรับการอัพเดตจากเคอร์เซอร์
exec sql ปิดเคอร์เซอร์ CurCust; — ปิดเคอร์เซอร์

SELECT S.Name, MAX(S.City) AS City, SUM(O.Amt) AS Amt จาก SalesPeople S INNER JOIN คำสั่งซื้อ O ON S.SNum=O.SNum GROUP BY S.Name ORDER BY 2

ประกาศ Cur1 เลื่อนเคอร์เซอร์สำหรับ SELECT S.Name, MAX(S.City) AS City, SUM(O.Amt) AS Amt จาก SalesPeople S INNER JOIN orders O ON S.SNum=O.SNum GROUP BY S.Name ORDER BY 2
เปิดเคอร์1
ดึงข้อมูลถัดไปจาก Cur1
ในขณะที่ @@FETCH_STATUS=0
เริ่ม
ดึงข้อมูลถัดไปจาก Cur1
จบ
ปิด Cur1
จัดสรร Cur1