1

我想创建调用递归函数的存储过程,每次它都会执行更新语句。

我有一张桌子叫document

documentId   folderId
----------   --------
1222         1
1256         2
1257         3

还有一张folder桌子:

folderId    parentFolder
--------    -----------
1             5
2             1
3             2 
5             null

我的存储过程将删除文件夹号(1),当它被删除时,它应该将文件夹1和1的子文件夹中的所有文档移动到1的父文件夹。

怎么做?

CREATE FUNCTION fn_deleteSubFolderDocument
(
@folderId INT ,
@newFolderId INT
)
RETURNS NVARCHAR(100) 
AS
BEGIN
DECLARE @count2 int 
SET @count2=(SELECT COUNT(*) FROM dbo.tbl_document_folder WHERE parent_folder=@folderId)
UPDATE tbl_document SET folder_id=@newFolderId WHERE folder_id=@folderId

IF(@count2 !=0)
BEGIN
DECLARE @table TABLE(id INT IDENTITY(1,1),folderId INT,parentFolder int  )
INSERT INTO @table(folderId,parentFolder)
SELECT folder_id,parent_folder FROM dbo.tbl_document_folder WHERE parent_folder=folder_id
DECLARE @index INT =0
WHILE @index<@count2
BEGIN
SET @index=@index+1
RETURN fn_deleteSubFolderDocument((SELECT folderId FROM @table WHERE id=@index),(SELECT parentFolder FROM @table WHERE id=@index ))
END

END 

END
GO
4

3 回答 3

1

我正在尝试在 SQLfiddle 中进行复制以尝试遍历您所说明的依赖关系树,因为我认为您的问题与此SO Answer类似

好的 - 这将为你走下你的树:

create table document
(
  [documentId] int,
  [folderId] int
)
insert into document
values
(1222, 1),
(1256, 2),
(1257, 3)


create table folder
(
  [folderId] int,
  [parentFolder] int null
)
insert into folder
values
(1, 5),
(2, 1),
(3, 2),
(5, null)

这是遍历树并找到子文件夹的子文件夹的子文件夹的递归 CTE...

DECLARE @folderToDelete int = 1

;WITH RESULT (folders,LEVEL)
  AS
  (
  --anchor
   SELECT
      folderId [folders]
      ,0 AS LEVEL
   FROM folder AS E 
   WHERE folderId = @folderToDelete

  UNION ALL
  SELECT 
      E.folderId [folders]
      ,LEVEL +1 --switched parent/child
  FROM 
      folder AS E
      INNER JOIN RESULT AS D  
         ON 
          E.parentFolder=D.folders 
  --WHERE LEVEL < 100
  )
SELECT *
FROM RESULT OPTION (MAXRECURSION 100)

在 SQLfiddle 上保存了一个现场示例

拥有这组文件夹后,应该很容易找到需要移动的所有相关文档

参考Pinal Dave 的这篇文章,我修改了循环检测最大值的方式。如果循环在过去 100 次迭代中进行,如果没有任何最大的捕获,服务器会出错,但根据这篇文章,看起来 MAXRECURSION 可以设置为高达 32767 ......希望你的文件结构不是那么复杂!

于 2012-06-24T15:19:56.223 回答
0

三个步骤:

  1. 选择后代的树,这里使用回车链接描述递归公用表表达式
  2. 更新所有文档,该文件夹包含在提供的列表中
  3. 删除旧文件夹。

当然,还有一些您没有回答的未解决问题,例如如何处理子文件夹 thesevles,但使用相同的递归 CTE 技术应该很容易解决

--create recursive cte
with childfolders(folderID, parentFolder)
as
{
    --stop when you reach the first level
    select * from folder where parentFolderID = @oldFolderId

    --get the other levels
    select folder.folderId, folder.parentFolderId
     from folder folder inner join childFolders children on children.folderId
     = folder.parentFolderId
}

--update
update document set folderId = @newFolderId
where folderId in (select folderId from childFolders)

--delete
delete from folder where folderId= @oldFolderId
于 2012-06-24T15:59:51.103 回答
0
  1. 你没有提到这种情况,如果没有父文件夹,即folder1的父ID为空怎么办?

  2. 由于这是在数据库中并且您只是删除文件夹,因此只需几个更新语句就足够了

    // Update the documents parent which were in folder1   
    Update document SET folderId=@newFolderID Where folderID = @oldFolderID 
    
    // Update the parent in Folder table where parentid =1 
    Update folder SET parentId=@newFolderID Where parentID = @oldFolderID 
    
    // Update the folder in Folder table where parentid =1 
    Update folder SET folderId=@newFolderID Where folderID = @oldFolderID 
    

除了这些不处理没有父文件夹的文件夹。

于 2012-06-24T13:54:17.123 回答