2013-05-28 119 views
0

我試圖實現的是以下內容。 當我刪除一條記錄時,我想檢查是否有任何FK關係,並且它需要遞歸。這樣我可以顯示與您想要刪除的記錄相關的所有記錄的列表。檢索所有外鍵及其記錄

所以嵌套鏈接的一個小例子 項目1 - >第1階段 - >塊1 - > ..

所以,當我嘗試刪除項目1我要得到你需要的物品清單刪除第一: 階段1 塊1 ....

我想與一個存儲過程,需要一個ID和一個表名(格式[CHEMA] [表名]),發現所有這些鏈接的記錄要做到這一點。

我遇到的問題是遞歸部分。 這裏是我到目前爲止的代碼:

ALTER PROCEDURE core.usp_CanBeDeleted  
    @entityId int, 
    @entityName nvarchar(250) 
AS 
BEGIN 
    DECLARE @NumberRecords int, @RowCount int 
    DECLARE @childId int 
    DECLARE @query nvarchar(max) 
    DECLARE @eName nvarchar(250) , @keyName nvarchar(250) 
    DECLARE @columnName nvarchar(250) 

    DECLARE @keys TABLE(
     RowID int IDENTITY(1, 1), 
     name nvarchar(250), 
     entityName nvarchar(250), 
     columnName nvarchar(250) 
    ) 

    if not exists (select * from sysobjects where name='partialResults' and xtype='U') 
    BEGIN 
     CREATE TABLE partialResults(
      RowID int IDENTITY(1, 1), 
      id int, 
      parentId int, 
      name nvarchar(250), 
      FK_name nvarchar(250) 
     ) 
    END 

    DECLARE @recusiveResults TABLE(
     RowID int, 
     id int, 
     parentId int, 
     name nvarchar(250), 
     FK_name nvarchar(250) 
    ) 

    DECLARE @results TABLE(
     RowID int, 
     id int, 
     parentId int, 
     name nvarchar(250), 
     FK_name nvarchar(250) 
    ) 

    SET @RowCount = 1 

     -- get all FK's of the entity 
    INSERT INTO @keys 
    SELECT name, '[' + OBJECT_SCHEMA_NAME(parent_object_id) + '].[' +  OBJECT_NAME(parent_object_id)+ ']',cu.column_name 
    from sys.foreign_keys k 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU 
    ON k.name = CU.CONSTRAINT_NAME 
    where k.referenced_object_id = OBJECT_ID(@entityName) 

    -- set variable to number of records in temp table 
    SET @NumberRecords = @@ROWCOUNT 

    -- loop through the FK's an get all linked entities 
    WHILE(@RowCount <= @NumberRecords) 
    BEGIN 

     SELECT @keyName = name, @eName = entityName, @columnName = columnName 
     FROM @keys 
     WHERE RowId = @RowCount 

     -- get all FK information 
     SET @query = 'INSERT INTO partialResults(FK_name, name, id, parentId)' 
     + ' SELECT ''' + @keyName + ''','''+ @eName + ''',' + 'id,' +   cast(@entityId as varchar(25)) + ' as parentid' 
     + ' FROM ' [email protected] 
     + ' WHERE id in ' 
     + ' (SELECT ' + @columnName 
      + ' FROM ' + @entityName 
      + ' WHERE id = ' + cast(@entityId as varchar(25)) 
      + ')' 

     --print @query            
     EXEC (@query) 

     SET @RowCount = @RowCount + 1 
    END 

    -- rest number of records 
    SET @RowCount = 1 
    SELECT @NumberRecords = count(id) 
    FROM partialResults 

    -- save partialResults 
    INSERT INTO @results--(FK_name, name, id, parentId) 
    SELECT *--FK_name, name, id, parentId 
    FROM partialResults 

    DELETE FROM partialResults 

    WHILE(@RowCount <= @NumberRecords) 
     BEGIN 
     -- select next row 
     SELECT @childId = id, @eName = name 
     FROM @results 
     WHERE RowId = @RowCount         

     INSERT INTO @recusiveResults   
     EXEC core.usp_CanBeDeleted @childId, @eName 

     SET @RowCount = @RowCount + 1 
    END 

    INSERT INTO @results 
    SELECT * 
    FROM @recusiveResults 

    if exists (select * from sysobjects where name='partialResults' and xtype='U') 
    BEGIN 
     -- remove temp tables 
     DROP TABLE partialResults 
    END 
    -- return results 
    SELECT * 
    FROM @results  
END 
GO 

問題就出在這裏:

INSERT INTO @recusiveResults   
EXEC core.usp_CanBeDeleted @childId, @eName 

Apparantly不能嵌套插入EXEC。然而,我真的沒有看到任何其他的方式來做到這一點。 我試過把它轉換成一個函數,但後來還有其他問題,如動態查詢。

任何幫助將大大apreciated。

回答

1

將程序拆分爲外部程序和內部程序。

在外層過程中創建#results temp-table,然後調用內層過程。

在內部程序中放入包括遞歸在內的所有邏輯,但不是在最後選擇結果,而是將結果插入已存在的#results表中。

這樣你就安全了很多時間,因爲你不必移動數據。你也不必再嵌套INSERT...EXEC了。

您也不需要dbo.PartialResults表,因爲您可以直接寫入動態語句中的#results表。如果你仍然需要它,爲了使遞歸工作取而代之的是你在內部過程中創建的#partialResults臨時表(不要檢查是否存在,只需創建一個新表。請參閱http://sqlity.net/en/1109/temp-tables-scoping-eclipsing/瞭解臨時表範圍的解釋) 。這樣,每次執行都創建自己的臨時表,並且不必處理清理。與使用真實表格相比,這也不那麼沉重。

最後,所有的表變量也可以。

在內部程序結束後,您可以執行一個簡單的SELECT * FROM #results;來輸出所有收集的結果。

+0

謝謝塞巴斯蒂安,我會試試看。 開始了很簡單,但我不斷增加的東西來嘗試和解決問題。 我想我會需要一個內部和外部程序,但有點失去了我的方式:-) –

+0

它的工作。我仍然需要額外的#partialResults臨時表來避免無限循環。 否則,我會將結果添加到結果中,循環播放結果並在每個循環中添加更多結果到結果......這不會是最好的想法。 無論如何,如果有人對最終代碼感興趣,我會在稍後發佈,因爲我現在沒有太多時間。 –

相關問題