2010-01-24 60 views

回答

25

您想用WHERE子句一個DELETE:這是標準的SQL。

你可以做的是批量刪除這樣的:

SELECT 'Starting' --sets @@ROWCOUNT 
WHILE @@ROWCOUNT <> 0 
    DELETE TOP (xxx) MyTable WHERE ... 

或者,如果你想刪除行的比例非常高......

SELECT col1, col2, ... INTO #Holdingtable 
      FROM MyTable WHERE ..opposite condition.. 
TRUNCATE TABLE MyTable 
INSERT MyTable (col1, col2, ...) 
      SELECT col1, col2, ... FROM #Holdingtable 
+0

感謝您的解決方案GBN。 – 2010-01-24 08:48:00

+1

如果是大量事務(取決於您的備份模型和日誌大小),請執行更多日誌備份以釋放日誌中的空間... – 2010-01-24 15:10:17

+0

將數據保存在臨時表中將使您支付更多內存使用量。 – 2011-10-18 13:08:06

4

你可以做幾件事情如果你想刪除你的表的一部分而不是TRUNCATE它。

,你可以選擇表的一部分到一個新表,然後換兩個,像這樣:

SELECT * 
INTO tmp_MyTable 
FROM MyTable 
WHERE Key='Value' 

IF @@ROWCOUNT > 0 
BEGIN 
    EXEC sp_rename MyTable, old_MyTable, NULL 
    EXEC sp_rename tmp_MyTable, MyTable, NULL 
    TRUNCATE old_MyTable 
END 

其次,如果你使用的分區,你可以創建一個相同(空)表在相同的分區方案中......並且如果根據歸檔/清除邏輯對錶進行分區,則可以將主表中的一個分區塊移至新表,然後截斷新表。例如:

ALTER TABLE MyTable 
SWITCH PARTITION 15 TO purge_MyTable PARTITION 2 
GO; 

TRUNCATE TABLE purge_MyTable 

Ps。 分區在SQL 2005/08 Ent中可用。

希望這會有所幫助!

+0

很好的答案。僅供參考,您可以使用ALTER TABLE..SWITCH而不進行分區,但您需要2個離散表。 – gbn 2012-01-22 11:19:20

0

Sychare Jedko,

TRUNCATE的優點是避免記錄在日誌文件中的每一個刪除。 TRUNCATE語句將爲整個批次創建單個條目(以日誌形式)。

0

剛剛遇到了一個類似的問題,該問題在臨時表上遇到了問題,並且存在適當的鎖定問題。由於相關表只是在我們的一個位置被引用,所以我們只需用動態表名稱的查詢替換該引用,該名稱使用類似於gbn建議的「select into」創建。

這是可維護的,因爲登臺表僅在代碼中的一個位置引用,並且額外的數據庫調用和表創建的開銷在倉儲上下文中是合理的。如果您只有幾百條記錄或多次引用代碼中的表格,則此方法可能無效。

0

當處理數百行的行時,我更喜歡使用WHERE語句並使用SELECT INTO副本表,刪除原始表並將副本重命名(返回原始名稱)。

雖然,你應該有像(FK)鍵,約束等東西在腦海中。但是使用這種方法可以避免日誌的大小,並且避免了大量的時間消耗。

/Snedker