1

updateステートメントを実行するたびに再帰関数を呼び出すストアドプロシージャを作成したいと思います。

私はというテーブルを持っています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

あなたの問題はこのSOAnswerに似ていると思うので、私はSQLfiddleで複製して、あなたが示した依存関係のツリーをたどろうとしています。

わかりました-これはあなたのためにあなたの木を歩きます:

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. ケースについては言及していませんが、親フォルダーがない場合、つまりfolder1の親IDがnullの場合はどうなりますか?

  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 に答える
0

3つのステップ:

  1. ここにリンクの説明を入力して再帰共通テーブル式を使用して、子孫のツリーを選択します
  2. 提供リストに含まれているすべてのドキュメントを更新します
  3. 古いフォルダを削除します。

もちろん、サブフォルダーをどうするかなど、答えられなかった未解決の問題もありますが、同じ再帰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 に答える