出於興趣,近期做了一個圖片分享的小項目,其中在做有關圖片的評論以及回復的功能時,剛開始對於這中功能有一些糾結,糾結的是評論與回復的內容是放在兩個表還是一個表中,對於放在兩張表的結構考慮到後期的數據讀取的復雜問題,最後決定將評論和回復的功能都放在同一張表中。數據庫采用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
結果:

好了,功能已完成,之後可以考慮優化的事了。