Bir SQL Server veritabanındaki tüm tablolardan tüm satırları nasıl silebilirim?


Yanıtlar:


264

Herhangi bir referans bütünlüğünüz varsa TRUNCATE'in çalışmayacağını unutmayın.

Bu durumda, bu işe yarayacaktır:

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

1
Aslında, bu sadece DDL tetikleyicileri içindir. Bu durumda: EXECP sp_MSForEachTable 'TETİKLEYİCİ TÜMÜNÜ devre dışı bırakılsın mı?'
Mark Rendle

10
SQL Azure'da mevcut değil :(
Akash Kava

Tamam Biraz kafam karıştı (belki de yardımcı olabilirim) Veritabanımın bir yedeğini aldım ve yaklaşık 10 MB'dı, sonra SQL kodunuzu veritabanımı boşaltmak için çalıştırdım ve düşündüğüm şeyin yeni bir yedeğini aldım boş veritabanı e-posta ile başka birine göndermek ama benim 'boş' veritabanı yedekleme şimdi 14 MB oldu? Neyi yanlış yaptım?
Ben

1
Anladım - bir yedek dosya zaten varsa, o zaman SSMS yerine yerine ekler gibi görünüyor (bunu fark etmedim). Bu yüzden dosyayı sildim ve şimdi 'boş' veritabanı yedekleme dosyası sadece 3.7 MB
Ben

1
Ne gibi DB, bir şey seçmek isterseniz: USE [MyDataBase]? Yukarıdaki fikir bir şekilde uyarlanmış olsaydı işe yarar mı? ... Çünkü SQL sunucusu tarafından tutulan tüm DB'leri silmek istemiyorum.
גרונןי גרונן

20

Son projemde görevim sql deyimini ve her tablonun Birincil Anahtar ve Yabancı Anahtar gibi birçok kısıtlaması olan tüm veritabanını temizlemekti. Veritabanında 1000'den fazla tablo vardır, bu nedenle her tabloya bir silme sorgusu yazmak mümkün değildir.

Sp_MSForEachTable adlı saklı yordamı kullanarak , tek bir veritabanındaki tabloların her birine karşı bazı kodları kolayca işlememizi sağlar. Veritabanındaki her tabloya karşı tek bir T-SQL komutunu veya farklı bir T-SQL komutunu işlemek için kullanıldığı anlamına gelir.

SQL Server Veritabanındaki tüm tabloları kısaltmak için aşağıdaki adımları izleyin:

Adım 1- Aşağıdaki sql sorgusunu kullanarak veritabanındaki tüm kısıtlamaları devre dışı bırakın:

EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

Adım 2- Aşağıdaki sql komutunu kullanarak veritabanının her tablosunda bir Sil veya kısalt işlemini yürütün:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Adım 3- Aşağıdaki sql deyimini kullanarak veritabanındaki tüm kısıtlamaları etkinleştirin:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'

1
Basitçe adım 2 çoklu süreleri yürütebilirsiniz, böylece bağımlı olmayan tabloları ilk kez siler, ilk kez başarısız olan bu tabloları silmek için 2. kez, 2. kez başarısızlığı silmek için 3. kez, vb.

bunun nasıl yapılacağı hakkında herhangi bir fikir sql server azure?
Zapnologica

Sadece düz SQL kullandığından Bu yaklaşım Azure da çalışacaktır: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner

15

Tüm satırları silmek zorunda kaldım ve sonraki komut dosyasıyla yaptım:

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

Bu yardımcı olur umarım!


Bunun için teşekkürler, çünkü bazı tabloları ortadan kaldırmak için seçimi değiştirmem gerekiyordu. Bu işe yaradı.
Don Rolling

13

İşte bir çözüm:

  1. Damla kısıtlamaları ( bu yazı sayesinde )
  2. INFORMATION_SCHEMA.TABLESBelirli bir veritabanı için yineleme yapar
  3. SELECTS bazı arama kriterlerini temel alan tablolar
  4. Bu tablolardaki tüm verileri siler
  5. Kısıtlamaları yeniden ekler
  6. Gibi belirli tabloları göz ardı izin verir sysdiagramsve__RefactorLog

Başlangıçta denedim EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', ama bu benim diyagramlarımı sildi.

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"

Bu harika ama dbo olmayan şemaları dikkate almıyor.
akın

Hiç dbo olmayan şemalar kullanmadım, bu yüzden onu yakalayamazdım. Ama neden çalışmıyor? Hiçbir yerde şema belirtmiyorum, bu yüzden sadece dbo varsayılan mı?
Zach Smith

Örneğin, test.Table1 adlı bir tablonuz varsa, burada "test" şemadır, "Tablo1'den SİL" işlemini gerçekleştirmeye çalıştığınızda silme işlemleriniz başarısız olur. Testten DELETE olması gerekir.
akın

2
@influent - şimdi hesaba olmayan Dbo şemaları alır
Zach Smith

Ne yazık ki FK kısıtlamaları varsa bu başarısız gibi görünüyor. ALTER TABLEDevre dışı kısıtlamaları biraz başarısız olur.
Douglas Gaskell

8

Benim durumumda QUOTED_IDENTIFIER ayarlamam gerekiyordu. Bu, Mark Rendle'ın yukarıdaki cevabında küçük bir değişikliğe yol açtı:

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

Benim için çalıştı - bu hatayı almadan önce: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.
DharmaTurtle

4
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'

1

Rubens'in önerdiği bir yaklaşımı kullanarak tüm tablolardaki tüm satırları silebilirsiniz veya tüm tabloları bırakıp yeniden oluşturabilirsiniz. Her zaman tam db oluşturma komut dosyalarına sahip olmak her zaman iyi bir fikirdir, böylece en kolay / en hızlı yöntem olabilir.


OP'nin referans bütünlüğü ve tetikleyicilerle ilgili olduğu anlaşılıyor; Bu durumda, en iyi çözümünüz var. Cevabımı bırakıyorum =)
Rubens Farias

2
Kısaltmak istedim =)
Rubens Farias

0

Bazı gereksinimler için belirli tabloları atlamamız gerekebilir. Tablo listesini filtrelemek için bazı ekstra koşullar eklemek için aşağıdaki komut dosyasını yazdım. Aşağıdaki komut dosyası ayrıca silme öncesi sayısını ve silme sonrası sayısını gösterir.

        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

0

Bu cevap, Zach Smith'in kimlik sütununu da sıfırlayarak cevabını temel alıyor :

  1. Tüm kısıtlamaları devre dışı bırakma
  2. Hariç tutmayı seçenler hariç tüm tablolarda yineleme
  3. Tablodaki tüm satırları siler
  4. Varsa kimlik sütununu sıfırlar
  5. Tüm kısıtlamaları yeniden etkinleştirir

İşte sorgu:

-- 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"

Bir nedenden ötürü bu çoğunlukla FK kısıtlama hataları attığından başarısız olur.
Douglas Gaskell

0
--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; 

-3

tüm tabloyu silmek istiyorsanız, bir sonraki SQL talimatını izlemelisiniz

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.