ขั้นตอนการจัดเก็บและการใช้งาน การลบขั้นตอนการจัดเก็บใน T-SQL - คำสั่ง DROP PROCEDURE การดำเนินการขั้นตอนการจัดเก็บ

รวมบรรทัดในขั้นตอนของคุณ - SET NOCOUNT ON:

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

ธุรกรรม-SQL

ใช้ชื่อสคีมากับชื่อวัตถุ:

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

ธุรกรรม-SQL

SELECT * FROM dbo.MyTable -- การทำเช่นนี้เป็นสิ่งที่ดี -- แทนที่จะเป็น SELECT * FROM MyTable -- และการทำเช่นนี้ไม่ดี -- การเรียกขั้นตอน EXEC dbo.MyProc -- ดีอีกครั้ง -- แทนที่จะเป็น EXEC MyProc --แย่!

อย่าใช้คำนำหน้า "sp_" ในชื่อของขั้นตอนการจัดเก็บของคุณ:

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

ใช้ IF EXISTS (SELECT 1) แทน IF EXISTS (SELECT *):

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

ขั้นตอนการจัดเก็บ

หัวข้อของบทนี้เป็นหนึ่งในเครื่องมือที่ทรงพลังที่สุดที่นำเสนอให้กับนักพัฒนาแอปพลิเคชันฐานข้อมูล InterBase สำหรับการนำตรรกะทางธุรกิจไปใช้ ประสิทธิภาพของแอปพลิเคชันทั้งหมดและรวมศูนย์การประมวลผลข้อมูลและลดจำนวนโค้ดที่จำเป็นในการทำงานที่ได้รับมอบหมายให้เสร็จสมบูรณ์ แอปพลิเคชันฐานข้อมูลที่ค่อนข้างซับซ้อนเกือบทุกชนิดไม่สามารถทำได้โดยไม่ต้องใช้ขั้นตอนการจัดเก็บ
นอกเหนือจากข้อดีที่ทราบกันดีเหล่านี้ของการใช้โพรซีเดอร์ที่เก็บไว้ ซึ่งพบได้ทั่วไปใน DBMS เชิงสัมพันธ์ส่วนใหญ่แล้ว โพรซีเดอร์ที่เก็บไว้ของ InterBase ยังสามารถทำหน้าที่เป็นชุดข้อมูลที่เกือบสมบูรณ์ ทำให้ผลลัพธ์ที่ส่งคืนนั้นสามารถนำไปใช้ในการสืบค้น SQL ทั่วไปได้
บ่อยครั้งที่นักพัฒนามือใหม่จินตนาการว่า Stored Procedure เป็นเพียงชุดของการสืบค้น SQL เฉพาะที่ทำบางอย่างภายในฐานข้อมูล และมีความเห็นว่าการทำงานกับ Stored Procedure นั้นยากกว่าการใช้ฟังก์ชันเดียวกันในแอปพลิเคชันไคลเอนต์ในระดับสูง ภาษาระดับ
ดังนั้นขั้นตอนการจัดเก็บใน InterBase คืออะไร?
Stored Procedure (SP) เป็นส่วนหนึ่งของเมตาดาต้าฐานข้อมูล ซึ่งเป็นรูทีนย่อยที่คอมไพล์เป็นการเป็นตัวแทนภายในของ InterBase ซึ่งเขียนด้วยภาษาพิเศษ ซึ่งคอมไพเลอร์ถูกสร้างไว้ในแกนหลักของเซิร์ฟเวอร์ InteiBase
สามารถเรียกกระบวนงานที่เก็บไว้ได้จากแอปพลิเคชันไคลเอ็นต์ จากทริกเกอร์ และจากขั้นตอนที่เก็บไว้อื่นๆ ขั้นตอนที่เก็บไว้ทำงานภายในกระบวนการเซิร์ฟเวอร์และสามารถจัดการข้อมูลในฐานข้อมูล รวมทั้งส่งคืนผลลัพธ์ของการดำเนินการไปยังไคลเอนต์ที่เรียกว่า (เช่น ทริกเกอร์, HP, แอปพลิเคชัน)
พื้นฐานของความสามารถอันทรงพลังที่มีอยู่ใน HP คือภาษาการเขียนโปรแกรมขั้นตอนซึ่งรวมถึงคำสั่งที่ได้รับการแก้ไขของ SQL ปกติเช่น INSERT, UPDATE และ SELECT รวมถึงเครื่องมือสำหรับการจัดระเบียบสาขาและลูป (IF, WHILE) รวมถึง เครื่องมือการจัดการข้อผิดพลาดและสถานการณ์พิเศษ ภาษาของขั้นตอนการจัดเก็บช่วยให้คุณสามารถใช้อัลกอริธึมที่ซับซ้อนสำหรับการทำงานกับข้อมูล และเนื่องจากการมุ่งเน้นที่การทำงานกับข้อมูลเชิงสัมพันธ์ HP จึงมีขนาดกะทัดรัดกว่าขั้นตอนที่คล้ายกันในภาษาดั้งเดิมมาก
ควรสังเกตว่ามีการใช้ภาษาการเขียนโปรแกรมเดียวกันสำหรับทริกเกอร์ ยกเว้นคุณสมบัติและข้อจำกัดบางประการ ความแตกต่างระหว่างชุดย่อยของภาษาที่ใช้ในทริกเกอร์และภาษา HP มีการอภิปรายโดยละเอียดในบท "ทริกเกอร์" (ตอนที่ 1)

ตัวอย่างขั้นตอนการจัดเก็บอย่างง่าย

ถึงเวลาสร้าง Stored Procedure แรกของคุณ และใช้เป็นตัวอย่างเพื่อเรียนรู้กระบวนการสร้าง Stored Procedure แต่ก่อนอื่นเราควรพูดสองสามคำเกี่ยวกับวิธีการทำงานกับขั้นตอนการจัดเก็บ ความจริงก็คือ HP มีชื่อเสียงในฐานะเครื่องมือที่ไม่ชัดเจนและไม่สะดวกสำหรับเครื่องมือมาตรฐานที่แย่มากสำหรับการพัฒนาและแก้ไขขั้นตอนการจัดเก็บ เอกสาร InterBase แนะนำให้สร้างขั้นตอนโดยใช้ไฟล์สคริปต์ SQL ที่มีข้อความ HP ซึ่งจัดหาเป็นอินพุตให้กับล่าม isql และด้วยเหตุนี้จึงสร้างและแก้ไข HP If ในสคริปต์ SQL นี้ในขั้นตอนของการรวบรวมข้อความของขั้นตอนใน BLR (เกี่ยวกับ BLR โปรดดูบท "โครงสร้างฐานข้อมูล InterBase" (ตอนที่ 4)) หากมีข้อผิดพลาดเกิดขึ้น isql จะแสดงข้อความเกี่ยวกับบรรทัดของไฟล์สคริปต์ SQL ที่เกิดข้อผิดพลาดนี้ แก้ไขข้อผิดพลาดและทำใหม่อีกครั้ง ไม่มีการพูดคุยใด ๆ เกี่ยวกับการดีบักในความหมายสมัยใหม่ของคำนั่นคือ เกี่ยวกับการติดตามการดำเนินการด้วยความสามารถในการดูค่ากลางของตัวแปร เห็นได้ชัดว่าแนวทางนี้ไม่ได้มีส่วนทำให้ความน่าดึงดูดใจของกระบวนการจัดเก็บเพิ่มขึ้นในสายตาของนักพัฒนา
อย่างไรก็ตาม นอกเหนือจากแนวทางเรียบง่ายมาตรฐานในการพัฒนา HP แล้ว<_\ществ\ют также инструменты сторонних разработчиков, которые делают работу с хранимыми процедурами весьма удобной Большинство универсальных продуктов для работы с InterBase, перечисленных в приложении "Инструменты администратора и разработчика InterBase", предоставляют удобный инструментарий для работы с ХП. Мы рекомендуем обязательно воспользоваться одним из этих инструментов для работы с хранимыми процедурами и изложение материала будем вести в предположении, что у вас имеется удобный GUI-инструмент, избавляющий от написания традиционных SQL-скриптов
ไวยากรณ์ของกระบวนงานที่เก็บไว้อธิบายไว้ดังนี้:

สร้างชื่อขั้นตอน
[ (ประเภทข้อมูลพารามิเตอร์ [, ประเภทข้อมูลพารามิเตอร์ ...]) ]
)]
เช่น
;
< procedure_body> = []
< block>
< vanable_declaration_list> =
ประกาศประเภทข้อมูล var ของตัวแปร;

=
เริ่ม
< compound_statement>
[< compound_statement> ...]
จบ
< compound_statement> = (คำแถลง;)

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

สร้างขั้นตอน SP_Add (first_arg ความแม่นยำสองเท่า
Second_arg ความแม่นยำสองเท่า)
ผลตอบแทน (ผลลัพธ์ที่แม่นยำสองเท่า)
เช่น
เริ่ม
ผลลัพธ์=first_arg+second_arg;
ระงับ;
จบ

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

ขั้นตอนที่เก็บไว้ใช้ชนิดข้อมูลสเกลาร์ใด ๆ InteiBase ไม่อนุญาตให้ใช้อาร์เรย์และประเภทที่ผู้ใช้กำหนด - โดเมน

ถัดมาคือคีย์เวิร์ด RETURNS หลังจากนั้นพารามิเตอร์ที่ส่งคืนจะแสดงอยู่ในวงเล็บเพื่อระบุประเภท - ในกรณีนี้จะมีเพียงผลลัพธ์เดียวเท่านั้น
หากขั้นตอนไม่ควรส่งคืนพารามิเตอร์ คำว่า RETURNS และรายการพารามิเตอร์ที่ส่งคืนจะหายไป
หลังจาก RETURNSQ คีย์เวิร์ด AS จะถูกระบุ ก่อนที่คำหลัก AS จะไป ชื่อ,และหลังจากนั้น- เทคโคขั้นตอน
เนื้อความของ Stored Procedure คือรายการคำอธิบายของตัวแปรภายใน (เฉพาะที่) (ถ้ามี เราจะดูรายละเอียดเพิ่มเติมด้านล่าง) คั่นด้วยเครื่องหมายอัฒภาค (;) และกลุ่มคำสั่งที่อยู่ในวงเล็บเหลี่ยม เริ่มต้นสิ้นสุด ในกรณีนี้เนื้อความของ HP นั้นง่ายมาก - เราขอให้เพิ่มอาร์กิวเมนต์อินพุตสองตัวและกำหนดผลลัพธ์ให้กับเอาต์พุตหนึ่งจากนั้นเรียกคำสั่ง SUSPEND อีกไม่นานเราจะอธิบายสาระสำคัญของการกระทำของคำสั่งนี้ แต่ตอนนี้เราจะทราบเพียงว่าจำเป็นต้องถ่ายโอนพารามิเตอร์ส่งคืนไปยังตำแหน่งที่เรียกใช้โพรซีเดอร์ที่เก็บไว้

ตัวคั่นในกระบวนงานที่เก็บไว้

โปรดทราบว่าคำสั่งภายในขั้นตอนจะลงท้ายด้วยเครื่องหมายอัฒภาค (;) ดังที่คุณทราบ อัฒภาคเป็นตัวคั่นคำสั่งมาตรฐานใน SQL ซึ่งเป็นสัญญาณไปยังล่าม SQL ว่าข้อความคำสั่งถูกป้อนเต็มและควรเริ่มประมวลผล ปรากฎว่าหากล่าม SQL พบเครื่องหมายอัฒภาคตรงกลาง HP จะถือว่ามีการป้อนคำสั่งเต็มแล้วและจะพยายามดำเนินการส่วนหนึ่งของขั้นตอนที่เก็บไว้ ข้อสันนิษฐานนี้ย่อมไม่มีคุณธรรม แน่นอน หากคุณสร้างไฟล์ที่จะเขียนตัวอย่างข้างต้น เพิ่มคำสั่งการเชื่อมต่อจากฐานข้อมูลและพยายามรันสคริปต์ SQL นี้โดยใช้ล่าม isql ข้อผิดพลาดจะถูกส่งกลับเนื่องจากสิ่งที่ไม่คาดคิดในความเห็นของล่าม การสิ้นสุด ของคำสั่งสร้าง Stored Procedure หากคุณสร้างขั้นตอนการจัดเก็บโดยใช้ไฟล์สคริปต์ SQL โดยไม่ต้องใช้เครื่องมือสำหรับนักพัฒนา InterBase เฉพาะ ดังนั้นก่อนคำสั่งการสร้าง HP แต่ละคำสั่ง (เช่นเดียวกับทริกเกอร์) คุณจะต้องเปลี่ยนตัวแยกคำสั่งสคริปต์เป็นอักขระอื่นที่ไม่ใช่เครื่องหมายอัฒภาคและหลังข้อความ HP เพื่อเรียกคืนมันกลับมา คำสั่ง isql ที่เปลี่ยนตัวคั่นคำสั่งย่อย SQL มีลักษณะดังนี้:

กำหนดระยะเวลา

สำหรับกรณีทั่วไปของการสร้างขั้นตอนการจัดเก็บ จะมีลักษณะดังนี้:

กำหนดระยะเวลา^;
สร้างขั้นตอน some_procedure
... . .
จบ
^
กำหนดระยะเวลา ;^

การเรียกกระบวนงานที่เก็บไว้

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

เลือก *
จาก Sp_add (181.35, 23.09)

ข้อความค้นหานี้จะส่งคืนหนึ่งบรรทัดที่มีช่องผลลัพธ์เพียงช่องเดียว ซึ่งจะมีผลรวมของตัวเลข 181.35 และ 23.09 เช่น 204.44
ดังนั้น ขั้นตอนของเราจึงสามารถนำไปใช้ในการสืบค้น SQL ทั่วไปที่ดำเนินการทั้งในโปรแกรมไคลเอนต์และใน HP หรือทริกเกอร์อื่น ๆ การใช้ขั้นตอนของเรานี้เกิดขึ้นได้โดยใช้คำสั่ง SUSPEND ที่ส่วนท้ายของขั้นตอนการจัดเก็บ
ความจริงก็คือใน InterBase (และในโคลนทั้งหมด) มีขั้นตอนการจัดเก็บสองประเภท: ขั้นตอนที่เลือกได้และขั้นตอนการปฏิบัติการ ข้อแตกต่างในการทำงานของ HP ทั้งสองประเภทนี้คือ ขั้นตอนการสุ่มตัวอย่างมักจะส่งคืนชุดพารามิเตอร์เอาต์พุตหลายชุด โดยจัดกลุ่มทีละบรรทัดซึ่งดูเหมือนชุดข้อมูล ในขณะที่ขั้นตอนปฏิบัติการอาจไม่ส่งคืนพารามิเตอร์เลย หรือส่งคืนเท่านั้น พารามิเตอร์เอาต์พุตหนึ่งชุด ซึ่งแสดงรายการอยู่ใน Returns โดยที่พารามิเตอร์หนึ่งบรรทัด กระบวนการเลือกจะถูกเรียกในแบบสอบถาม SELECT และขั้นตอนที่ปฏิบัติการได้จะถูกเรียกโดยใช้คำสั่ง EXECUTE PROCEDURE
โพรซีเดอร์ที่เก็บไว้ทั้งสองชนิดมีไวยากรณ์การสร้างเหมือนกันและเป็นทางการไม่แตกต่างกัน ดังนั้นโพรซีเดอร์ที่ปฏิบัติการได้ใดๆ จึงสามารถเรียกใช้ในการสืบค้น SELECT และโพรซีเดอร์การเลือกใดๆ ก็สามารถเรียกได้โดยใช้ EXECUTE PROCEDURE คำถามคือ HP จะประพฤติตนอย่างไรเมื่อใด ประเภทต่างๆเรียก. กล่าวอีกนัยหนึ่ง ความแตกต่างอยู่ที่การออกแบบขั้นตอนสำหรับการโทรประเภทใดประเภทหนึ่งโดยเฉพาะ นั่นคือ ขั้นตอนการเลือกถูกสร้างขึ้นโดยเฉพาะเพื่อให้เรียกจากแบบสอบถาม SELECT และขั้นตอนการปฏิบัติการนั้นถูกสร้างขึ้นโดยเฉพาะเพื่อให้เรียกใช้โดยใช้ EXECUTE PROCEDURE มาดูกันว่าการออกแบบ HP ทั้งสองประเภทนี้แตกต่างกันอย่างไร
เพื่อให้เข้าใจถึงวิธีการทำงานของขั้นตอนการสุ่มตัวอย่าง คุณจะต้องเจาะลึกเข้าไปในทฤษฎีอีกเล็กน้อย ลองจินตนาการถึงแบบสอบถาม SQL ปกติเช่น SELECT ID, NAME FROM Table_example จากการดำเนินการ เราได้ตารางที่ประกอบด้วยสองคอลัมน์ (ID และ NAME) และจำนวนแถวที่แน่นอน (เท่ากับจำนวนแถวในตาราง Table_example) ตารางที่ส่งคืนจากการสืบค้นนี้เรียกอีกอย่างว่าชุด ข้อมูล SQLลองคิดดูว่าชุดข้อมูลถูกสร้างขึ้นอย่างไรในระหว่างการดำเนินการแบบสอบถามนี้ เมื่อเซิร์ฟเวอร์ได้รับแบบสอบถามแล้วจะพิจารณาว่าตารางใดที่อ้างถึง จากนั้นค้นหาว่าชุดย่อยของระเบียนใดจากตารางเหล่านี้จะต้องรวมอยู่ในผลลัพธ์ของแบบสอบถาม ถัดไป เซิร์ฟเวอร์จะอ่านแต่ละระเบียนที่ตรงกับผลลัพธ์การสืบค้น เลือกฟิลด์ที่จำเป็นจากระเบียนนั้น (ในกรณีของเราคือ ID และ NAME) และส่งไปยังไคลเอนต์ จากนั้นกระบวนการจะทำซ้ำอีกครั้ง - และต่อๆ ไปสำหรับแต่ละเรคคอร์ดที่เลือก
การพูดนอกเรื่องทั้งหมดนี้จำเป็นเพื่อให้ผู้อ่านที่รักเข้าใจว่าชุดข้อมูล SQL ทั้งหมดถูกสร้างขึ้นทีละแถวรวมถึงในขั้นตอนการจัดเก็บด้วย! และข้อแตกต่างที่สำคัญระหว่างขั้นตอนการดึงข้อมูลและขั้นตอนการปฏิบัติการก็คือ ขั้นตอนแรกได้รับการออกแบบให้ส่งคืนแถวจำนวนมาก ในขณะที่ขั้นตอนหลังได้รับการออกแบบให้ส่งคืนเพียงแถวเดียวเท่านั้น นั่นเป็นสาเหตุว่าทำไมจึงใช้แตกต่างกัน: กระบวนการเลือกถูกเรียกโดยใช้คำสั่ง SELECT ซึ่ง "ต้องการ" ขั้นตอนในการละทิ้งบันทึกทั้งหมดที่สามารถส่งคืนได้ กระบวนการปฏิบัติการถูกเรียกโดยใช้ EXECUTE PROCEDURE ซึ่งจะ "นำ" เพียงหนึ่งบรรทัดออกจาก HP และละเว้นส่วนที่เหลือ (แม้ว่าจะมีอยู่ก็ตาม!)
เรามาดูตัวอย่างขั้นตอนการสุ่มตัวอย่างเพื่อให้ชัดเจนยิ่งขึ้น สำหรับ > การให้อภัย มาสร้างขั้นตอนการจัดเก็บที่ทำงานเหมือนกับแบบสอบถาม SELECT ID, NAME FROM Table_Example ทุกประการ กล่าวคือ เพียงเลือกฟิลด์ ID และ NAME จากทั้งตาราง นี่คือตัวอย่างนี้:

สร้างขั้นตอน Simple_Select_SP
การส่งคืน (
จำนวนเต็ม procID,
procNAME วาร์ชาร์(80))
เช่น
เริ่ม
สำหรับ
เลือก ID ชื่อจาก table_example
เข้าสู่:procID, :procNAME
ทำ
เริ่ม
ระงับ;
จบ
จบ

มาดูขั้นตอนของกระบวนการนี้ที่เรียกว่า Simple_Select_SP อย่างที่คุณเห็น ไม่มีพารามิเตอร์อินพุตและมีพารามิเตอร์เอาต์พุตสองตัว - ID และ NAME สิ่งที่น่าสนใจที่สุดแน่นอนว่าอยู่ในเนื้อหาของกระบวนการ โครงสร้าง FOR SELECT ถูกใช้ที่นี่:

สำหรับ
เลือก ID ชื่อจาก table_example
เข้าสู่:procID, :procNAME
ทำ
เริ่ม

/*ทำอะไรบางอย่างกับตัวแปร procID และ procName*/

จบ

โค้ดชิ้นนี้มีความหมายดังต่อไปนี้: สำหรับแต่ละแถวที่เลือกจากตาราง Table_example ให้ใส่ค่าที่เลือกไว้ในตัวแปร procID และ procName จากนั้นทำบางสิ่งกับตัวแปรเหล่านี้
คุณอาจทำหน้าประหลาดใจแล้วถามว่า "ตัวแปร? มีตัวแปรอะไรอีกบ้าง? 9" เป็นเรื่องน่าประหลาดใจในบทนี้ที่เราสามารถใช้ตัวแปรใน Stored Procedure ได้ ในภาษา HP คุณสามารถประกาศทั้งตัวแปรในเครื่องของคุณเองภายในขั้นตอนและใช้พารามิเตอร์อินพุตและเอาต์พุตเป็นตัวแปร
ในการประกาศตัวแปรโลคอลในขั้นตอนการจัดเก็บ คุณต้องวางคำอธิบายไว้หลังคีย์เวิร์ด AS และก่อนคำแรก BEGIN คำอธิบายของตัวแปรโลคัลมีลักษณะดังนี้:

ประกาศตัวแปร ;

ตัวอย่างเช่น หากต้องการประกาศตัวแปรภายในจำนวนเต็ม Mylnt คุณจะต้องแทรกการประกาศต่อไปนี้ระหว่าง AS และ BEGIN

ประกาศตัวแปร Mylnt INTEGER;

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

procName="ชื่อบางชื่อ";

แต่กลับมาที่เนื้อหาของขั้นตอนของเรากันดีกว่า ส่วนคำสั่ง FOR SELECT ส่งคืนข้อมูลที่ไม่ใช่ตาราง - เป็นชุดข้อมูล แต่จะส่งคืนทีละแถว แต่ละฟิลด์ที่ส่งคืนจะต้องอยู่ในตัวแปรของตัวเอง: ID => procID, NAME => procName ในส่วน DO ตัวแปรเหล่านี้จะถูกส่งไปยังไคลเอนต์ที่เรียกโพรซีเดอร์โดยใช้คำสั่ง SUSPEND
ดังนั้น คำสั่ง FOR SELECT...DO จะวนซ้ำระเบียนที่เลือกในส่วน SELECT ของคำสั่ง ในเนื้อความของลูปที่เกิดจากส่วน DO บันทึกที่สร้างขึ้นถัดไปจะถูกถ่ายโอนไปยังไคลเอนต์โดยใช้คำสั่ง SUSPEND
ดังนั้น ขั้นตอนการเลือกจึงได้รับการออกแบบให้ส่งคืนแถวตั้งแต่หนึ่งแถวขึ้นไป โดยจะมีการจัดระเบียบลูปภายในเนื้อหาของ HP ที่เติมพารามิเตอร์ตัวแปรผลลัพธ์ และที่ส่วนท้ายของเนื้อหาของลูปนี้จะมีคำสั่ง SUSPEND เสมอ ซึ่งจะส่งคืนข้อมูลแถวถัดไปไปยังไคลเอนต์

คำสั่งลูปและสาขา

นอกเหนือจากคำสั่ง FOR SELECT...DO ซึ่งจัดระเบียบลูปผ่านบันทึกของการเลือกแล้ว ยังมีลูปอีกประเภทหนึ่ง - WHILE...DO ซึ่งช่วยให้คุณจัดระเบียบลูปโดยขึ้นอยู่กับการตรวจสอบเงื่อนไขใดๆ นี่คือตัวอย่างของ HP ที่ใช้ลูป WHILE..DO ขั้นตอนนี้จะคืนค่ากำลังสองของจำนวนเต็มตั้งแต่ 0 ถึง 99:

สร้าง PROCEDJRE QUAD
ผลตอบแทน (จำนวนเต็ม QUADRAT)
เช่น
ประกาศตัวแปร I จำนวนเต็ม;
เริ่ม
ฉัน = 1;
ในขณะที่(i<100) DO
เริ่ม
ควอดราต= ฉัน*ฉัน;
ฉัน=ฉัน+1;
ระงับ;
จบ
จบ

จากการดำเนินการค้นหา SELECT FROM QUAD เราจะได้รับตารางที่มีคอลัมน์ QUADRAT หนึ่งคอลัมน์ ซึ่งจะมีจำนวนเต็มกำลังสองตั้งแต่ 1 ถึง 99
นอกเหนือจากการวนซ้ำผลลัพธ์ของตัวอย่าง SQL และลูปแบบคลาสสิกแล้ว ภาษาของกระบวนงานที่เก็บไว้ยังใช้ตัวดำเนินการ IF...THEN..ELSE ซึ่งช่วยให้คุณสามารถจัดระเบียบการแยกย่อยขึ้นอยู่กับการดำเนินการของเงื่อนไขใดๆ ก็ตาม ไวยากรณ์จะคล้ายกัน ไปจนถึงตัวดำเนินการแยกส่วนส่วนใหญ่ในภาษาการเขียนโปรแกรมระดับสูง เช่น Pascal และ C.
ลองดูตัวอย่างที่ซับซ้อนมากขึ้นของขั้นตอนการจัดเก็บที่ทำดังต่อไปนี้

  1. คำนวณราคาเฉลี่ยในตาราง Table_example (ดูบท "คีย์หลักและตัวสร้างตาราง")
  2. ถัดไป สำหรับแต่ละรายการในตาราง จะมีการตรวจสอบดังต่อไปนี้: หากราคาที่มีอยู่ (PRICE) มากกว่าราคาเฉลี่ย ก็จะกำหนดราคาเท่ากับราคาเฉลี่ย บวกด้วยเปอร์เซ็นต์คงที่ที่ระบุ
  3. หากราคาที่มีอยู่น้อยกว่าหรือเท่ากับราคาเฉลี่ย ให้กำหนดราคาให้เท่ากับราคาก่อนหน้า บวกด้วยความแตกต่างครึ่งหนึ่งระหว่างราคาก่อนหน้าและราคาเฉลี่ย
  4. ส่งคืนแถวที่แก้ไขทั้งหมดในตาราง

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

สร้างขั้นตอน เพิ่มราคา (
เปอร์เซ็นต์2เพิ่มความแม่นยำสองเท่า)
ผลตอบแทน (ID INTEGER, NAME VARCHAR(SO), new_price DOUBLE
ความแม่นยำ AS

ขั้นตอนนี้เรียกว่าเพิ่มราคา โดยมีพารามิเตอร์อินพุต Peiceni21nciease ประเภท DOUBLE PRECISION หนึ่งรายการ และพารามิเตอร์เอาต์พุต 3 รายการ - ID, NAME และ new_pnce โปรดทราบว่าพารามิเตอร์เอาต์พุตสองตัวแรกมีชื่อเดียวกันกับฟิลด์ในตาราง Table_example ที่เราจะใช้งาน ซึ่งได้รับอนุญาตตามกฎของภาษาของกระบวนงานที่เก็บไว้
ตอนนี้เราจำเป็นต้องประกาศตัวแปรท้องถิ่นที่จะใช้ในการจัดเก็บค่าเฉลี่ย

ประกาศตัวแปร avg_price ความแม่นยำสองเท่า;

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

เลือก AVG(ราคา_l)
จากตาราง_ตัวอย่าง
เข้าสู่:avg_price,-

คำขอนี้ใช้ ฟังก์ชันรวม AVG ซึ่งส่งกลับค่าเฉลี่ยของช่อง PRICE_1 ในแถวข้อความค้นหาที่เลือก ในกรณีของเรา คือค่าเฉลี่ย PRICE_1 ในตาราง Table_example ทั้งหมด ค่าที่ส่งคืนโดยคำขอจะถูกวางไว้ในตัวแปร avg_price โปรดทราบว่าตัวแปร avg_pnce นำหน้าด้วยโคลอนเพื่อแยกความแตกต่างจากฟิลด์ที่ใช้ในคำขอ
ลักษณะเฉพาะของแบบสอบถามนี้คือจะส่งกลับระเบียนเดียวเสมอ คิวรีดังกล่าวเรียกว่าคิวรีซิงเกิลตัน และเฉพาะตัวเลือกดังกล่าวเท่านั้นที่สามารถใช้ได้ในขั้นตอนการจัดเก็บ หากแบบสอบถามส่งคืนมากกว่าหนึ่งแถว จะต้องจัดรูปแบบเป็นโครงสร้าง FOR SELECT...DO ซึ่งจะจัดระเบียบลูปเพื่อประมวลผลแต่ละแถวที่ส่งคืน
ดังนั้นเราจึงได้ราคาเฉลี่ย ตอนนี้คุณต้องดูทั้งตาราง เปรียบเทียบราคาในแต่ละรายการกับราคาเฉลี่ย และดำเนินการตามความเหมาะสม
จากจุดเริ่มต้น เราจัดระเบียบการค้นหาสำหรับแต่ละเรกคอร์ดจากตาราง Table_example

สำหรับ
เลือก ID, NAME, PRICE_1
จากตาราง_ตัวอย่าง
เข้าสู่:ID, :NAME, :new_price
ทำ
เริ่ม
/*_ที่นี่เราอธิบายแต่ละรายการ*/
จบ

เมื่อดำเนินการก่อสร้างนี้ ข้อมูลจะถูกแยกออกจากตาราง Table_example ทีละแถว และค่าฟิลด์ในแต่ละแถวจะถูกกำหนดให้กับตัวแปร ID, NAME และ new_pnce แน่นอนคุณจำไว้ว่าตัวแปรเหล่านี้ได้รับการประกาศเป็นพารามิเตอร์เอาต์พุต แต่ไม่ต้องกังวลว่าข้อมูลที่เลือกจะถูกส่งกลับเป็นผลลัพธ์: ความจริงที่ว่าพารามิเตอร์เอาต์พุตได้รับการกำหนดบางสิ่งบางอย่างไม่ได้หมายความว่าไคลเอนต์ที่เรียก HP จะได้รับค่าเหล่านี้ทันที ! พารามิเตอร์จะถูกส่งเมื่อมีการดำเนินการคำสั่ง SUSPEND เท่านั้น และก่อนหน้านั้นเราสามารถใช้พารามิเตอร์เอาต์พุตเป็นตัวแปรธรรมดาได้ - ในตัวอย่างของเรา เราทำเช่นนั้นด้วยพารามิเตอร์ new_price
ดังนั้นภายในเนื้อหาของลูป BEGIN... END เราสามารถประมวลผลค่าของแต่ละแถวได้ ดังที่คุณจำได้ เราจำเป็นต้องพิจารณาว่าราคาปัจจุบันเปรียบเทียบกับราคาเฉลี่ยอย่างไร และดำเนินการตามความเหมาะสม เราใช้ขั้นตอนการเปรียบเทียบนี้โดยใช้คำสั่ง IF:

IF (new_price > avg_price) แล้ว /*หากราคาปัจจุบันสูงกว่าราคาเฉลี่ย*/
เริ่ม
/*จากนั้นเราจะกำหนดราคาใหม่ให้เท่ากับราคาเฉลี่ยบวกด้วยเปอร์เซ็นต์คงที่ */
new_price = (avg_price + avg_price*(เปอร์เซ็นต์2เพิ่มขึ้น/100));
อัปเดตตาราง_ตัวอย่าง
SET PRICE_1 = :ราคาใหม่
รหัสอยู่ที่ไหน = :ID;
จบ
อื่น
เริ่ม
/* หากราคาปัจจุบันน้อยกว่าหรือเท่ากับราคาเฉลี่ย ให้ตั้งราคาเท่ากับราคาก่อนหน้าบวกด้วยส่วนต่างระหว่างราคาก่อนหน้าและราคาเฉลี่ยครึ่งหนึ่ง */
new_price = (new_pnce + ((avg_pnce new_price)/2)) ;
อัปเดตตาราง_ตัวอย่าง
SET PRICE_1 = :ราคาใหม่
รหัสที่ไหน = .ID;
จบ

อย่างที่คุณเห็น ผลลัพธ์ที่ได้คือโครงสร้าง IF ที่ค่อนข้างใหญ่ ซึ่งจะเข้าใจได้ยากหากไม่ใช่เพราะความคิดเห็นที่อยู่ในสัญลักษณ์ /**/
ในการเปลี่ยนแปลงราคาตามความแตกต่างที่คำนวณได้ เราจะใช้คำสั่ง UPDATE ซึ่งช่วยให้เราสามารถแก้ไขบันทึกที่มีอยู่ - หนึ่งรายการขึ้นไป เพื่อระบุอย่างชัดเจนว่าจำเป็นต้องเปลี่ยนราคาในบันทึกใด เราจะใช้ฟิลด์คีย์หลักในเงื่อนไข WHERE โดยเปรียบเทียบกับค่าของตัวแปรที่เก็บค่า ID สำหรับบันทึกปัจจุบัน: ID=:ID โปรดทราบว่าตัวแปร ID นำหน้าด้วยเครื่องหมายทวิภาค
หลังจากดำเนินการโครงสร้าง IF...THEN...ELSE แล้ว ตัวแปร ID, NAME และ new_price จะมีข้อมูลที่เราต้องส่งคืนไปยังไคลเอนต์ที่เรียกว่าโพรซีเดอร์ ในการดำเนินการนี้ หลังจาก IF คุณจะต้องแทรกคำสั่ง SUSPEND ซึ่งจะส่งข้อมูลไปยังตำแหน่งที่เรียกใช้ HP ในระหว่างการถ่ายโอน ขั้นตอนจะถูกระงับ และเมื่อจำเป็นต้องใช้ HP รายการใหม่จากนั้นจะมีการดำเนินการต่ออีกครั้ง และจะดำเนินต่อไปจนกระทั่ง FOR SELECT...DO วนซ้ำผ่านบันทึกทั้งหมดของแบบสอบถาม
ควรสังเกตว่านอกเหนือจากคำสั่ง SUSPEND ซึ่งจะระงับเฉพาะกระบวนงานที่เก็บไว้เท่านั้น ยังมีคำสั่ง EXIT ที่ยุติกระบวนงานที่เก็บไว้หลังจากผ่านสตริงแล้ว อย่างไรก็ตาม คำสั่ง EXIT ถูกใช้ค่อนข้างน้อย เนื่องจากคำสั่งดังกล่าวจำเป็นสำหรับการขัดจังหวะลูปเป็นหลักเมื่อถึงเงื่อนไข
อย่างไรก็ตาม ในกรณีที่เรียกใช้โพรซีเดอร์ด้วยคำสั่ง SELECT และเสร็จสิ้นด้วย EXIT แถวสุดท้ายที่ดึงมาจะไม่ถูกส่งคืน นั่นคือ หากคุณต้องการขัดจังหวะโพรซีเดอร์แต่ยังคง >รับสตริงนี้ คุณจะต้องใช้ลำดับ

ระงับ;
ออก;

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

สร้างขั้นตอน เพิ่มราคา (
เปอร์เซ็นต์2เพิ่มความแม่นยำสองเท่า)
ผลตอบแทน (ID INTEGER, ชื่อ VARCHAR(80),
new_price ความแม่นยำสองเท่า) AS
ประกาศตัวแปร avg_price ความแม่นยำสองเท่า;
เริ่ม
เลือก AVG(ราคา_l)
จากตาราง_ตัวอย่าง
INTO:avg_price;
สำหรับ
เลือก ID, NAME, PRICE_1
จากตาราง_ตัวอย่าง
เข้าสู่:ID, :NAME, :new_price
ทำ
เริ่ม
/*ประมวลผลแต่ละบันทึกที่นี่*/
IF (new_pnce > avg_price) แล้ว /*หากราคาปัจจุบันสูงกว่าราคาเฉลี่ย*/
เริ่ม
/*กำหนดราคาใหม่เท่ากับราคาเฉลี่ยบวกเปอร์เซ็นต์คงที่ */
new_price = (avg_price + avg_price*(เปอร์เซ็นต์2lncrease/100));
อัปเดตตาราง_ตัวอย่าง
SET PRICE_1 = :ราคาใหม่
รหัสอยู่ที่ไหน = :ID;
จบ
อื่น
เริ่ม
/* หากราคาปัจจุบันน้อยกว่าหรือเท่ากับราคาเฉลี่ย ให้ตั้งราคาเท่ากับราคาก่อนหน้าบวกด้วยส่วนต่างครึ่งหนึ่งระหว่างราคาก่อนหน้าและราคาเฉลี่ย */
new_price = (new_price + ((ราคาเฉลี่ย - new_price)/2));
อัปเดตตาราง_ตัวอย่าง
SET PRICE_1 = :ราคาใหม่
รหัสอยู่ที่ไหน = :ID;
จบ
ระงับ;
จบ
จบ

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

ขั้นตอนการจัดเก็บแบบเรียกซ้ำ

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

สินค้า
- เครื่องใช้ในครัวเรือน
- ตู้เย็น
- สามห้อง
- ห้องคู่
- ห้องเดี่ยว
- เครื่องซักผ้า
- แนวตั้ง
- หน้าผาก
- คลาสสิค
- แคบ
- เทคโนโลยีคอมพิวเตอร์
....

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

เครื่องซักผ้า-แนวตั้ง
เครื่องซักผ้า-ฝาหน้าคลาสสิค
เครื่องซักผ้า-หน้าแคบ

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

สร้างตาราง GoodsTree
(ID_GOOD จำนวนเต็มไม่เป็นโมฆะ
ID_PARENT_GOOD จำนวนเต็ม
วาร์ชาร์ GOOD_NAME(80)
ข้อ จำกัด คีย์หลัก pkGooci (ID_GOOD));

เราสร้างหนึ่งตาราง GoodsTree ซึ่งมีเพียง 3 ฟิลด์: ID_GOOD - ตัวระบุอัจฉริยะของหมวดหมู่ ID_PARENT_GOOD - ตัวระบุของบริษัทแม่สำหรับหมวดหมู่นี้ และ GOOD_NAME - ชื่อของหมวดหมู่ เพื่อให้มั่นใจในความสมบูรณ์ของข้อมูลในตารางนี้ เราจะกำหนดข้อจำกัดคีย์ต่างประเทศในตารางนี้:

เปลี่ยนตาราง GoodsTree
เพิ่มข้อจำกัด FK_goodstree
คีย์ต่างประเทศ (ID_PARENT_GOOD)
ข้อมูลอ้างอิง GoodSTPEE (ID__GOOD)

ตารางอ้างอิงถึงตัวมันเอง และคีย์ต่างประเทศนี้จะคอยติดตามข้อมูลนั้น เพื่อให้ตารางไม่มีการอ้างอิงถึงผู้ปกครองที่ไม่มีอยู่จริง และยังป้องกันการพยายามลบหมวดหมู่ผลิตภัณฑ์ที่มีรายการลูกด้วย
มาป้อนข้อมูลต่อไปนี้ลงในตารางของเรา:

ID_ดี

1
2
3
4
5
6
7
8
9
10
11
12

ID_PARENT_GOOD

0
1
1
2
2
4
4
4
5
5
10
10

GOOD_NAME

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

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

สร้างขั้นตอน GETFULLNAME (ID_GOOD2SHOW Integer)
การส่งคืน (FULL_GOODS_NAME VARCHAR(1,000)
ID_CHILD_GOOD จำนวนเต็ม)
เช่น
ประกาศตัวแปร CURR_CHILD_NAME VARCHAR(80);
เริ่ม
/*0จัดระเบียบภายนอก สำหรับห่วง SELECT บนผู้สืบทอดลำดับถัดไปของผลิตภัณฑ์ที่มี ID_GOOD=ID_GOOD2SHOW */
สำหรับการเลือก gtl.id_good, gtl.good_name
จาก GoodsTree gtl
โดยที่ gtl.id_parent_good=:ID_good2show
เข้าสู่:ID_CHILD_GOOD, :full_goods_name
ทำ
เริ่ม
/"ตรวจสอบโดยใช้ฟังก์ชัน EXISTS ซึ่งจะคืนค่า TRUE หากแบบสอบถามในวงเล็บส่งคืนอย่างน้อยหนึ่งแถว หากโหนดที่พบที่มี ID_PARENT_GOOD = ID_CHILD_GOOD ไม่มีรายการย่อย แสดงว่าจะเป็น “leaf” ของแผนผังและรวมอยู่ในผลลัพธ์ */
ถ้า (ไม่มีอยู่(
เลือก * จาก GoodsTree
โดยที่ GoodsTree.id_parent_good=:id_child_good))
แล้ว
เริ่ม
/* ส่ง “ใบไม้” ของต้นไม้ไปสู่ผลลัพธ์ */
ระงับ;
จบ
อื่น
/* สำหรับโหนดที่มีลูก */
เริ่ม
/*บันทึกชื่อของโหนดหลักในตัวแปรชั่วคราว */
CURR_CHILD_NAME=ชื่อสินค้าเต็ม;
/* รันโพรซีเดอร์นี้ซ้ำ ๆ */
สำหรับ
เลือก ID_CHILD_GOOD, full_goods_name
จาก GETFULLNAME (:ID_CHILD_GOOD)
เข้าสู่:ID_CHILD_GOOD, :full_goods_name
เริ่มต้นเลย
/*เพิ่มชื่อของโหนดพาเรนต์ให้กับชื่อลูกที่พบโดยใช้การดำเนินการต่อสตริง || -
full_goods_name=CURR_CHILD_NAME| - f ull_goods_name,-
ระงับ; /* คืนชื่อเต็มของผลิตภัณฑ์*/
จบ
จบ
จบ
จบ

หากเราดำเนินการตามขั้นตอนนี้ด้วยพารามิเตอร์อินพุต ID_GOOD2SHOW= 1 เราจะได้รับสิ่งต่อไปนี้:

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

บทสรุป

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

เมื่อใดที่ฉันควรใช้กระบวนงานที่เก็บไว้ และเมื่อใดที่ฉันควรใช้มุมมองใน SQL Server

สิทธิ์ช่วยให้เราสามารถสร้างแบบสอบถามแบบไดนามิกที่เราสามารถส่งพารามิเตอร์?

อันไหนเร็วที่สุดและเร็วกว่าอันอื่นบนพื้นฐานอะไร?

มุมมองหรือขั้นตอนการจัดเก็บจะเก็บหน่วยความจำไว้อย่างถาวรหรือไม่

หมายความว่าอย่างไรถ้ามีคนบอกว่ามุมมองสร้างตารางเสมือนและขั้นตอนสร้างสารบัญ?

โปรดแจ้งให้เราทราบเกี่ยวกับจุดเพิ่มเติมหากมี

โซลูชันที่รวบรวมจากเว็บของ "อะไรคือความแตกต่างระหว่างขั้นตอนการจัดเก็บและมุมมอง"

วิวคือ เสมือนโต๊ะ. คุณสามารถรวมหลายตารางในมุมมองเดียว และใช้มุมมองนั้นเพื่อนำเสนอข้อมูลเสมือนว่าข้อมูลมาจากตารางเดียว

Stored Procedure ใช้พารามิเตอร์เพื่อทำหน้าที่...ไม่ว่าจะอัปเดตและแทรกข้อมูลหรือส่งคืนค่าแต่ละค่าหรือชุดข้อมูล

การสร้างมุมมองและขั้นตอนการจัดเก็บ - มีข้อมูลบางอย่างจาก Microsoft ว่าควรใช้เมื่อใดและเพราะเหตุใด

สมมติว่าฉันมีสองตาราง:

คอลัมน์ tbl_user: .user_id, .user_name, .user_pw

คอลัมน์ tbl_profile: .profile_id, .user_id .profile_description

ดังนั้นหากฉันกำลังสืบค้นจากตาราง ALOT เหล่านี้... แทนที่จะทำการเข้าร่วมในทุก ๆ sql ฉันจะกำหนดมุมมองดังนี้:

สร้าง ดู vw_user_profile AS เลือก A.user_id, B.profile_description จาก tbl_user A เหลือการรวม tbl_profile B บน A.user_id = b.user_id GO

ดังนั้นในอนาคตหากฉันต้องการสืบค้น profile_description โดย userid... สิ่งที่ฉันต้องทำคือ

เลือกprofile_descriptionจากvw_user_profileโดยที่ user_id = @ID

รหัสนี้สามารถใช้ในขั้นตอนการจัดเก็บ เช่น:

สร้างขั้นตอน dbo.getDesc @ID int AS เริ่มต้น SELECT profile_description จาก vw_user_profile WHERE user_id = @ID END GO

หลังจากนั้นฉันสามารถโทรได้

Dbo.getDesc25

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

แน่นอนว่ายังมีอะไรอีกมากมาย แต่นั่นเป็นเพียงแนวคิดพื้นฐานเท่านั้น

ก่อนอื่นคุณต้องเข้าใจว่าทั้งสองสิ่งต่างกัน ขั้นตอนที่เก็บไว้เหมาะที่สุดสำหรับคำสั่ง INSERT-UPDATE-DELETE และ Views ใช้สำหรับคำสั่ง SELECT และคุณควรใช้ทั้งสองอย่าง

ในมุมมอง คุณไม่สามารถเปลี่ยนแปลงข้อมูลได้

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

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

สามารถใช้มุมมองใน Stored Procedure ได้ แต่ไม่สามารถใช้ Stored Procedure ใน Views...!

ขั้นตอนการจัดเก็บจะใช้เมื่อ SQL อย่างง่ายมันไม่เพียงพอ ขั้นตอนการจัดเก็บประกอบด้วยตัวแปร ลูป และการเรียกขั้นตอนการจัดเก็บอื่นๆ มันเป็นภาษาโปรแกรม ไม่ใช่ภาษาคิวรี

    การดูเป็นแบบคงที่ ให้มองว่าเป็นตารางใหม่ที่มีเค้าโครงเฉพาะ และข้อมูลในตารางจะถูกสร้างขึ้นทันทีโดยใช้แบบสอบถามที่คุณสร้างขึ้น เช่นเดียวกับตาราง SQL อื่นๆ คุณสามารถจัดเรียงและกรองโดยใช้ WHERE , GROUP BY และ ORDER BY

    มันขึ้นอยู่กับสิ่งที่คุณกำลังทำ

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

    มุมมองที่เป็นรูปธรรมช่วยให้คุณสร้างดัชนีในคอลัมน์มุมมอง (โดยเฉพาะในคอลัมน์จากการคำนวณที่ไม่มีอยู่ในฐานข้อมูล)

    ฉันไม่เข้าใจสิ่งที่คุณกำลังพูดถึง

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

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

มุมมองคือการแสดงข้อมูลอย่างง่ายที่จัดเก็บไว้ในตารางฐานข้อมูล ในขณะที่ Stored Procedure คือกลุ่มของคำสั่งที่สามารถดำเนินการได้

มุมมองจะเร็วขึ้นเนื่องจากจะแสดงข้อมูลจากตารางที่อ้างอิง ในขณะที่ขั้นตอนการจัดเก็บดำเนินการคำสั่ง SQL

ลองอ่านบทความนี้: ดูเทียบกับขั้นตอนการจัดเก็บ สิ่งที่คุณกำลังมองหา

@Patrick ถูกต้องกับสิ่งที่เขาพูด แต่เพื่อตอบคำถามอื่น ๆ ของคุณ View จะสร้างตัวเองในหน่วยความจำและขึ้นอยู่กับประเภทของการรวมข้อมูลและหากการรวมกลุ่มใด ๆ เสร็จสิ้น ก็อาจเป็นมุมมองที่ค่อนข้างหิว

ขั้นตอนที่เก็บไว้ทำการประมวลผลทั้งหมดโดยใช้ Temp Hash Table เช่น #tmpTable1 หรือในหน่วยความจำโดยใช้ @tmpTable1 ขึ้นอยู่กับสิ่งที่คุณต้องการจะพูด

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

แน่นอนว่าตารางหน่วยความจำเวลาส่วนใหญ่จะเร็วกว่า เว้นแต่ว่าคุณจะดึงข้อมูลจำนวนมาก

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

สร้าง ดู vw_user_profile AS เลือก A.user_id, B.profile_description จาก tbl_user A เหลือการรวม tbl_profile B บน A.user_id = b.user_id

ฉันสามารถอัปเดตข้อมูลได้... ดังตัวอย่าง ฉันสามารถทำสิ่งเหล่านี้ได้...

อัพเดต vw_user_profile ตั้งprofile_description="Manager" โดยที่ user_id=4

อัปเดต tbl_profile ตั้งprofile_description="Manager" โดยที่ user_id=4

คุณไม่สามารถ INSERT ลงในมุมมองนี้ได้ เนื่องจากไม่มีฟิลด์ทั้งหมดในตารางทั้งหมด และฉันถือว่า PROFILE_ID เป็นคีย์หลักและไม่สามารถเป็น NULL ได้ อย่างไรก็ตาม บางครั้งคุณอาจต้องการ INSERT ลงในมุมมอง...

ฉันได้สร้างมุมมองสำหรับตารางที่มีอยู่โดยใช้...

สร้าง View Junk เป็น SELECT * from

แทรกลงในค่าขยะ (รหัสชื่อ) ("glyn", "Glyn Roberts"), ("Mary", "Maryann Roberts")

ลบออกจากขยะ โดยที่ ID>4

ทั้ง INSERT และ DELETE ทำงานในกรณีนี้

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

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

นอกเหนือจากความคิดเห็นข้างต้น ฉันอยากจะเพิ่มหมายเหตุบางประการเกี่ยวกับ Views

  1. การแสดงแทนสามารถใช้เพื่อซ่อนความซับซ้อนได้ ลองนึกภาพสถานการณ์ที่มีคน 5 คนกำลังทำงานในโครงการหนึ่ง แต่มีเพียงหนึ่งคนเท่านั้นที่ดีเกินไปกับฐานข้อมูล เช่น การรวมที่ซับซ้อน ในสถานการณ์เช่นนี้ เขาสามารถสร้างมุมมองที่สมาชิกในทีมคนอื่นๆ สามารถสืบค้นได้อย่างง่ายดายในขณะที่พวกเขาสืบค้นตารางใดตารางหนึ่ง
  2. การรักษาความปลอดภัยสามารถนำไปใช้ได้อย่างง่ายดายโดย Views สมมุติว่าเรา พนักงานตารางที่มีคอลัมน์ที่ละเอียดอ่อนเช่น เงินเดือน , หมายเลขเอสเอสเอ็น- คอลัมน์เหล่านี้ไม่ควรปรากฏแก่ผู้ใช้ที่ไม่ได้รับอนุญาตให้ดู ในกรณีนี้เราสามารถสร้างมุมมองที่จะเลือกคอลัมน์ในตารางที่ไม่จำเป็นต้องมีการอนุญาต เช่น ชื่อ , อายุและฯลฯ โดยไม่เปิดเผยคอลัมน์ที่มีช่องโหว่ (เช่น เงินเดือน ฯลฯ ที่เรากล่าวถึงข้างต้น) ตอนนี้เราสามารถลบสิทธิ์ในการสืบค้นตารางได้โดยตรง พนักงานและเพียงเก็บสิทธิ์การอ่านไว้ในมุมมอง ดังนั้นเราจึงสามารถใช้การรักษาความปลอดภัยโดยใช้ Views

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

เริ่มจากข้อโต้แย้งต่อ:

ตรรกะทางธุรกิจที่เปื้อน

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

ความขาดแคลนของภาษา DBMS

มีสิ่งนั้นอยู่ ภาษาดั้งเดิมสำหรับการเขียน HF pl/sql, t-sql, pl/pgsql นั้นค่อนข้างดั้งเดิมเมื่อเทียบกับ ภาษาสมัยใหม่วัตถุประสงค์ทั่วไป เป็นที่น่าสังเกตว่ามีความเป็นไปได้ที่จะเขียน HF ในภาษาขั้นสูง เช่น Java ใน Oracle หรือ Python ใน postgresql

การไม่ทนต่อฟังก์ชั่นที่เก็บไว้

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

ขาดทักษะที่จำเป็นในทีมและ "ต้นทุน" ที่สูงของผู้เชี่ยวชาญที่เกี่ยวข้อง

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

ตอนนี้ข้อดี:

ความเร็ว

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

การซ่อนโครงสร้างข้อมูล

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

การจัดการสิทธิ์การเข้าถึงที่ยืดหยุ่น

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

โอกาสในการฉีด SQL น้อยลง

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

การใช้ SQL ซ้ำ

ด้วยการใช้ตรรกะในการทำงานกับข้อมูลในเลเยอร์ที่เก็บไว้ เราจะได้แบบจำลองลำดับชั้นที่คุ้นเคยของการทำซ้ำ โดยใช้ SQLรหัส.
เมื่อใช้ไดนามิก SQL การใช้คิวรีซ้ำเป็นเรื่องยาก
ตัวอย่างเช่น ให้มีระบบ A ที่ใช้ HF และระบบ B ที่ใช้ Dynamic SQL ทั้งสองระบบมีฟังก์ชันสำหรับรับราคาของสินค้า get_price ในกรณี A นี่คือฟังก์ชันหรือมุมมองที่เก็บไว้ ในกรณี B สมมติว่าเป็นขั้นตอนจาวาที่ดำเนินการแบบสอบถาม SQL ผ่าน JDBC มีภารกิจ - รับต้นทุนรวมของสินค้าในคลังสินค้า ในกรณี A เรารวม get_price โดยตรงกับแบบสอบถามที่ได้รับรายการสินค้าในคลังสินค้า (หาก get_price เป็นมุมมองหรือ HF ใน SQL เช่นใน PostgreSQL เครื่องมือเพิ่มประสิทธิภาพจะขยายแบบสอบถามแบบอินไลน์ - ดังนั้นจึงได้รับหนึ่งแบบสอบถามที่รวดเร็ว หาจำนวนเงิน)
ในกรณี B มีสองตัวเลือก - วิ่งผ่านเคอร์เซอร์พร้อมกับเลือกสินค้าในคลังสินค้าและเรียก get_price n ครั้ง (ซึ่งหมายความว่าการเลือกทั้งหมดจะต้องส่งผ่านเครือข่ายไปยังไคลเอนต์) หรือลืมการใช้ซ้ำและเขียน แบบสอบถามย่อยที่ซ้ำกับแบบสอบถามที่เขียนไว้แล้วใน get_price ตัวเลือกทั้งสองไม่ดี

การดีบัก SQL อย่างง่าย

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

เมื่อใดจึงควรเขียนตรรกะทางธุรกิจลงในฐานข้อมูล?

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

เมื่อไหร่จะปล่อยโค้ด?

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

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

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

1. ทำงานตามตัวอย่างทั้งหมด วิเคราะห์ผลลัพธ์ของการดำเนินการในยูทิลิตี้ SQL Server Management Studio ตรวจสอบการมีอยู่ของขั้นตอนที่สร้างขึ้นในฐานข้อมูลปัจจุบัน

2. ทำตัวอย่างและงานทั้งหมดให้เสร็จสิ้นระหว่างการทำงานในห้องปฏิบัติการ

3. ทำงานแต่ละอย่างให้เสร็จสิ้นตามตัวเลือก

คำชี้แจงในการปฏิบัติงาน

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

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

ประเภทของขั้นตอนการจัดเก็บ

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

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

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

การสร้าง การแก้ไขขั้นตอนการจัดเก็บ

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

ไวยากรณ์ของตัวดำเนินการสำหรับการสร้างใหม่หรือการเปลี่ยนแปลงขั้นตอนการจัดเก็บที่มีอยู่ในรูปแบบ MS SQL Server:

( สร้าง | แก้ไข ) PROC[ EDURE] Procedure_name [ ;number] [ ( @parameter_name data_type ) [ VARYING ] [ = DEFAULT ] [ OUTPUT ] ] [ ,... n] [ WITH ( RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION ) ] [ สำหรับการจำลอง] AS sql_statement [ ... n]

มาดูพารามิเตอร์ของคำสั่งนี้กัน

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

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

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

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

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

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

การลบขั้นตอนการจัดเก็บ

วางขั้นตอน (procedure_name) [,...n]

การดำเนินการขั้นตอนการจัดเก็บ

หากต้องการดำเนินการขั้นตอนที่เก็บไว้ ให้ใช้คำสั่ง: [ [ EXEC [ UTE] Procedure_name [ ;number] [ [ @parameter_name= ] ( value | @variable_name) [ OUTPUT ] | [ ค่าเริ่มต้น ] ] [ ,... n]

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

อนุญาตให้ใช้คีย์เวิร์ด OUTPUT เมื่อเรียกใช้โพรซีเดอร์เฉพาะกับพารามิเตอร์ที่ได้รับการประกาศเมื่อสร้างโพรซีเดอร์ด้วยคีย์เวิร์ด OUTPUT

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

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

โปรดทราบว่าเมื่อเรียกโพรซีเดอร์จะระบุชื่อพารามิเตอร์ที่มีค่าหรือเฉพาะค่าที่ไม่มีชื่อพารามิเตอร์เท่านั้น ไม่อนุญาตให้รวมเข้าด้วยกัน

การใช้ RETURN ในขั้นตอนการจัดเก็บ

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

สร้างขั้นตอน Count_Books AS SELECT COUNT (Code_book) จากหนังสือ GO

ภารกิจที่ 1

EXEC Count_Books

ตรวจสอบผลลัพธ์

ตัวอย่างการสร้างขั้นตอนด้วยพารามิเตอร์อินพุต:

สร้างขั้นตอน Count_Books_Pages @Count_pages AS INT AS SELECT COUNT (Code_book) จากหนังสือ WHERE Pages>= @Count_pages GO

ภารกิจที่ 2- สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้คำสั่ง

EXEC นับ_หนังสือ_หน้า 100

ตรวจสอบผลลัพธ์

ตัวอย่างการสร้างขั้นตอนด้วยพารามิเตอร์อินพุต:

สร้างขั้นตอนการสร้าง Count_Books_Title @Count_pages AS INT , @Title AS CHAR (10 ) AS SELECT COUNT (Code_book) จากหนังสือ WHERE Pages>= @Count_pages AND Title_book LIKE @Title GO

ภารกิจที่ 3สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้คำสั่ง

EXEC Count_Books_Title 100 , "P%"

ตรวจสอบผลลัพธ์

ตัวอย่างการสร้างขั้นตอนด้วยพารามิเตอร์อินพุตและพารามิเตอร์เอาต์พุต:

สร้างขั้นตอน Count_Books_Itogo @Count_pages INT , @Title CHAR (10 ) , @Itogo INT OUTPUT AS SELECT @Itogo = COUNT (Code_book) จากหนังสือ WHERE Pages>= @Count_pages AND Title_book LIKE @Title GO

ภารกิจที่ 4สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้ชุดคำสั่ง:

Sql> ประกาศ @q เป็น int EXEC Count_Books_Itogo 100, "P%", @q เอาต์พุตเลือก @q

ตรวจสอบผลลัพธ์

ตัวอย่างการสร้างขั้นตอนด้วยพารามิเตอร์อินพุตและ RETURN:

สร้างขั้นตอนการตรวจสอบชื่อ @param INT AS IF (เลือก Name_author จากผู้เขียน WHERE Code_author = @param) = "Pushkin A.S."

ส่งคืน 1 มิฉะนั้นส่งคืน 2ภารกิจที่ 5

สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้คำสั่ง:

ประกาศ @return_status INT EXEC @return_status = ชื่อตรวจสอบ 1 เลือก "สถานะการคืนสินค้า" = @return_status

ตัวอย่างการสร้างขั้นตอนโดยไม่มีพารามิเตอร์เพื่อเพิ่มค่าของฟิลด์คีย์ในตารางการซื้อ 2 เท่า:

สร้าง PROC update_proc AS UPDATE ซื้อ SET Code_purchase = Code_purchase* 2ภารกิจที่ 6

สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้คำสั่ง

EXEC อัพเดต_proc

ตัวอย่างของขั้นตอนที่มีพารามิเตอร์อินพุตเพื่อรับข้อมูลทั้งหมดเกี่ยวกับผู้เขียนเฉพาะ:

สร้าง PROC select_author @k CHAR (30 ) AS SELECT * จากผู้เขียน WHERE name_author= @k

ภารกิจที่ 7

EXEC select_author "พุชกิน A.S."

หรือ select_author @k= "Pushkin A.S."

หรือ EXEC select_author @k= "Pushkin A.S."

ตัวอย่างการสร้างขั้นตอนด้วยพารามิเตอร์อินพุตและค่าเริ่มต้นเพื่อเพิ่มค่าของฟิลด์คีย์ในตารางการซื้อตามจำนวนครั้งที่ระบุ (2 ครั้งโดยค่าเริ่มต้น):สร้าง PROC update_proc @p INT = 2 AS อัปเดตการซื้อ SET Code_purchase = Code_purchase * @p

ขั้นตอนไม่ส่งคืนข้อมูลใดๆ ภารกิจที่ 8

สร้างขั้นตอนนี้ในส่วน Stored Procedures ของฐานข้อมูล DB_Books โดยใช้ยูทิลิตี้ Studio จัดการเซิร์ฟเวอร์ SQL รันโดยใช้คำสั่ง:

EXEC update_proc 4 หรือ EXEC update_proc @p = 4 หรือ EXEC update_proc

--จะใช้ค่าเริ่มต้นสร้าง PROC update_proc @p INT = 2 AS อัปเดตการซื้อ SET Code_purchase = Code_purchase * @p

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

สร้าง PROC count_purchases @d1 SMALLDATETIME, @d2 SMALLDATETIME, @c INT OUTPUT AS SELECT @c= COUNT (Code_purchase) จากการซื้อ WHERE Date_order BETWEEN @d1 AND @d2 SET @c = ISNULL(@c, 0 ) ภารกิจที่ 9 №4

ประกาศ @c2 INT EXEC count_purchases '01-มิ.ย.- 2549 ', '01- ก.ค.- 2549', @c2 OUTPUT SELECT @c2ตัวเลือกสำหรับงาน งานห้องปฏิบัติการสำหรับรหัส (ปุ่ม "สร้างคำขอ") ทำให้ฐานข้อมูล DB_Books ที่สร้างขึ้นโดยทางโปรแกรมใช้งานได้โดยใช้คำสั่ง Use สร้างขั้นตอนการจัดเก็บโดยใช้คำสั่งสร้างขั้นตอน และกำหนดชื่อของขั้นตอนด้วยตนเอง แต่ละขั้นตอนจะดำเนินการหนึ่งแบบสอบถาม SQL ที่ถูกดำเนินการในห้องปฏิบัติการที่สอง นอกจากนี้จำเป็นต้องเปลี่ยนรหัส SQL ของแบบสอบถามเพื่อให้สามารถส่งค่าของฟิลด์ที่ใช้ในการค้นหาได้

ตัวอย่างเช่น งานเริ่มแรกและคำขอในห้องปฏิบัติการหมายเลข 2:

/*เลือกจากไดเร็กทอรีซัพพลายเออร์ (ตารางการจัดส่ง) ชื่อบริษัท หมายเลขโทรศัพท์ และ INN (ฟิลด์ Name_company, โทรศัพท์ และ INN) ซึ่งมีชื่อบริษัท (ฟิลด์ Name_company) คือ “OJSC MIR”

เลือก Name_company, โทรศัพท์, INN จากการจัดส่ง โดยที่ Name_company = "OJSC MIR"

*/ –ในงานนี้ ขั้นตอนต่อไปนี้จะถูกสร้างขึ้น:

สร้าง PROC select_name_company @comp CHAR (30 ) AS เลือก Name_company, โทรศัพท์, INN จากการจัดส่ง โดยที่ Name_company = @comp

–หากต้องการเริ่มขั้นตอน ให้ใช้คำสั่ง:

EXEC select_name_company "JSC MIR"

รายการงาน

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

ตัวเลือกที่ 1

1. แสดงรายชื่อพนักงานที่มีบุตรอย่างน้อยหนึ่งคน

2. แสดงรายชื่อเด็กที่ได้รับของขวัญในช่วงระยะเวลาที่กำหนด

3.แสดงรายชื่อผู้ปกครองที่มีบุตรที่ยังไม่บรรลุนิติภาวะ

4. แสดงข้อมูลเกี่ยวกับของขวัญที่มีค่ามากกว่าจำนวนที่กำหนดโดยเรียงตามวันที่

ตัวเลือกที่ 2

1.แสดงรายการอุปกรณ์ตามประเภทที่ระบุ

2. แสดงจำนวนเครื่องที่ซ่อมและยอดรวมค่าซ่อมจากช่างที่ระบุ

3. แสดงรายชื่อเจ้าของอุปกรณ์และจำนวนคำขอ โดยจัดเรียงตามจำนวนคำขอจากมากไปน้อย

4. แสดงข้อมูลเกี่ยวกับช่างฝีมือที่มียศมากกว่าจำนวนที่กำหนดหรือวันที่จ้างงานน้อยกว่าวันที่กำหนด

ตัวเลือกที่ 3

2. แสดงรายการรหัสการขายที่ขายดอกไม้เกินจำนวนที่กำหนด

3. แสดงวันที่ขาย จำนวน ผู้ขาย และดอกไม้ ตามรหัสการขายที่ระบุ

4. แสดงรายการดอกไม้และพันธุ์ดอกไม้ที่มีความสูงเกินจำนวนหรือบานที่กำหนด

ตัวเลือกที่ 4

1.แสดงรายการยาพร้อมข้อบ่งชี้ในการใช้

2. แสดงรายการวันที่จัดส่งซึ่งมีการขายยาชื่อเดียวกันเกินจำนวนที่ระบุ

3. แสดงวันที่จัดส่ง จำนวน ชื่อเต็มของผู้จัดการจากผู้จำหน่าย และชื่อยาตามรหัสใบเสร็จรับเงินที่มากกว่าจำนวนที่กำหนด

ตัวเลือกที่ 5

2.แสดงรายการอุปกรณ์ที่เลิกใช้งานด้วยเหตุผลที่กำหนด

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

4. แสดงรายการอุปกรณ์ตามประเภทที่ระบุหรือวันที่รับสินค้ามากกว่าค่าที่กำหนด

ตัวเลือกที่ 6

1. แสดงรายการอาหารที่มีน้ำหนักมากกว่าจำนวนที่กำหนด

2. แสดงรายการผลิตภัณฑ์ที่มีชื่อที่มีส่วนของคำที่ระบุ

3. แสดงปริมาณสินค้า ชื่อจาน ชื่อผลิตภัณฑ์ พร้อมรหัสจานจากที่ระบุ ค่าเริ่มต้นที่ค่าสุดท้ายที่แน่นอน

4. แสดงลำดับการเตรียมอาหารและชื่ออาหารที่มีปริมาณคาร์โบไฮเดรตมากกว่าค่าที่กำหนดหรือปริมาณแคลอรี่มากกว่าค่าที่กำหนด

ตัวเลือก 7

1. แสดงรายชื่อพนักงานตามตำแหน่งที่กำหนด

3. แสดงวันที่จดทะเบียน ประเภทเอกสาร ชื่อเต็มของนายทะเบียน และชื่อหน่วยงานสำหรับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายการเอกสารที่ลงทะเบียนพร้อมประเภทเอกสารเฉพาะหรือวันที่ลงทะเบียนมากกว่าค่าที่กำหนด

ตัวเลือกที่ 8

1. แสดงรายชื่อพนักงานพร้อมระบุเหตุผลในการเลิกจ้าง

3. แสดงวันที่ลงทะเบียน เหตุผลในการเลิกจ้าง ชื่อนามสกุล ลูกจ้าง สำหรับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

ตัวเลือก 9

1. แสดงรายชื่อพนักงานที่ลาตามประเภทที่กำหนด

2.แสดงรายการเอกสารที่มีวันจดทะเบียนในช่วงเวลาที่กำหนด

3. แสดงวันที่ลงทะเบียน, ประเภทการลา, ชื่อเต็มของพนักงานสำหรับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายการเอกสารที่ลงทะเบียนพร้อมรหัสเอกสารในช่วงที่กำหนด

ตัวเลือกที่ 10

1. แสดงรายชื่อพนักงานตามตำแหน่งที่กำหนด

2. แสดงรายการเอกสารที่มีเนื้อหามีส่วนของคำที่ระบุ

3. แสดงวันที่ลงทะเบียน ประเภทเอกสาร ชื่อนามสกุลของผู้ส่ง และชื่อหน่วยงานสำหรับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายการเอกสารที่ลงทะเบียนตามประเภทเอกสารที่ระบุหรือรหัสเอกสารน้อยกว่าค่าที่กำหนด

ตัวเลือกที่ 11

1. แสดงรายชื่อพนักงานที่ได้รับมอบหมายให้ดำรงตำแหน่งที่กำหนด

2.แสดงรายการเอกสารที่มีวันจดทะเบียนในช่วงเวลาที่กำหนด

3. แสดงวันที่ลงทะเบียน ตำแหน่ง ชื่อเต็มของพนักงานสำหรับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายการเอกสารที่ลงทะเบียนพร้อมรหัสเอกสารในช่วงที่กำหนด

ตัวเลือก 12

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

ตัวเลือกที่ 13

1.แสดงรายการอุปกรณ์ตามประเภทที่กำหนด 2. แสดงรายการอุปกรณ์ที่พนักงานคนใดคนหนึ่งตัดออก

3. แสดงจำนวนอุปกรณ์ที่เลิกใช้งาน แบ่งกลุ่มตามประเภทอุปกรณ์

4. แสดงข้อมูลเกี่ยวกับพนักงานที่มีวันจ้างงานมากกว่าวันที่กำหนด

ตัวเลือก 14

1. พิมพ์รายการดอกไม้ตามประเภทใบที่ระบุ

2. แสดงรายการรหัสใบเสร็จซึ่งมีการขายดอกไม้ในจำนวนที่มากกว่ามูลค่าที่กำหนด

3. แสดงวันที่รับสินค้า จำนวน ชื่อผู้จำหน่าย และสีตามรหัสผู้จำหน่ายเฉพาะ

4. แสดงรายการดอกไม้และพันธุ์ดอกไม้ที่มีความสูงมากกว่าจำนวนที่กำหนดหรือกำลังบาน

ตัวเลือกที่ 15

1. แสดงรายชื่อลูกค้าที่เช็คอินห้องพักในช่วงเวลาที่กำหนด

2. แสดงยอดการชำระเงินรวมสำหรับห้องพักของลูกค้าแต่ละราย

3. แสดงวันที่เข้าพัก ประเภทห้องพัก ชื่อนามสกุลของลูกค้าที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายชื่อลูกค้าที่ลงทะเบียนในห้องบางประเภท

ตัวเลือกที่ 16

1.แสดงรายการอุปกรณ์ตามประเภทที่กำหนด

2. แสดงรายการอุปกรณ์ที่ลูกค้าเฉพาะรายเช่า

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

4. แสดงข้อมูลเกี่ยวกับลูกค้าเรียงตามที่อยู่

ตัวเลือกที่ 17

1. แสดงรายการของมีค่าที่มีราคาซื้อมากกว่ามูลค่าที่กำหนดหรือระยะเวลาการรับประกันมากกว่าจำนวนที่กำหนด

2. แสดงรายการที่ตั้งของสินทรัพย์วัสดุที่มีชื่อมีคำที่ระบุ

3. แสดงผลรวมของค่าด้วยรหัสในช่วงที่กำหนด

4. แสดงรายชื่อผู้รับผิดชอบทางการเงินพร้อมวันที่เข้าทำงานอยู่ในช่วงที่กำหนด

ตัวเลือกที่ 18

1. แสดงรายการการซ่อมแซมที่ดำเนินการโดยช่างเทคนิคเฉพาะ

2. แสดงรายการขั้นตอนการทำงานที่รวมอยู่ในผลงานที่มีชื่อมีคำที่ระบุ

3. แสดงผลรวมต้นทุนขั้นตอนงานซ่อมสำหรับงานโดยมีรหัสอยู่ในช่วงที่กำหนด

4. แสดงรายการหัวหน้าคนงานพร้อมวันจ้างงานในช่วงที่กำหนด

ตัวเลือกที่ 19

1.แสดงรายการยาพร้อมข้อบ่งชี้เฉพาะ

2. แสดงรายการหมายเลขใบเสร็จรับเงินที่มีการขายยาเกินจำนวนที่กำหนด

3. แสดงวันที่ขาย จำนวนเงิน ชื่อแคชเชียร์ และยา บนใบเสร็จพร้อมหมายเลขที่ระบุ

4. แสดงรายการยาและหน่วยวัดยาที่มีปริมาณในบรรจุภัณฑ์มากกว่าจำนวนที่กำหนดหรือรหัสยาน้อยกว่าค่าที่กำหนด

ตัวเลือกที่ 20

1. แสดงรายชื่อพนักงานตามตำแหน่งที่กำหนด

2. แสดงรายการเอกสารที่มีเนื้อหามีส่วนของคำที่ระบุ

3. แสดงวันที่จดทะเบียน ประเภทเอกสาร ชื่อเต็มของผู้ดำเนินการ และข้อเท็จจริงในการดำเนินการกับเอกสารที่ลงทะเบียนในช่วงเวลาที่กำหนด

4. แสดงรายการเอกสารที่ลงทะเบียนพร้อมประเภทเอกสารหรือรหัสเอกสารที่ระบุในช่วงที่กำหนด