답변:
참조 무결성이 설정되어 있으면 TRUNCATE가 작동하지 않습니다.
이 경우 작동합니다.
EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
GO
USE [MyDataBase]
. 어떻게 든 적응하면 위의 아이디어가 효과가 있습니까? ... SQL 서버가 유지하는 모든 DB를 삭제하고 싶지 않기 때문에.
최근 프로젝트에서 내 작업은 sql 문과 기본 키 및 외래 키와 같은 많은 제약 조건이있는 각 테이블을 사용하여 전체 데이터베이스를 정리하는 것이 었습니다. 데이터베이스에 1000 개가 넘는 테이블이 있으므로 각 테이블에 대해 삭제 쿼리를 작성할 수 없습니다.
sp_MSForEachTable 이라는 저장 프로 시저를 사용하면 단일 데이터베이스의 각 테이블에 대해 일부 코드를 쉽게 처리 할 수 있습니다. 즉, 데이터베이스의 모든 테이블에 대해 단일 T-SQL 명령 또는 다른 T-SQL 명령을 처리하는 데 사용됩니다.
따라서 아래 단계에 따라 SQL Server 데이터베이스의 모든 테이블을 자릅니다.
1 단계-아래 SQL 쿼리를 사용하여 데이터베이스의 모든 제약 조건을 비활성화하십시오.
EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
2 단계 아래 sql 명령을 사용하여 데이터베이스의 각 테이블에서 삭제 또는 자르기 작업을 실행합니다.
EXEC sys.sp_msforeachtable 'DELETE FROM ?'
3 단계-아래 sql 문을 사용하여 데이터베이스에서 모든 제약 조건을 활성화합니다.
EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
sql server azure
있습니까?
모든 행을 삭제하고 다음 스크립트로 수행했습니다.
DECLARE @Nombre NVARCHAR(MAX);
DECLARE curso CURSOR FAST_FORWARD
FOR
Select Object_name(object_id) AS Nombre from sys.objects where type = 'U'
OPEN curso
FETCH NEXT FROM curso INTO @Nombre
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
DECLARE @statement NVARCHAR(200);
SET @statement = 'DELETE FROM ' + @Nombre;
print @statement
execute sp_executesql @statement;
END
FETCH NEXT FROM curso INTO @Nombre
END
CLOSE curso
DEALLOCATE curso
도움이 되었기를 바랍니다!
해결책은 다음과 같습니다.
INFORMATION_SCHEMA.TABLES
특정 데이터베이스에 대해 반복SELECTS
일부 검색 기준에 따른 테이블sysdiagrams
하고__RefactorLog
처음에 시도 EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?'
했지만 다이어그램이 삭제되었습니다.
USE <DB name>;
GO
-- Disable all constraints in the database
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
TABLE_CATALOG,
TABLE_SCHEMA,
TABLE_NAME
from INFORMATION_SCHEMA.TABLES
where
TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != '__RefactorLog'
OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
/* Make sure these are the commands you want to execute before executing */
PRINT 'Executing statement: ' + @sql
-- EXECUTE sp_executesql @sql
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
END
CLOSE i;
DEALLOCATE i;
-- Re-enable all constraints again
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
ALTER TABLE
제약 조건을 비활성화 하는 비트가 실패합니다.
제 경우에는 QUOTED_IDENTIFIER를 설정해야했습니다. 이로 인해 위의 Mark Rendle의 답변이 약간 수정되었습니다.
EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
GO
DELETE failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.
Set nocount on
Exec sp_MSForEachTable 'Alter Table ? NoCheck Constraint All'
Exec sp_MSForEachTable
'
If ObjectProperty(Object_ID(''?''), ''TableHasForeignRef'')=1
Begin
-- Just to know what all table used delete syntax.
Print ''Delete from '' + ''?''
Delete From ?
End
Else
Begin
-- Just to know what all table used Truncate syntax.
Print ''Truncate Table '' + ''?''
Truncate Table ?
End
'
Exec sp_MSForEachTable 'Alter Table ? Check Constraint All'
Rubens 제안과 같은 접근 방식을 사용하여 모든 테이블에서 모든 행을 삭제하거나 모든 테이블을 삭제하고 다시 만들 수 있습니다. 어쨌든 가장 쉬운 / 빠른 방법이 될 수 있도록 전체 DB 작성 스크립트를 사용하는 것이 좋습니다.
일부 요구 사항의 경우 특정 테이블을 건너 뛰어야 할 수도 있습니다. 테이블 목록을 필터링하기 위해 몇 가지 추가 조건을 추가하기 위해 아래 스크립트를 작성했습니다. 아래 스크립트에는 사전 삭제 횟수와 사후 삭제 횟수도 표시됩니다.
IF OBJECT_ID('TEMPDB..#TEMPRECORDCOUNT') IS NOT NULL
DROP TABLE #TEMPRECORDCOUNT
CREATE TABLE #TEMPRECORDCOUNT
( TABLENAME NVARCHAR(128)
,PREDELETECOUNT BIGINT
,POSTDELETECOUNT BIGINT
)
INSERT INTO #TEMPRECORDCOUNT (TABLENAME, PREDELETECOUNT, POSTDELETECOUNT)
SELECT O.name TableName
,DDPS.ROW_COUNT PREDELETECOUNT
,NULL FROM sys.objects O
INNER JOIN (
SELECT OBJECT_ID, SUM(row_count) ROW_COUNT
FROM SYS.DM_DB_PARTITION_STATS
GROUP BY OBJECT_ID
) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1
DECLARE @TableName NVARCHAR(MAX);
DECLARE TableDeleteCursor CURSOR FAST_FORWARD
FOR
SELECT TableName from #TEMPRECORDCOUNT
OPEN TableDeleteCursor
FETCH NEXT FROM TableDeleteCursor INTO @TableName
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
DECLARE @STATEMENT NVARCHAR(MAX);
SET @STATEMENT = ' DISABLE TRIGGER ALL ON ' + @TableName +
'; ALTER TABLE ' + @TableName + ' NOCHECK CONSTRAINT ALL' +
'; DELETE FROM ' + @TableName +
'; ALTER TABLE ' + @TableName + ' CHECK CONSTRAINT ALL' +
'; ENABLE TRIGGER ALL ON ' + @TableName;
PRINT @STATEMENT
EXECUTE SP_EXECUTESQL @STATEMENT;
END
FETCH NEXT FROM TableDeleteCursor INTO @TableName
END
CLOSE TableDeleteCursor
DEALLOCATE TableDeleteCursor
UPDATE T
SET T.POSTDELETECOUNT = I.ROW_COUNT
FROM #TEMPRECORDCOUNT T
INNER JOIN (
SELECT O.name TableName, DDPS.ROW_COUNT ROW_COUNT
FROM sys.objects O
INNER JOIN (
SELECT OBJECT_ID, SUM(row_count) ROW_COUNT
FROM SYS.DM_DB_PARTITION_STATS
GROUP BY OBJECT_ID
) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1
) I ON I.TableName COLLATE DATABASE_DEFAULT = T.TABLENAME
SELECT * FROM #TEMPRECORDCOUNT
ORDER BY TABLENAME ASC
이 답변은 ID 열도 재설정하여 Zach Smith의 답변을 기반 으로합니다.
다음은 쿼리입니다.
-- Disable all constraints in the database
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
TABLE_CATALOG,
TABLE_SCHEMA,
TABLE_NAME
from INFORMATION_SCHEMA.TABLES
where
TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != '__RefactorLog'
-- Optional
-- AND (TABLE_SCHEMA = 'dbo')
OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
/* Make sure these are the commands you want to execute before executing */
PRINT 'Executing statement: ' + @sql
--EXECUTE sp_executesql @sql
-- Reset identity counter if one exists
IF ((SELECT OBJECTPROPERTY( OBJECT_ID(@catalog + '.' + @schema + '.' + @tbl), 'TableHasIdentity')) = 1)
BEGIN
SET @sql = N'DBCC CHECKIDENT ([' + @catalog + '.' + @schema + '.' + @tbl + '], RESEED, 0)'
PRINT 'Executing statement: ' + @sql
--EXECUTE sp_executesql @sql
END
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
END
CLOSE i;
DEALLOCATE i;
-- Re-enable all constraints again
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
--Load tables to delete from
SELECT
DISTINCT
' Delete top 1000000 from <DBName>.<schema>.' + c.TABLE_NAME + ' WHERE <Filter Clause Here>' AS query,c.TABLE_NAME AS TableName, IsDeleted=0, '<InsertSomeDescriptorHere>' AS [Source]--,t.TABLE_TYPE, c.*
INTO dbo.AllTablesToDeleteFrom
FROM INFORMATION_SCHEMA.TABLES AS t
INNER JOIN information_schema.columns c ON c.TABLE_NAME = t.TABLE_NAME
WHERE c.COLUMN_NAME = '<column name>'
AND c.TABLE_SCHEMA = 'dbo'
AND c.TABLE_CATALOG = '<DB Name here>'
AND t.TABLE_TYPE='Base table'
--AND t.TABLE_NAME LIKE '<put filter here>'
DECLARE @TableSelect NVARCHAR(1000)= '';
DECLARE @Table NVARCHAR(1000)= '';
DECLARE @IsDeleted INT= 0;
DECLARE @NumRows INT = 1000000;
DECLARE @Source NVARCHAR(50)='';
WHILE ( @IsDeleted = 0 )
BEGIN
--This grabs one table at a time to be deleted from. @TableSelect has the sql to execute. it is important to order by IsDeleted ASC
--because it will pull tables to delete from by those that have a 0=IsDeleted first. Once the loop grabs a table with IsDeleted=1 then this will pop out of loop
SELECT TOP 1
@TableSelect = query,
@IsDeleted = IsDeleted,
@Table = TableName,
@Source=[a].[Source]
FROM dbo.AllTablesToDeleteFrom a
WHERE a.[Source]='SomeDescriptorHere'--use only if needed
ORDER BY a.IsDeleted ASC;--this is required because only those records returned with IsDeleted=0 will run through loop
--SELECT @Table; can add this in to monitor what table is being deleted from
WHILE ( @NumRows = 1000000 )--only delete a million rows at a time?
BEGIN
EXEC sp_executesql @TableSelect;
SET @NumRows = @@ROWCOUNT;
--IF @NumRows = 1000000 --can do something here if needed
--One wants this loop to continue as long as a million rows is deleted. Once < 1 million rows is deleted it pops out of loop
--and grabs next table to delete
-- BEGIN
--SELECT @NumRows;--can add this in to see current number of deleted records for table
INSERT INTO dbo.DeleteFromAllTables
( tableName,
query,
cnt,
[Source]
)
SELECT @Table,
@TableSelect,
@NumRows,
@Source;
-- END;
END;
SET @NumRows = 1000000;
UPDATE a
SET a.IsDeleted = 1
FROM dbo.AllTablesToDeleteFrom a
WHERE a.TableName = @Table;
--flag this as deleted so you can move on to the next table to delete from
END;