出於興趣,近期做了一個圖片分享的小項目,其中在做有關圖片的評論以及回復的功能時,剛開始對於這中功能有一些糾結,糾結的是評論與回復的內容是放在兩個表還是一個表中,對於放在兩張表的結構考慮到後期的數據讀取的復雜問題,最後決定將評論和回復的功能都放在同一張表中。數據庫采用SqlServer,具體表設計如下:
CREATE TABLE [dbo].[DemoComment]( [RowGuid] [nvarchar](50) NOT NULL, [ParentGuid] [nvarchar](50) NULL, [CommentText] [nvarchar](200) NULL, [CommentUserGuid] [nvarchar](50) NULL, [CommentUserName] [nvarchar](50) NULL, [CommentDate] [datetime] NULL, [ToUserGuid] [nvarchar](50) NULL, [ToUserName] [nvarchar](50) NULL, [CommentPictureGuid] [nvarchar](50) NULL )
然後對每一張圖片的評論就會有兩種情況:1、評論。2、評論和回復。現假設有"person_A"和"person_B"兩人對圖片"pic"評論,則有
1、評論情況就是簡單的插入一條評論記錄:
insert into DemoComment(RowGuid,CommentText,CommentUserGuid,CommentUserName,CommentDate,CommentPictureGuid) values(NEWID(),'wow,nice pic!','person_A_Guid','person_A',getdate(),'pic'); insert into DemoComment(RowGuid,CommentText,CommentUserGuid,CommentUserName,CommentDate,CommentPictureGuid) values(NEWID(),'wow,what a nice pic!','person_B_Guid','person_B',getdate(),'pic');
則用戶浏覽圖片詳細時,可以看到圖片“pic”下有如下兩條評論:
此時,有“person_C”是“person_B”的好友,“person_C”在“person_B”的評論下進行了回復,則有
2、“person_C”對“person_B”評論的回復
insert into DemoComment(RowGuid,ParentGuid,CommentText,CommentUserGuid,CommentUserName,CommentDate,ToUserGuid,ToUserName,CommentPictureGuid) values(NEWID(),'E07E9026-0194-4695-9FE4-FDD4DF9D3865','yes,I want to get one!','person_C_Guid','person_C',getdate(),'person_B_Guid','person_B','pic');
然後“person_B”也對“person_C”進行了回復
insert into DemoComment(RowGuid,ParentGuid,CommentText,CommentUserGuid,CommentUserName,CommentDate,ToUserGuid,ToUserName,CommentPictureGuid) values(NEWID(),'B688AB26-22D8-42BF-A518-10E3EFDC041F','OK,I will buy one for you!','person_B_Guid','person_B',getdate(),'person_C_Guid','person_C','pic');
然後“person_C”也對“person_B”表達了謝意。
insert into DemoComment(RowGuid,ParentGuid,CommentText,CommentUserGuid,CommentUserName,CommentDate,ToUserGuid,ToUserName,CommentPictureGuid) values(NEWID(),'81E882B3-9232-40C7-8BBD-F1E821063B64','really,Thank you very muck!','person_C_Guid','person_C',getdate(),'person_B_Guid','person_B','pic');
至此,所有的評論與回復已全部完成。
現在要做的就是取出對“pic”的所有評論和回復。
注意,此時可不是簡單地按照時間進行排序,假設“person_A”開始做了5條評論,過了一段時間"person_B"對“person_A”的第一條評論進行了回復,如果按時間排序肯定出錯。這是就可以看到“RowGuid”和“ParentGuid”的關系了:
沒錯,RowGuid和ParentGuid具有關聯關系,我們要做的就是找到第一條評論的RowGuid,然後與之關聯的評論與回復就可以全部取出了。這裡有一點遞歸的意思。
定義一個存儲過程,取出某一條評論下的所有回復:
procedure [dbo].[sp_GetCommnetsByRowGuid] (@RowGuid nvarchar(50)) as begin declare @comment table --定義表變量 ( RowGuid nvarchar(50) not null default NEWID(), ParentGuid nvarchar(50) null, CommentText nvarchar(200) null, CommentUserGuid nvarchar(50) null, CommentUserName nvarchar(50) null, CommentDate datetime null, ToUserGuid nvarchar(50) null, ToUserName nvarchar(50) null, PictureGuid nvarchar(50) null ) declare @parentGuid nvarchar(50);--第一父表標識變量 insert into @comment select d.* from DemoComment d where d.RowGuid=@RowGuid--添加記錄到表變量 --select @parentGuid=c.RowGuid from @comment c; set @parentGuid=@RowGuid;--初始化父表標識的值 declare @count int; set @count=1;--初始化循環條件,默認為1,標識可以循環 while @count >0 begin insert into @comment select * from DemoComment where parentguid=@parentGuid;--增加一條記錄到表變量 select @parentGuid=c.RowGuid from DemoComment c where c.parentguid=@parentGuid;--修改父表標識的值 select @count=COUNT(RowGuid) from DemoComment c where c.parentguid=@parentGuid;--為循環條件賦值 end select c.* from @comment c; end GO
執行該存儲過程有結果如下:
好了,現在可以再寫一個存儲過程調用“[dbo].[sp_GetCommnetsByRowGuid] ”一次取出所有評論:
create procedure sp_GetCommentsAndReplys as begin declare @RowNumberMin int; declare @RowNumberMax int; select @RowNumberMin=MIN(t.RowNumber),@RowNumberMax=MAX(t.RowNumber) from (select ROW_NUMBER()over(order by d.commentdate) RowNumber,d.* from DemoComment d where ParentGuid is null or ParentGuid ='')t print @RowNumberMin; print @RowNumberMax; declare @comment table --定義表變量 ( RowGuid nvarchar(50) not null default NEWID(), ParentGuid nvarchar(50) null, CommentText nvarchar(200) null, CommentUserGuid nvarchar(50) null, CommentUserName nvarchar(50) null, CommentDate datetime null, ToUserGuid nvarchar(50) null, ToUserName nvarchar(50) null, PictureGuid nvarchar(50) null ) while @RowNumberMin <=@RowNumberMax begin declare @CommentGuid nvarchar(50); --insert into @comment select @CommentGuid= t.RowGuid from (select ROW_NUMBER()over(order by d.ParentGuid) RowNumber,d.* from DemoComment d where ParentGuid is null or ParentGuid ='')t where t.RowNumber=@RowNumberMin; insert into @comment exec [dbo].[sp_GetCommnetsByRowGuid] @CommentGuid set @RowNumberMin=@RowNumberMin+1; end select * from @comment; end go exec sp_GetCommentsAndReplys
結果:
好了,功能已完成,之後可以考慮優化的事了。