2012-10-27 53 views
0

我希望刪除具有標題,子標題和訂單項詳細信息的訂單,然後再寫出相同的訂單,而不管替換子標題,訂單項詳細信息現在可能如何。當我嘗試使用更改寫回新版本時,出現pk違規錯誤。經過分析,我發現儘管我的DELETE語句似乎可行,但在發佈後(例如受影響的x行),目標表保持不變。所以,這將解釋pk vio問題。我錯過了什麼?tsql:刪除行爲

這裏的語句之一:

 -- detail level (drop products) 
     DELETE dprods FROM [SQLsever].[WIP].[order].DropProducts as dprods 
     INNER JOIN #dropprods t on t.OrderId = dprods.OrderId 
      AND t.OrderDropId = dprods.OrderDropId 
      AND t.DropProdId = dprods.DropProdId; 

發出聲明後,我仍然有在目標表中的所有200個多行,我在#dropprods臨時表200個+ IDS。爲什麼?

** 編輯,以更好地確定問題 ** * ** * ** * ** * * 的DELETE語句是不是問題。該問題與一組嵌套/命名事務有關。 DELETE語句在一個下面,INSERT語句在另一個下面。這是我的。這顯然是錯誤的。我想要做的是確保在我知道我將有一個很好的替代INSERT之前,我不提交DELETE。以下是我所做的: * EDITED T-SQL WITH SAVE TRANSACTION FIX * ** 此TSQL現在可以使用。

-- CHANGED 
    BEGIN TRANSACTION 
    SAVE TRANSACTION process_orders 
    BEGIN TRY 
    -- detail level 
    DELETE lprods FROM [SQLServer].[WIP].[order].LiftProducts as lprods 
    INNER JOIN #liftprods t on t.OrderId = lprods.OrderId 
     AND t.OrderLiftId = lprods.OrderLiftId 
     AND t.LiftProdId = lprods.LiftProdId; 
      -- the rest of the deletes 
      --NOTE: No commit transaction here; saving it to the end 
    END TRY 
    BEGIN CATCH 
     SELECT 
      ERROR_NUMBER() AS ErrorNumber, 
      ERROR_SEVERITY() AS ErrorSeverity, 
      ERROR_MESSAGE() AS ErrorMessage; 
     IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION process_orders; 
     END CATCH 

     BEGIN TRANSACTION 
     -- CHANGED 
     SAVE TRANSACTION process_orders 
     BEGIN TRY  
      -- CHANGED 
       COMMIT TRANSACTION process_orders;  
     END TRY 
     BEGIN CATCH 
      SELECT 
      ERROR_NUMBER() AS ErrorNumber, 
      ERROR_SEVERITY() AS ErrorSeverity, 
      ERROR_MESSAGE() AS ErrorMessage; 
      IF @@TRANCOUNT > 0 
       ROLLBACK TRANSACTION process_orders ; 
     END CATCH 
+0

不知道,你打算在世界混淆錦標賽上進入這個計劃嗎? DropOrder,OrderDrop dprods,t ...如果我們一起工作,我和你會失去一個大風格。除了忘記提交交易之外,如果您的舉報被刪除,他們並不是您認爲他們的人。您可能希望查看級聯刪除... –

+0

感謝您回覆Tony。 5分鐘前,我拿出了所有有名的交易和中提琴!刪除工作。謝天謝地。我不認爲我失去了主意。好吧,不管在這個舞臺上! :)我正在更新交易問題的問題描述。 – plditallo

+0

對我而言,這是一個很好的猜測,但這是一個猜測。 :) –

回答

1

首先,您必須在ROLLBACK TRANSACTION之後移除事務名稱。內部交易不允許回退 - 只有最外層的交易可以回滾。其次,SQL服務器忽略內部事務的提交(例如鎖定等待,直到最外層的事務被提交然後釋放)。所以你只需要一個沒有事務名的COMMIT TRANSACTION。

您的代碼應在運行,如果你需要沒有問題,可以放心的是:

    如果刪除succeedes你開始插入
  • ,否則你放棄更改和
  • 如果這些插入成功,你接受改變,否則丟棄所有

如果您需要格外放心​​在你提交之前(比如:另一個開發人員在一些SP寫道插入代碼,插入代碼是真正的大...等),你可以用你的#liftprods臨時表(這顯然包含刪除/ inse的鍵rt)並檢查鍵是否與你認爲應該插入的項目匹配。如果不是,請發出將回滾事務的RAISERROR('Some message',16,1)。

+0

感謝您的迴應 - 是的,它肯定會忽略內部交易的提交。我通過命名第一個事務process_orders來解決這個問題,然後在INSERTS中添加了一個SAVE TRANSACTION。現在就像一個魔法咒語! :) – plditallo

+0

那麼,它可以保存交易。然而,我提出的解決方案也應該是有效的,因爲它在知道插入正確發佈之前不會執行刪除操作,而這正是您想要的,對嗎? ;) – OzrenTkalcecKrznaric

+0

絕對。您的解決方案有效。 – plditallo