답변:
외래 키 관계가있는 테이블에서 데이터를 삭제하는 경우 (기본적으로 올바르게 디자인 된 데이터베이스의 경우) 모든 제약 조건을 비활성화하고 모든 데이터를 삭제 한 다음 제약 조건을 다시 활성화 할 수 있습니다
-- disable all constraints
EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"
-- delete data in all tables
EXEC sp_MSForEachTable "DELETE FROM ?"
-- enable all constraints
exec sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
제약 조건 및 트리거 비활성화에 대한 추가 정보 여기를 참조하십시오.
일부 테이블에 ID 열이있는 경우 다시 열어야 할 수도 있습니다.
EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
RESEED의 동작은 새 테이블과 이전에 BOL 에서 일부 데이터를 삽입 한 테이블간에 다릅니다 .
DBCC CHECKIDENT ( 'table_name', RESEED, newReseedValue)
현재 ID 값은 newReseedValue로 설정됩니다. 작성된 이후 테이블에 행이 삽입되지 않은 경우 DBCC CHECKIDENT를 실행 한 후 삽입 된 첫 번째 행은 newReseedValue를 ID로 사용합니다. 그렇지 않으면 삽입 된 다음 행은 newReseedValue + 1을 사용합니다. newReseedValue의 값이 ID 열의 최대 값보다 작은 경우, 테이블에 대한 후속 참조에서 오류 메시지 2627이 생성됩니다.
제약 조건을 비활성화하면 자르기를 사용할 수 없다는 사실을 지적한 Robert 에게 감사의 말을 전하고 제약 조건을 삭제 한 다음 다시 만들어야합니다.
SET ROWCOUNT 0
기본적으로 작업을 500 행으로 제한하는 것이기 때문에 스크립트 시작 부분에 추가하고 싶을 것입니다 ! 모든 데이터가 실제로 삭제되지는 않았기 때문에 좌절 한 오류가 발생합니다.
다음은 데이터베이스 삭제 스크립트의 왕자입니다. 모든 테이블을 지우고 올바르게 다시 시드합니다.
SET QUOTED_IDENTIFIER ON;
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? DISABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? ENABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON';
IF NOT EXISTS (
SELECT
*
FROM
SYS.IDENTITY_COLUMNS
JOIN SYS.TABLES ON SYS.IDENTITY_COLUMNS.Object_ID = SYS.TABLES.Object_ID
WHERE
SYS.TABLES.Object_ID = OBJECT_ID('?') AND SYS.IDENTITY_COLUMNS.Last_Value IS NULL
)
AND OBJECTPROPERTY( OBJECT_ID('?'), 'TableHasIdentity' ) = 1
DBCC CHECKIDENT ('?', RESEED, 0) WITH NO_INFOMSGS;
즐기 되 조심하십시오!
가장 간단한 방법은
이렇게하면 디버깅이나 모든 것을 포함했는지에 대해 걱정할 필요없이 모든 테이블을 삭제하고 다시 만드는 스크립트가 제공됩니다. 이것은 잘림 이상의 기능을 수행하지만 결과는 동일합니다. 할당 된 마지막 값을 기억하는 잘린 테이블과 달리 자동 증가 기본 키는 0에서 시작합니다. PreProd 또는 프로덕션 환경에서 Management Studio에 액세스 할 수없는 경우 코드에서이를 실행할 수도 있습니다.
1.
2.
삼.
SQL Server에서는 외래 키를 사용하여 테이블을자를 수 없으므로 테이블간에 외래 키 관계가없는 경우에만 모든 테이블을 잘릴 수 있습니다.
이에 대한 대안은 외래 키가있는 테이블을 결정하고 먼저 외래 키를 삭제하는 것입니다. 그런 다음 외래 키없이 테이블을자를 수 있습니다.
자세한 내용은 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341 및 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=72957 을 참조 하십시오 .
이러지 마! 실제로는 좋은 생각이 아닙니다.
잘라내려는 테이블을 알고있는 경우 잘리는 저장 프로 시저를 만듭니다. 외래 키 문제를 피하기 위해 순서를 수정할 수 있습니다.
실제로 모두 잘라내려면 (예를 들어 BCP를로드 할 수 있음) 데이터베이스를 신속하게 삭제하고 처음부터 새 데이터베이스를 작성하면 위치를 정확히 알 수있는 추가 이점이 있습니다.
동일한 db 내에서 다른 테이블의 데이터를 삭제 / 잘라내는 동안 특정 테이블 (예 : 정적 조회 테이블)에 데이터를 유지하려면 예외가있는 루프가 필요합니다. 이것이 내가이 질문을 우연히 발견했을 때 찾고 있던 것입니다.
sp_MSForEachTable은 버그가있는 것 같습니다 (즉, IF 문과 일치하지 않는 동작). 아마도 MS가 문서화하지 않은 이유 일 것입니다.
declare @LastObjectID int = 0
declare @TableName nvarchar(100) = ''
set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
while(@LastObjectID is not null)
begin
set @TableName = (select top 1 [name] from sys.tables where [object_id] = @LastObjectID)
if(@TableName not in ('Profiles', 'ClientDetails', 'Addresses', 'AgentDetails', 'ChainCodes', 'VendorDetails'))
begin
exec('truncate table [' + @TableName + ']')
end
set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
end
모든 테이블을 잘라내는 가장 어려운 부분은 외래 키 제약 조건을 제거하고 다시 추가하는 것입니다.
다음 쿼리는 @myTempTable의 각 테이블 이름과 관련된 각 제약 조건에 대해 drop & create 문을 만듭니다. 모든 테이블에 대해 이들을 생성하려면 정보 스키마를 사용하여 이러한 테이블 이름을 대신 수집 할 수 있습니다.
DECLARE @myTempTable TABLE (tableName varchar(200))
INSERT INTO @myTempTable(tableName) VALUES
('TABLE_ONE'),
('TABLE_TWO'),
('TABLE_THREE')
-- DROP FK Contraints
SELECT 'alter table '+quotename(schema_name(ob.schema_id))+
'.'+quotename(object_name(ob.object_id))+ ' drop constraint ' + quotename(fk.name)
FROM sys.objects ob INNER JOIN sys.foreign_keys fk ON fk.parent_object_id = ob.object_id
WHERE fk.referenced_object_id IN
(
SELECT so.object_id
FROM sys.objects so JOIN sys.schemas sc
ON so.schema_id = sc.schema_id
WHERE so.name IN (SELECT * FROM @myTempTable) AND sc.name=N'dbo' AND type in (N'U'))
-- CREATE FK Contraints
SELECT 'ALTER TABLE [PIMSUser].[dbo].[' +cast(c.name as varchar(255)) + '] WITH NOCHECK ADD CONSTRAINT ['+ cast(f.name as varchar(255)) +'] FOREIGN KEY (['+ cast(fc.name as varchar(255)) +'])
REFERENCES [PIMSUser].[dbo].['+ cast(p.name as varchar(255)) +'] (['+cast(rc.name as varchar(255))+'])'
FROM sysobjects f
INNER JOIN sys.sysobjects c ON f.parent_obj = c.id
INNER JOIN sys.sysreferences r ON f.id = r.constid
INNER JOIN sys.sysobjects p ON r.rkeyid = p.id
INNER JOIN sys.syscolumns rc ON r.rkeyid = rc.id and r.rkey1 = rc.colid
INNER JOIN sys.syscolumns fc ON r.fkeyid = fc.id and r.fkey1 = fc.colid
WHERE
f.type = 'F'
AND
cast(p.name as varchar(255)) IN (SELECT * FROM @myTempTable)
그런 다음 실행할 명령문을 복사하지만 약간의 노력으로 커서를 사용하여 동적으로 실행할 수 있습니다.
비어있는 "템플릿"데이터베이스를 만들고 전체 백업을 수행하십시오. 새로 고침해야 할 때는 WITH REPLACE를 사용하여 복원하십시오. 빠르고 간단하며 방탄. 그리고 여기에 몇 개의 테이블이 있거나 기본 데이터 (예 : 구성 정보 또는 앱을 실행시키는 기본 정보)가 필요한 경우도 처리합니다.
이것은 하나입니다 방법입니다 ... 10 가지가 더 좋고 더 효율적일 가능성이 있지만, 이것이 매우 드물게 수행되는 것처럼 들리므로 여기에갑니다 ...
tables
from 의 목록을 가져온 sysobjects
다음 커서를 사용 sp_execsql('truncate table ' + @table_name)
하여 각각을 호출 하여 목록 을 반복 합니다 iteration
.
주석 처리 된 섹션을 한 번 실행하고 _TruncateList 테이블을 잘라내려는 테이블로 채우고 나머지 스크립트를 실행하십시오. 이 작업을 많이 수행하면 시간이 지남에 따라 _ScriptLog 테이블을 정리해야합니다.
모든 테이블을 수행하려면 SELECT name INTO #TruncateList FROM sys.tables에두기 만하면이 값을 수정할 수 있습니다. 그러나 일반적으로 모든 것을 원하지는 않습니다.
또한 이것은 데이터베이스의 모든 외래 키에 영향을 미치며 응용 프로그램에 너무 무딘 경우에도 수정할 수 있습니다. 내 목적이 아닙니다.
/*
CREATE TABLE _ScriptLog
(
ID Int NOT NULL Identity(1,1)
, DateAdded DateTime2 NOT NULL DEFAULT GetDate()
, Script NVarChar(4000) NOT NULL
)
CREATE UNIQUE CLUSTERED INDEX IX_ScriptLog_DateAdded_ID_U_C ON _ScriptLog
(
DateAdded
, ID
)
CREATE TABLE _TruncateList
(
TableName SysName PRIMARY KEY
)
*/
IF OBJECT_ID('TempDB..#DropFK') IS NOT NULL BEGIN
DROP TABLE #DropFK
END
IF OBJECT_ID('TempDB..#TruncateList') IS NOT NULL BEGIN
DROP TABLE #TruncateList
END
IF OBJECT_ID('TempDB..#CreateFK') IS NOT NULL BEGIN
DROP TABLE #CreateFK
END
SELECT Scripts = 'ALTER TABLE ' + '[' + OBJECT_NAME(f.parent_object_id)+ ']'+
' DROP CONSTRAINT ' + '[' + f.name + ']'
INTO #DropFK
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
SELECT TableName
INTO #TruncateList
FROM _TruncateList
SELECT Scripts = 'ALTER TABLE ' + const.parent_obj + '
ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY (
' + const.parent_col_csv + '
) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ')
'
INTO #CreateFK
FROM (
SELECT QUOTENAME(fk.NAME) AS [const_name]
,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id))
FROM sys.foreign_key_columns AS fcP
WHERE fcp.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [parent_col_csv]
,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id))
FROM sys.foreign_key_columns AS fcR
WHERE fcR.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [ref_col_csv]
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id
INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id
INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id
INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id
GROUP BY fkc.parent_object_id
,fkc.referenced_object_id
,fk.NAME
,fk.object_id
,schParent.NAME
,schRef.NAME
) AS const
ORDER BY const.const_name
INSERT INTO _ScriptLog (Script)
SELECT Scripts
FROM #CreateFK
DECLARE @Cmd NVarChar(4000)
, @TableName SysName
WHILE 0 < (SELECT Count(1) FROM #DropFK) BEGIN
SELECT TOP 1 @Cmd = Scripts
FROM #DropFK
EXEC (@Cmd)
DELETE #DropFK WHERE Scripts = @Cmd
END
WHILE 0 < (SELECT Count(1) FROM #TruncateList) BEGIN
SELECT TOP 1 @Cmd = N'TRUNCATE TABLE ' + TableName
, @TableName = TableName
FROM #TruncateList
EXEC (@Cmd)
DELETE #TruncateList WHERE TableName = @TableName
END
WHILE 0 < (SELECT Count(1) FROM #CreateFK) BEGIN
SELECT TOP 1 @Cmd = Scripts
FROM #CreateFK
EXEC (@Cmd)
DELETE #CreateFK WHERE Scripts = @Cmd
END
INFORMATION_SCHEMA.TABLES에서 '+ TABLE_NAME에서 삭제'를 선택하십시오. 여기서 TABLE_TYPE = 'BASE TABLE'
결과가 나오는 곳.
쿼리 창에서 복사하여 붙여 넣기 및 명령 실행