簡體   English   中英

如何在SQL Server中刪除或截斷表?

[英]How to delete or truncate table in SQL Server?

我需要清除許多表(最好是截斷表)。 但是表有許多FK約束。 我試過這樣的事,但失敗了: -

ALTER TABLE Table1 NOCHECK CONSTRAINT ALL 
TRUNCATE TABLE Table1
ALTER TABLE Table1 WITH CHECK CHECK CONSTRAINT ALL

這是我得到的錯誤: -

無法截斷表'Test',因為它正被FOREIGN KEY約束引用。

請通過臨時刪除約束建議我如何刪除或截斷表。

只需按正確的FK順序刪除它們:

DELETE GreatGrandChild
DELETE Child
DELETE Parent

並且不用擔心放棄約束。

示例代碼:

create table ParentTable (ParentID int primary key not null, RowValue varchar(10))
INSERT INTO ParentTable VALUES (1,'AAA')
INSERT INTO ParentTable VALUES (2,'BBB')

create table ChildTable (ChildID int primary key not null, ParentID int, RowValue varchar(10))

ALTER TABLE ChildTable ADD CONSTRAINT FK_ChildTable_ParentTable FOREIGN KEY
 (ParentID) REFERENCES dbo.ParentTable (ParentID) ON UPDATE  NO ACTION  ON DELETE  NO ACTION 

INSERT INTO ChildTable VALUES (10,1,'a')
INSERT INTO ChildTable VALUES (11,1,'aa')
INSERT INTO ChildTable VALUES (12,2,'b')
INSERT INTO ChildTable VALUES (13,1,'aaa')

DELETE ChildTable
DELETE ParentTable

要查找依賴於表的表,請運行此查詢:

select 
    object_name(parent_object_id) AS ReferencesYourTable
        ,object_name(referenced_object_id) AS YourTable
        ,* 
    from sys.foreign_keys 
    WHERE object_name(referenced_object_id)='YourTable'

對於上述查詢,刪除在刪除YourTable之前列出的每個表中的所有行。

與其他人發布的內容相反,您永遠不能截斷外鍵引用的表。 它在TRUNCATE TABLE下的聯機叢書中有記錄,但是自己嘗試一下要快得多:

create table Parent (col1 int primary key)

create table Child (
    col1 int primary key, 
    col2 int, 
    constraint fk foreign key (col2) references Parent (col1)
)


-- works
truncate table Child
-- doesn't work
truncate table Parent

alter table child nocheck constraint all

-- still doesn't work, even though the FK is disabled
truncate table Parent

drop table Child
drop table Parent

它不起作用的(概念)原因是TRUNCATE是物理操作,而不是邏輯操作。 所以它不是'外鍵識別',如果你讓它忽略外鍵,它會殺死參照完整性。

通常的解決方案(如其他人所述)是:

解決方案1

  1. 刪除外鍵
  2. 截斷表格
  3. 重新創建外鍵

解決方案2

  1. 刪除表
  2. 重新創建表

無論哪種解決方案都有效,它確實是一個部署問題,因為它更容易,更適合您的情況。 我知道你說這是一次性任務,但我仍然會編寫腳本,即使只是作為一種學習經歷。 解決方案1在純TSQL中很容易; 解決方案2使用外部語言更容易。

使用delete語句刪除該表中的所有行后,使用以下命令

從表名中刪除*

DBCC CHECKIDENT(tablename,RESEED,0)

最簡單的方法是刪除約束,然后在截斷后重新應用它們。

您還需要在所有引用截斷表的表中刪除約束。 之后,您將能夠截斷表格。 但不要忘記再次創建它們。

即使引用截斷表的所有表都沒有行,MSSQL也不允許截斷表。

所以你需要首先刪除FK約束。

您需要做什么(並且可能有一個工具,但我不知道一個)是不可用的所有關系附加到受影響的表(來自和被截斷的表)。 這通常意味着禁用其他表的約束。

<SoapBox>我確定你已經意識到了這一點,但如果我沒有指出這些約束可能存在的原因非常充分,那么我就會失職,你需要非常非常確定你的數據在截斷之前和之后都是干凈的。 <\\SoapBox>

最簡單(也許不是最快)的方法是DELETE FROM Table1

即使是外鍵也能正常工作(但是,刪除順序應該考慮在具有匹配主鍵的表之前刪除具有外鍵的表。

試試這個:

EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

您需要使用Table1的外鍵刪除或截斷任何表,或者如果您的數據庫支持它,則執行級聯刪除(我認為它是在SQL Server 2005中添加的)

Sql Server級聯刪除

如果需要對數據庫結構進行重大更改,則有三種選擇。 首先,您可以處理所有約束,刪除然后在圍繞您將采取的核心操作的腳本中重新創建它們。 這是相當耗時且容易出錯的。 第二個選項是使用Enterprise Studio中的“設計”功能找到執行操作的方法。 但是,在保存操作之前,只需右鍵單擊設計窗口並要求保存為腳本。 如果您希望在腳本中進行微調,這將為您提供一個起點。

您的最終選項 - 以及我更喜歡的選項 - 是使用第三方DDL生成器來更改數據庫結構。 我強烈推薦Red Gate的SQL比較。 它也會生成一個腳本,但它可以很容易地比較兩個數據庫,以發現如何將一個數據庫轉換為另一個數據庫。 祝好運!

我在ETL系統中做了一些事情,通過“記錄”用戶表中的每個外鍵以及CREATE和DROP腳本(當然,所有這些都基於ALTER TABLE)。 根據您的情況,您將按指定的順序循環訪問它,並為每個表提取並執行所有“drop key”腳本,截斷表,然后應用“create key”腳本。

對一次性運行沒有幫助。 它需要開發和認真調試(因為它必須工作)。 每次修改架構時,都可能需要更新此表的內容。 但是,如果您將此過程作為常規程序的一部分,那么值得付出努力。

選項2:通過所有目標表的SSMS生成“創建”腳本。 刪除所有表(以及所有數據)。 運行腳本以重新創建空表。

也試試這個。

暫時取消選中約束,然后重新檢查。

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'    
EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'    
EXEC sp_MSForEachTable 'DELETE FROM ?'   
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'    
EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM