|
|
Cơ sở dữ liệu - Store Procedure & Transaction trong SQL Server? Help!!!
Hỏi đáp, trao đổi về CSDL và ngôn ngữ SQL. Các câu hỏi về các hệ thống CSDL cụ thể (MSSQL Server, Oracle, MySQL...) xin hãy gởi vào các box con tương ứng. Các câu hỏi về hệ thống CSDL nào chưa có box riêng có thể gởi vào box này!| |
| Store Procedure & Transaction trong SQL Server? Help!!! |
|
Member
Member since
04:16 17-06-2003
Posts:
47
Fantasy Points:
811
|
Mình có một chút vấn đề về StoreProc và Transaction muốn hỏi mọi người. Giả sử mình có một Table như sau: Categories(CategoryID, CategoryName, ParentCategoryID), có một Relationship từ bảng Categories đến chính nó, CategoryID ---<- ParentCategoryID . Mỗi Category có thể có các Category con hoặc không có. Khi mình delete một Category đi thì mình muốn: nếu Category đó có các Category con thì trường ParentCategoryID của các Category con đó cho về null. Vậy mình viết một StoreProc sau, mọi người sửa giúp mình nhé . Mình viết bằng ngôn ngữ giả SQL mô tả công việc thôi, nhờ mọi người chuyển giúp thành ngôn ngữ SQL thật :
PROCEDURE DeleteCategory @CategoryID char(10) AS if exists( select * from Categories where CategoryID =@CategoryID ) begin begin Transaction // bắt đầu một giao dịch SubCategories = select * from Categories where ParentID = @CategoryID for each Category in SubCategories{ // cái này mình chỉ mô tả thôi, không biết viết chính xác như thế nào exec UpdateCategoryParent Category.CategoryID, null// lời gọi này có đúng ko? } delete from Categories where CategoryID =@CategoryID if error goto err end Transaction // kết thúc giao dịch err: roll back Transaction // nếu có lỗi thì đảo ngược giao dịch end RETURN
Còn đây là StoreProc UpdateCategoryParent :
PROCEDURE UpdateCategoryParent @CategoryID char(10), @ParentID char(10) AS if exists( select * from Categories where CategoryID=@CategoryID) begin if exists( select * from Categories where CategoryID=@ParentID) begin update Categories set ParentID = @ParentID where CategoryID=@CategoryID end end RETURN
Mình nói lại là mình chỉ viết bằng ngôn ngữ giả SQL để mô tả thôi chứ không phải SQL thật . Nhờ mọi người giúp chuyển thành SQL thật . Cám ơn nhiều !
Bảng Categories có quan hệ đến chính nó, Category A có Category con là B, B lại có Category con là C, ..D..E....cứ tiếp tục như thế . Như vậy ta không thể biết được chính xác độ sâu của chuỗi Category cha con. Tớ muốn truy vấn như thế này, đầu vào là một CategoryID, đầu ra là tất cả các Category nằm trong chuỗi Category cha con đó thì phải truy vấn như thế nào . Mọi người chỉ giúp với. Thanks a lot!
This post has been viewed
12,564
time(s).
5 direct repli(es)
and
7 indirect repli(es).
|
| Re: Store Procedure & Transaction trong SQL Server? Help!!! |
|
Guest
|
 Posted at
21:42 02-02-2004
Reply to
Store Procedure & Transaction trong SQL Server? Help!!!
( thangdv)
Với yêu cầu của bạn thì dùng Stored Procedure là "dao mổ trâu giết gà" rồi. Bạn chỉ cần dùng tính chất của Foreign key là đủ.
VD tạo 1 table có relationship với chính nó
CREATE TABLE category ( categoryID int not null default '0', parentID int not null default '0' REFERENCES category(categoryID) ON DELETE SET DEFAULT ON UPDATE CASCADE, PRIMARY KEY (categoryID) )
ON DELETE/UPDATE là event đựoc fired khi có thao tác DELTE/UPDATE xảy ra.
SET DEFAULT sẽ gán giá trị của field đó vể mặc định (là 0) CASCADE: update hoặc del luôn các row nằm trong ràng buộc của relationship SET NULL sẽ gán giá trị cảu field đó là NULL
This post has been viewed
10,863
time(s).
1 direct repli(es)
and
0 indirect repli(es).
|
Title
|
Poster
|
 |
 |
Re: Store Procedure & Transaction trong SQL Server? Help!!! |
| |
|
|
orlacien
|
|
| Re: Store Procedure & Transaction trong SQL Server? Help!!! |
|
Forum Moderator
Member since
01:41 06-11-2001
Posts:
610
Fantasy Points:
9,822
|
 Posted at
22:21 03-02-2004
Reply to
Store Procedure & Transaction trong SQL Server? Help!!!
( thangdv)
thangdv: Mình có một chút vấn đề về StoreProc và Transaction muốn hỏi mọi người......
PROCEDURE DeleteCategory @CategoryID char(10) AS ..........................
Chào bạn, Cách làm của bạn có vẻ phức tạp quá. Nếu như thế bạn sẽ phải dùng đến Cursor. Mình thử đưa một cách đơn giản hơn để bạn xem xem thế nào nhé. Cách xử lí của mình: Đầu tiên mình sẽ set hết parentID của các bản ghi về rống(hay gì đó) nếu như nó có giá trị là CategoryID cần xoá. Sau đó xoá bản ghi CategoryID Tất nhiên trong cả 2 cách mình vẫn cần đến transaction. Khi đó thủ tục xoá sẽ là: PROCEDURE DeleteCategory @CategoryID char(10) AS Begin Tran DeleteCate_Trans -- set parent to empty UPADATE Category SET ParentID='' WHERE ParentID=@CategoryID
--Check error If @@Error <>0 goto Error_Lbl
-- Delete Delete FROM Category WHERE CategoryID=@CategoryID
--Check error If @@Error <>0 goto Error_Lbl
-- Have no error, commit trans, exit sub Commit Tran DeleteCate_Trans Return
-- error processing Error_Lbl: Rollback Tran DeleteCate_TransMình thấy việc update|delete đâu cần thiết check exist làm gì, nếu muốn bắt lỗi, bạn có thể dùng @@ROWCOUNT sau mỗi câu lệnh để kiểm tra số bản ghi đưọc thực thi. Còn việc làm như bạn Guest bảo thì có lẽ không ổn, chí ít là đối với SQL server 2K vì mình không thấy có cú pháp đó trong SQL server 2K. Have fun. HHD.
............................ Tiền tài công danh bủa vây, mấy khi con nhớ đến mẹ, học đòi xa hoa giàu sang, biết đâu lòng mẹ...Và rồi con như nhận ra, thế gian sẽ chẳng là gì... ............................ tranquoc.tuan@yahoo.com
This post has been viewed
10,855
time(s).
1 direct repli(es)
and
1 indirect repli(es).
|
Title
|
Poster
|
 |
 |
Re: Store Procedure & Transaction trong SQL Server? Help!!! |
| |
|
|
Guest
|
|
| Re: Store Procedure & Transaction trong SQL Server? Help!!! |
|
Guest
|
 Posted at
22:50 03-02-2004
Reply to
Re: Store Procedure & Transaction trong SQL Server? Help!!!
( hhdtuan)
hau_hung_dao: Còn việc làm như bạn Guest bảo thì có lẽ không ổn, chí ít là đối với SQL server 2K vì mình không thấy có cú pháp đó trong SQL server 2K. MSSQL Server 7 thì tôi không biết (mà có lẽ là không có thật vì trên internet cũng có nhiều người hỏi câu này), nhưng MSSQL Server 2k thì đã hỗ trợ ON DELETE và ON UPDATE. Xem thêm: http://databasejournal....ssql/article.php/2219901và trên MSDN cú pháo lệnh CREATE TABLE: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_create2_8g9x.asp hoặc trong Book online của MSSQL Server (hiện cái book online tôi không có ở đây). Tuy nhiên, hiện tại MSSQL Server chỉ hỗ trợ CASCADE và NO ACTION chứ không có SET NULL hay SET DEFAULT, chắc là bạn guest kia nhớ nhầm sang Oracle hoặc MySQL.
This post has been viewed
10,747
time(s).
1 direct repli(es)
and
0 indirect repli(es).
|
Title
|
Poster
|
 |
 |
Re: Store Procedure & Transaction trong SQL Server? Help!!! |
| |
|
|
hhdtuan
|
|
| Re: Store Procedure & Transaction trong SQL Server? Help!!! |
|
Forum Moderator
Member since
01:41 06-11-2001
Posts:
610
Fantasy Points:
9,822
|
 Posted at
23:20 03-02-2004
Reply to
Re: Store Procedure & Transaction trong SQL Server? Help!!!
( Guest)
Guest: ............... Tuy nhiên, hiện tại MSSQL Server chỉ hỗ trợ CASCADE và NO ACTION chứ không có SET NULL hay SET DEFAULT, chắc là bạn guest kia nhớ nhầm sang Oracle hoặc MySQL.
Hi, Bác Guest này nói chính xác (cú pháp) của SQL Server, hihih, còn bác Guest kia nhớ nhầm sang MySQL rồi thì phải vì em thấy Oracle cũng chỉ có đến SET NULL chứ chưa có thêm SET DEFAULT như MySQL. Have fun! HHD.
............................ Tiền tài công danh bủa vây, mấy khi con nhớ đến mẹ, học đòi xa hoa giàu sang, biết đâu lòng mẹ...Và rồi con như nhận ra, thế gian sẽ chẳng là gì... ............................ tranquoc.tuan@yahoo.com
This post has been viewed
10,736
time(s).
0 direct repli(es)
and
0 indirect repli(es).
|
| Re: Store Procedure & Transaction trong SQL Server? Help!!! |
|
Forum Moderator
Member since
01:41 06-11-2001
Posts:
610
Fantasy Points:
9,822
|
 Posted at
01:50 04-02-2004
Reply to
Store Procedure & Transaction trong SQL Server? Help!!!
( thangdv)
thangdv: Giả sử mình có một Table như sau: Categories(CategoryID, CategoryName, ParentCategoryID), có một Relationship từ bảng Categories đến chính nó. ........ Category A có Category con là B, B lại có Category con là C, ..D..E....cứ tiếp tục như thế . Như vậy ta không thể biết được chính xác độ sâu của chuỗi Category cha con. Tớ muốn truy vấn như thế này, đầu vào là một CategoryID, đầu ra là tất cả các Category nằm trong chuỗi Category cha con đó thì phải truy vấn như thế nào . Mọi người chỉ giúp với. Thanks a lot!
Hi, Còn cái query này, ý của bạn là lấy tất cả con, cháu, chắt, chút, chít, ... của nó ra đúng không, thế thì chắc là phải dùng đệ quy rồi, ;-). Bạn có thể dùng trong code của chương trình (recordset), hoặc có thể dùng ngay T-SQL trong SQL Server. Chắc cách gọi đệ quy thế nào trong bài toán này thì bạn hẳn đã biết rồi đúng không! Theo ý kiến chủ quan của mình, để làm được trong T-SQL thì sẽ phải dùng đến cursor và chỉ làm được trên SQL Server 2K(8.0) vì mình dùng kiểu biến là Table, ;-), và ... mình phải viết dưới dạng hàm, ;-). Đây là hàm của mình để bạn tham khảo, có thể cấu trúc bảng sẽ khác với của bạn: CREATE FUNCTION getChild( @ParentID int ) RETURNS @OutTable Table(CategoryID int, [Name] varchar(50), ParentID int ) AS BEGIN -- Khai bao mot bien kieu Table voi cau truc nhu trong CSDL Declare @tmpTable Table(CategoryID int, [Name] varchar(50), ParentID int )
-- Lay gia tri do vao table INSERT Into @tmpTable SELECT CategoryID, [Name], ParentID FROM Category WHERE ParentID=@ParentID
-- neu chua het ban ghi, ;-) hay van còn con IF @@RowCount>0 Begin Declare @tmpID int -- Khai bao mot bien con tro de duyet, lap de quy Declare myCur CURSOR FOR SELECT CategoryID FROM Category WHERE ParentID=@ParentID -- Mo con tro Open myCur -- chuyen den ban ghi dau tien Fetch next from myCur Into @tmpID
While @@Fetch_Status=0 -- lap khi van con du lieu Begin -- goi de quy va lay gia tri chen vao bang ket qua INSERT Into @tmpTable SELECT CategoryID, [Name], ParentID From dbo.getChild(@tmpID) -- Move next -- chuyen den ban ghi ke tiep Fetch Next From myCur Into @tmpID End -- Dong va giai phong bien con tro Close myCur Deallocate myCur End -- Do giu lieu ra bang ket qua INSERT Into @OutTable SELECT CategoryID, [Name], ParentID From @tmpTable
Return
ENDSau dùng câu lệnh select đơn giản như sau: Select * From dbo.getchild(category_value) Order by CategoryIDTất nhiên, để đơn giản bạn có thể chỉ cần lấy ra CategoryID thôi, khi đó câu SQL truy vấn sẽ có thể như sau: Select * From CategoryTable WHERE CategoryID IN ( Select CategoryID From dbo.getchild(category_value)) Order by CategoryID Have fun! HHD.
............................ Tiền tài công danh bủa vây, mấy khi con nhớ đến mẹ, học đòi xa hoa giàu sang, biết đâu lòng mẹ...Và rồi con như nhận ra, thế gian sẽ chẳng là gì... ............................ tranquoc.tuan@yahoo.com
This post has been viewed
10,861
time(s).
1 direct repli(es)
and
1 indirect repli(es).
|
Title
|
Poster
|
 |
 |
Re: Store Procedure & Transaction trong SQL Server? Help!!! |
| |
|
|
thangdv
|
|
| Cho mình hỏi thêm về cursor! |
|
Member
Member since
04:16 17-06-2003
Posts:
47
Fantasy Points:
811
|
 Posted at
02:41 17-02-2004
Reply to
Re: Store Procedure & Transaction trong SQL Server? Help!!!
( hhdtuan)
Thanks bác H_H_D và mọi người, mode thế mới là mode chứ. Cho mình hỏi thêm một chút nhá, có được dùng nhiều hơn một con trỏ CURSOR trong cùng một storeProc hay function không vậy. Vì mình thấy điều kiện kiểm tra con trỏ là: fetch next from ... into @.... while @@FETCH_STATUS = 0 begin ............... fetch next from ... into @.... end tất cả các con trỏ trong cùng một giao dịch đều dùng biến global @@FETCH_STATUS để kiểm tra, như vậy nếu hai con trỏ lồng nhau thì có được không, ví dụ: declare thefirstCur CURSOR FOR select .............. fetch next from thefirstCur into @.... while @@FETCH_STATUS = 0 begin declare thesecondCur CURSOR FOR select .............. fetch next from thesecondCur into @.... while @@FETCH_STATUS = 0 begin ............... fetch next from thesecondCur into @.... end close thefirstCur deallocate thefirstCur ....................... fetch next from thefirstCur into @.... end close thefirstCur deallocate thefirstCur
Đại loại là lồng nhau như vậy có làm sao không ạ?
This post has been viewed
10,737
time(s).
1 direct repli(es)
and
0 indirect repli(es).
|
Title
|
Poster
|
 |
 |
Cho mình hỏi thêm về cursor! |
| |
|
|
hhdtuan
|
|
| Re: Cho mình hỏi thêm về cursor! |
|
Forum Moderator
Member since
01:41 06-11-2001
Posts:
610
Fantasy Points:
9,822
|
 Posted at
01:10 18-02-2004
Reply to
Cho mình hỏi thêm về cursor!
( thangdv)
thangdv: Cho mình hỏi thêm một chút nhá,..... Tất cả các con trỏ trong cùng một giao dịch đều dùng biến global @@FETCH_STATUS để kiểm tra, như vậy nếu hai con trỏ lồng nhau thì có được không, ví dụ: declare thefirstCur CURSOR FOR select .............. fetch next from thefirstCur into @.... while @@FETCH_STATUS = 0 begin declare thesecondCur CURSOR FOR select .............. fetch next from thesecondCur into @.... while @@FETCH_STATUS = 0 begin ............... fetch next from thesecondCur into @.... end close thefirstCur deallocate thefirstCur ....................... fetch next from thefirstCur into @.... end close thefirstCur deallocate thefirstCur
Đại loại là lồng nhau như vậy có làm sao không ạ?
Chào bạn, Đúng là cái biến @@FETCH_STATUS là được dùng chung cho tất cả các cursor trong một connection, nó được set lại khi bạn gọi lệnh FETCH và dĩ nhiên sẽ nhận giá trị của cursor vừa được fetch đó, vì thế bạn phải hết sức chú ý khi sử dụng nó. Nếu bạn dùng nó trong trường hợp lồng nhau như bạn kể ở trên thì mình có thể nói là không có vấn đề gì. Sở dĩ làm được đó là vì bạn duyệt hết cursor con rồi gọi lại Fetch tới cursor cha, khi đó @@FETCH_STATUS được set trở lại và nó sẽ mang giá trị của cursor cha. Mình có thể mô tả như thế này nhé: Fetch next from Cursor_Cha -- -> @@Fetch_status được reset, nó nhận giá trị của Cursor_Cha
While @@Fetch_status=0 -- tôi luôn mang giá trị của Cursor_Cha?, ;-) Begin ............................................... Fetch next from Cursor_Con -- -> @@Fetch_status được reset, nó nhận giá trị của Cursor_Con
While @@Fetch_status=0 -- tôi luôn mang giá trị của Cursor_Con?, ;-) Begin ........................... Fetch next from Cursor_Con -- -> @@Fetch_status được reset, nó nhận giá trị của Cursor_Con End
Fetch next from Cursor_Cha -- -> @@Fetch_status được reset, nó nhận giá trị của Cursor_Cha -- Nhận giá trị của Cursor_Cha hả?, hehehe vòng lặp sài tốt EndNhư vậy là vẫn được phải không, tuy nhiên nếu bạn mà dùng không cẩn thận thì sẽ bị lỗi, chủ yếu có thể là dùng song song các cursor. Ví dụ như đoạn code sau: .......... Open Cursor1 Open Cursor2 .................
Fetch Next From Cursor1 -- -> @@Fetch_status được reset If @@Fetch_status=0 --tôi mang giá trị của Cursor1 đó, quá rõ ràng;-) Begin -- Tôi đang ở bản ghi đầu tiên của bảng -- do Cursor1 trỏ tới. ừ! ..................... End
.............................. Fetch Next From Cursor2 -- -> @@Fetch_status được reset If @@Fetch_status=0 --bây giờ tôi thì mang giá trị của Cursor2 rồi. Dĩ nhiên! Begin -- Và tôi cũng đang ở bản ghi đầu tiên -- của bảng do Cursor2 trỏ tới. Ừ! ..................... End
Fetch Next From Cursor1 -- -> @@Fetch_status được reset If @@Fetch_status=0 --tôi mang giá trị của Cursor1 đó. Biết rồi! Begin -- Bây giờ tôi đang ở bản ghi thứ 2 của bảng do -- Cursor1 trỏ tới. Rồi! Nói nhiều quá, ;-) ..................... End
...................................Như vậy, khi dùng với con trỏ trong SQL Server, bạn cần chú ý là bạn đã gọi fetch trên con trỏ nào thì @@Fetch_status mang giá trị của con trỏ đó và nó luôn mang giá trị của contror được fetch sau cùng, ;-). Hi vọng có thể giúp được bạn đôi chút, HHD.
............................ Tiền tài công danh bủa vây, mấy khi con nhớ đến mẹ, học đòi xa hoa giàu sang, biết đâu lòng mẹ...Và rồi con như nhận ra, thế gian sẽ chẳng là gì... ............................ tranquoc.tuan@yahoo.com
This post has been viewed
10,714
time(s).
0 direct repli(es)
and
0 indirect repli(es).
|
|
Permissions:
Create Topic:
No
|
Reply Topic:
No
|
Attach File:
No
|
Make Poll:
No
|
|