ไม่มากก็น้อย เราได้จัดทำเมนูสองหรือสามระดับ เช่น ไดเร็กทอรีแผนผังและการจำแนกประเภทผลิตภัณฑ์ หากเราพบการจำแนกประเภทที่มากขึ้น โดยทั่วไปเราจะใช้การเรียกซ้ำ การใช้การเรียกซ้ำในโปรแกรมจะช่วยเพิ่มโอเวอร์เฮดด้านประสิทธิภาพบางส่วนไม่มากก็น้อย
เมื่อก่อนผมเคยใช้ ASP.net ในการจัดหมวดหมู่แบบ non-recursive infinite-level ในโปรแกรม แต่เมื่อพิจารณาว่าความสะดวกในการพกพายังไม่ดีนัก ผมจึงเปลี่ยนเป็น Stored Procedure แล้วส่งออกให้ทุกคนได้ศึกษากัน ในระหว่างกระบวนการทดสอบ ไม่พบปัญหาใดๆ นอกจากนี้ โค้ดยังไม่ได้รับการปรับให้เหมาะสม
โดยปกติแล้ว การดำเนินการส่วนใหญ่ของเราคือการอ่านไดเร็กทอรี ดังนั้นในการใช้งานต่อไปนี้ เราจำเป็นต้องมีคำสั่ง Select เพียงคำสั่งเดียวในการอ่าน หากไม่มีการเรียกซ้ำ ระดับจะไม่มีที่สิ้นสุดตามทฤษฎี~!
================================================== ====================
โครงสร้างตาราง:
ชื่อตาราง: Tb_Column
โครงสร้างตาราง (ทุกช่องไม่ว่างเปล่า):
คีย์หลัก int ของ Column_ID (หมายเหตุ: ไม่ใช่ตัวระบุ)
ชื่อการจัดหมวดหมู่ Column_Name nvarchar(50)
Parent_ID int รหัสหมวดหมู่หลัก (ค่าเริ่มต้น 0)
เส้นทางการจัดหมวดหมู่ Column_Path nvarchar(1000)
Column_Depth ความลึกการจำแนกประเภท int (ค่าเริ่มต้น 0)
Column_Order int sort (ค่าเริ่มต้น 0)
คำอธิบายการจำแนกประเภท Column_Intro nvarchar(1000)
=========================================== === ==================
ขั้นตอนที่หนึ่งที่เก็บไว้: สร้างการจัดประเภทใหม่
สร้างกระบวนการ sp_Column_Insert
-
@Parent_ID อินท์
@Column_Name nvarchar (50)
@Column_Intro nvarchar (1,000)
-
เช่น
ประกาศ @Err As int
ตั้งค่า @Err=0
เริ่ม Tran
--รับรหัสคอลัมน์จากบันทึกที่มีอยู่
ประกาศ @Column_ID เป็น int
ประกาศ @Column_Depth As int
เลือก @Column_ID = Max(Column_ID) จาก Tb_Column
หาก @Column_ID ไม่เป็นค่าว่าง
ตั้งค่า @Column_ID = @Column_ID+1
อื่น
ตั้งค่า @Column_ID = 1
-- ตรวจสอบว่าเป็นคอลัมน์ระดับบนสุดหรือไม่ และตั้งค่า Column_Path และ Column_Order
ประกาศ @Column_Path เป็น nvarchar (1,000)
ประกาศ @Column_Order As int
ถ้า @Parent_ID = 0
เริ่ม
ตั้ง @Column_Path =Ltrim(Str(@Column_ID))
เลือก @Column_Order = Max(Column_Order) จาก Tb_Column
ถ้า @Column_Order ไม่เป็นค่าว่าง
ตั้ง @Column_Order = @Column_Order + 1
อื่น --หากไม่พบบันทึก แสดงว่านี่คือบันทึกแรก
ตั้งค่า @Column_Order = 1
--Depth
ตั้งค่า @Column_Depth = 1
จบ
อื่น
เริ่ม
--รับเส้นทางและความลึกของโหนดหลัก
เลือก @Column_Path = Column_Path ,@Column_Depth = Column_Depth จาก Tb_Column โดยที่
Column_ID=@Parent_ID
ถ้า @Column_Path เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 1
ไปที่จุดสิ้นสุด
สิ้นสุด
-- รับหมายเลขลำดับสูงสุดภายใต้โหนดหลักเดียวกัน
เลือก @Column_Order = Max(Column_Order) จาก Tb_PicColumn โดยที่ Column_Path เช่น
''+@Column_Path+'|%' หรือ Column_ID = @Parent_ID
IF @Column_Order Is Not Null --หากมีหมายเลขลำดับอยู่แล้ว ให้เพิ่ม 1 ให้กับหมายเลขลำดับทั้งหมดหลังหมายเลขลำดับ
เริ่ม
--อัปเดตหมายเลขลำดับของโหนดทั้งหมดหลังจากโหนดปัจจุบันที่จะแทรก
อัปเดตชุด Tb_Column Column_Order = Column_Order +1 โดยที่ Column_Order
>@Column_Order
--หมายเลขลำดับสูงสุดภายใต้โหนดพาเรนต์เดียวกันบวก 1 จะสร้างหมายเลขลำดับของตัวเอง
ตั้ง @Column_Order = @Column_Order + 1
จบ
อื่น
เริ่ม
ตั้งค่า @Err=1
ไปที่จุดสิ้นสุด
สิ้นสุด
- เส้นทางของโหนดหลักบวกหมายเลข ID ของตัวเองจะสร้างเส้นทางของตัวเอง
ตั้งค่า @Column_Path = @Column_Path + '|' + Ltrim(@Column_ID))
--Depth
ตั้งค่า @Column_Depth = @Column_Depth+1
แทรก
ส่วนท้ายลงใน Tb_Column(Column_ID,Column_Name,Parent_ID,Column_Path,
Column_Depth,Column_Order,Column_Intro) ค่า(@Column_ID,@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column _Order ,@Column_Intro )
ถ้า @@ข้อผิดพลาด<>0
เริ่ม
ตั้งค่า @Err=1
ไปที่จุดสิ้นสุด
สิ้นสุด
- อัปเดต ORDER ของเรคคอร์ดหลังเรคคอร์ดปัจจุบัน
--อัปเดตชุด Tb_Column Column_Order = Column_Order+1 โดยที่ Column_Order > @Column_Order
theEnd:
ถ้า @Err=0
เริ่ม
มุ่งมั่นทรานส์
กลับ @Column_ID
จบ
อื่น
เริ่ม
ย้อนกลับทราน
กลับ 0
จบ
ไป
================================================= ============================
ขั้นตอนที่เก็บไว้ที่สอง: ลบหมวดหมู่
สร้างขั้นตอน sp_Column_Delete
-
@Column_ID ภายใน
-
เช่น
ประกาศ @Err As int
ตั้งค่า @Err = 0
เริ่มทราน.
--ขั้นแรกให้ตรวจสอบว่ามีโหนดย่อยอยู่ใต้โหนดหรือไม่
เลือก Column_ID จาก Tb_Column โดยที่ Parent_ID = @Column_ID
ถ้า @@RowCount<>0
เริ่ม
ตั้งค่า @Err = 1
ไปที่จุดสิ้นสุด
สิ้นสุด
-- รับ Column_Order ของโหนด เพื่อจัดเรียงลำดับของระเบียนอื่นหลังจากการลบ
ประกาศ @Column_Order As int
เลือก @Column_Order = Column_Order จาก Tb_Column โดยที่ Column_ID = @Column_ID
ถ้า @Column_Order เป็น NUll
เริ่ม
ตั้ง @Err =2
ไปที่จุดสิ้นสุด
สิ้นสุด
--อัปเดต Column_Order ของระเบียนอื่นๆ
อัปเดตชุด Tb_Column Column_Order = Column_Order -1 โดยที่ Column_Order >@Column_Order
หาก @@ข้อผิดพลาด<>0
เริ่ม
ตั้ง @Err =3
ไปที่จุดสิ้นสุด
สิ้นสุด
--ลบการดำเนินการ
ลบออกจาก Tb_Column โดยที่ Column_ID=@Column_ID
หาก @@ข้อผิดพลาด<>0
เริ่ม
ตั้ง @Err =4
ไปที่จุดสิ้นสุด
สิ้นสุด
--อัปเดต Column_ID ของระเบียนอื่น
--อัปเดตชุด Tb_Column Column_ID= Column_ID - 1 โดยที่ Column_ID >@Column_ID
--IF @@ข้อผิดพลาด<>0
-- เริ่ม
-- ตั้งค่า @Err =5
-- ไปที่จุดสิ้นสุด
-- จบ
ตอนจบ:
ถ้า @Err = 0
เริ่ม
มุ่งมั่นทรานส์
กลับ 0 --ลบสำเร็จ
จบ
อื่น
เริ่ม
ถ้า @Err=1
เริ่ม
ย้อนกลับทราน
ส่งคืน 1 --มีโหนดลูก
จบ
อื่น
เริ่ม
ย้อนกลับทราน
ส่งคืน 2--ข้อผิดพลาดที่ไม่ทราบสาเหตุ
จบ
จบ
ไป
================================================== ================
ขั้นตอนที่เก็บไว้ที่สาม: แก้ไขการจำแนกประเภท
สร้างขั้นตอน sp_Column_Update
-
@Column_ID อินท์
@Parent_ID อินท์
@Column_Name nvarchar (50)
@Column_Intro nvarchar (1,000)
-
เช่น
ประกาศ @Err As int
ตั้งค่า @Err=0
Begin Tran
--รับค่าก่อนการแก้ไข: Parent_ID, Column_Depth, Column_Order
ประกาศ @oParent_ID เป็น int
ประกาศ @oColumn_Depth เป็น int
ประกาศ @oColumn_Order เป็น int
ประกาศ @oColumn_Path เป็น nvarchar(1000)
เลือก @oParent_ID = Parent_ID, @oColumn_Depth = Column_Depth,@oColumn_Order = Column_Order, @oColumn_Path = Column_Path จาก Tb_Column โดยที่ Column_ID = @Column_ID
ถ้า @oParent_ID เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 1
ไปที่จุดสิ้นสุด
สิ้นสุด
--หากรหัสพาเรนต์ไม่เปลี่ยนแปลง ให้แก้ไขชื่อคอลัมน์และการแนะนำคอลัมน์โดยตรง
ถ้า @oParent_ID = @Parent_ID
เริ่ม
อัปเดตชุด Tb_Column Column_Name = @Column_Name,Column_Intro = @Column_Intro โดยที่ Column_ID = @Column_ID
หาก @@ข้อผิดพลาด <> 0
ตั้งค่า @Err = 2
ไปที่จุดสิ้นสุด
จบ
ประกาศ @nColumn_Path เป็น nvarchar (1,000)
ประกาศ @nColumn_Depth เป็น int
ประกาศ @nColumn_Order As int
-- รับจำนวนโหนดที่มีอยู่ในโหนดปัจจุบันเป็นโหนดหลัก [รวมถึงตัวมันเอง] หมายเหตุ: หากส่งคืน "1" หมายความว่าเป็นโหนดเดียว
ประกาศ @theCount เป็น int
เลือก @theCount = Count(Column_ID) จาก Tb_Column โดยที่ Column_ID=@Column_ID หรือ Column_Path เช่น ''+@oColumn_Path+'|%'
ถ้า @theCount เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 3
ไปที่จุดสิ้นสุด
สิ้นสุด
IF @Parent_ID=0 --หากถูกตั้งค่าเป็นโหนดระดับบนสุด ให้ตั้งค่าโหนดเป็นโหนดระดับบนสุดสุดท้าย
เริ่ม
--พิมพ์ 'ตั้งเป็นคอลัมน์ระดับบนสุด'
ตั้ง @nColumn_Path = Ltrim(Str(@Column_ID))
ตั้งค่า @nColumn_Depth =1
เลือก @nColumn_Order = Max(Column_Order) จาก Tb_Column
ถ้า @nColumn_Order เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 4
ไปที่จุดสิ้นสุด
End
Set @nColumn_Order = @nColumn_Order - @theCount + 1
--อัปเดตสามส่วน 1 โหนดเอง 2 โหนดย่อยทั้งหมด 2 ลำดับของบันทึกที่ตามมาก่อนที่แผนผังนี้จะเปลี่ยนแปลง
--พิมพ์ 'อัปเดตคอลัมน์ทั้งหมดหลังจากตำแหน่งก่อนหน้าของคอลัมน์นี้ [ไม่รวมคอลัมน์ย่อยภายใต้คอลัมน์นี้]: Column_Order'
อัปเดตชุด Tb_Column Column_Order = Column_Order-@theCount โดยที่ (Column_Order >@oColumn_Order) และ (Column_Path ไม่เหมือน ''+@oColumn_Path+'|%' )
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 7
ไปที่จุดสิ้นสุด
สิ้นสุด
--พิมพ์ 'อัปเดตคอลัมน์นี้: Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
พิมพ์ 'Order : '+Ltrim(Str(@nColumn_Order))
อัปเดตชุด Tb_Column Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro โดยที่ Column_ID = @Column_ID
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 5
ไปที่จุดสิ้นสุด
สิ้นสุด
--พิมพ์ 'อัปเดตคอลัมน์ย่อยทั้งหมดภายใต้คอลัมน์นี้: Column_Path, Column_Depth, Column_Order'
อัปเดต Tb_Column Set Column_Path = แทนที่ (Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+( @nColumn_Order-@oColumn_Order) โดยที่ Column_Path เช่น ''+@oColumn_Path+' |%'
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 6
ไปที่จุดสิ้นสุด
จบ
จบ
อื่น
เริ่ม
--รับข้อมูลที่เกี่ยวข้องของโหนดหลักในอนาคตและตั้งค่าที่เกี่ยวข้องของโหนดนี้
เลือก @nColumn_Depth = Column_Depth,@nColumn_Path = Column_Path จาก Tb_Column โดยที่ Column_ID = @Parent_ID
หาก @nColumn_Depth เป็นโมฆะ หรือ @nColumn_Path เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 8
ไปที่จุดสิ้นสุด
จบ
ตั้ง @nColumn_Depth = @nColumn_Depth +1
เลือก @nColumn_Order =Max(Column_Order) จาก Tb_Column โดยที่ Column_ID = @Parent_ID หรือ Column_Path เช่น ''+@nColumn_Path+'|%'
ถ้า @nColumn_Order เป็นโมฆะ
เริ่ม
ตั้งค่า @Err = 9
ไปที่จุดสิ้นสุด
End
Set @nColumn_Path = @nColumn_Path +'|'+ Ltrim(Str(@Column_ID))
IF @nColumn_Order = @oColumn_Order+1 --หากโหนดพาเรนต์ใหม่เป็นพี่น้องที่ใกล้ที่สุดเหนือตำแหน่งเดิม ลำดับของโหนดทั้งหมดจะ แตกต่าง
เริ่ม
อัปเดตชุด Tb_Column Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth, Column_Name = @Column_Name,Column_Intro = @Column_Intro โดยที่ Column_ID = @Column_ID
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 10
ไปที่จุดสิ้นสุด
จบ
End
Set @nColumn_Order = @nColumn_Order + 1
--อัปเดตสามส่วน 1 ลำดับของบันทึกต่อไปนี้ (หรือก่อนหน้า) ก่อนที่ทรีนี้จะเปลี่ยนแปลง 1 ตัวโหนดเอง 3 โหนดลูกทั้งหมด
--แบ่งออกเป็นการเคลื่อนไหวขึ้นหรือลง
--พิมพ์ 'อัปเดตคอลัมน์ทั้งหมดหลังตำแหน่งก่อนหน้าของคอลัมน์นี้ [หรือตำแหน่งหลังคอลัมน์นี้] [ยกเว้นคอลัมน์ย่อยภายใต้คอลัมน์นี้]: Column_Order'
ถ้า @nColumn_Order < @oColumn_Order
เริ่ม
อัปเดต Tb_Column Set Column_Order = Column_Order+@theCount โดยที่ Column_Order<@oColumn_Order And Column_Order >=@nColumn_Order And (Column_Path ไม่เหมือน ''+@oColumn_Path+'|%' ) และ Column_ID<>@Column_ID
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 12
ไปที่จุดสิ้นสุด
จบ
จบ
อื่น
เริ่ม
อัปเดตชุด Tb_Column Column_Order = Column_Order-@theCount โดยที่ Column_Order >@oColumn_Order และ Column_Order<@nColumn_Order และ (Column_Path ไม่เหมือน ''+@oColumn_Path+'|%' ) และ Column_ID<>@Column_ID
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 13
ไปที่จุดสิ้นสุด
จบ
สิ้นสุด
--พิมพ์ 'อัปเดตคอลัมน์นี้: Parent_ID, Column_Path, Column_Depth, Column_Order, Column_Name, Column_Intro'
พิมพ์ 'Order : '+Ltrim(Str(@nColumn_Order))
ถ้า @nColumn_Order > @oColumn_Order
ตั้งค่า @nColumn_Order = @nColumn_Order - @theCount
อัปเดตชุด Tb_Column Parent_ID=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro โดยที่ Column_ID = @Column_ID
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 10
ไปที่จุดสิ้นสุด
End
--Print 'อัปเดตคอลัมน์ย่อยทั้งหมดภายใต้คอลัมน์นี้: Column_Paht, Column_Depth, Column_Order'
อัปเดต Tb_Column Set Column_Path = แทนที่ (Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth-@oColumn_Depth),Column_Order = Column_Order+(@nColumn_Order-@oColumn_Order) โดยที่ Column_Path เช่น ''+@oColumn_Path+' |%'
หาก @@ข้อผิดพลาด <> 0
เริ่ม
ตั้งค่า @Err = 11
ไปที่จุดสิ้นสุด
จบ
สิ้นสุด
การสิ้นสุด:
IF @Err<>0 --หากมีข้อผิดพลาด ให้ส่งคืนหมายเลขข้อผิดพลาด
เริ่ม
ย้อนกลับทราน
กลับ@ผิดพลาด
จบ
อื่น -- คืนค่า 0 หากไม่มีข้อผิดพลาด
เริ่ม
มุ่งมั่นทรานส์
กลับ 0
จบ
ไป
================================================== =========================
ขั้นตอนที่เก็บไว้ที่สี่: การจำแนกประเภทการแสดงผล (เพียงคำสั่งเลือก)
รายการหมวดหมู่:
สร้างขั้นตอน sp_Column_List
เช่น
เลือก Column_ID, Column_Name, Parent_ID, Column_Path, Column_Depth,
คอลัมน์_ลำดับ, คอลัมน์_บทนำ
จาก Tb_Column
เรียงตามคอลัมน์_เรียงลำดับ
ไป
=======================================
นี่คือตัวอย่างการใช้งานภายใต้ ASP.NET ที่โพสต์ในฟอรัมของเพื่อน:
http://www.mzline.com/bbs/dispbbs.asp?boardID=67&ID=5044&replyID=25788&star=1&skin=0#25788