FOREIGN KEY kısıtlaması tarafından başvurulduğundan tablo kesilemiyor mu?


459

MSSQL2005 kullanarak, alt tabloyu (FK ilişkisinin birincil anahtarının bulunduğu tablo) ilk önce kesersem, tabloyu yabancı anahtar kısıtlamasıyla kesebilir miyim?

Biliyorum ki ben de

  • Bir kullanma DELETEbir yerde madde ve daha sonra olmadan RESEEDkimlik (ya da)
  • FK'yi çıkarın, masayı kesin ve FK'yi yeniden oluşturun.

Ebeveynden önce alt tabloyu kesmiş olduğum sürece, yukarıdaki seçeneklerden herhangi birini yapmadan iyi olacağımı düşündüm, ancak bu hatayı alıyorum:

FOREIGN KEY kısıtlaması tarafından başvuruda bulunduğundan 'TableName' tablosu kesilemiyor.

Yanıtlar:


379

Doğru; üzerinde FK kısıtlaması olan bir tabloyu kesemezsiniz.

Genellikle bunun için benim süreç:

  1. Kısıtlamaları bırakın
  2. Masayı kes
  3. Kısıtlamaları yeniden oluşturun.

(Tabii ki bir işlemde.)

Tabii ki, bu sadece çocuk zaten kesilmişse geçerlidir. Aksi takdirde, tamamen verilerimin neye benzediğine bağlı olarak farklı bir rotaya giderim. (Buraya girmek için çok fazla değişken var.)

Orijinal poster NEDEN böyle olduğunu belirledi; bkz bu cevabı daha fazla ayrıntı için.


73
Bir "SİL", otomatik artan sütunları sıfırlamaz. Kesik keser. İşlevsel olarak eşdeğer değildirler.
robross0606

35
Büyük miktarda veri siliyorsanız, kısaltma genellikle yapmak istediğiniz şeydir. Bir milyon satırı mı kesiyorsunuz? Bir milyar? 1 ms ... yani @ M07, lütfen "yaklaşımdan sil daha temiz" demeyin, çünkü bu uzaktan doğru değildir.
ctb

1
Büyük verileri sildikten sonra, kullanıcının disk alanını geri kazanmak için tabloları ve günlük dosyalarını daraltması gerekir.
Muhammed Yousaf Sulahria

2
Magic Shrink düğmesi (veya komut dosyası)% 99 oranında tavsiye edilmez.
Tom Stickel

1
Ve bunu nasıl yapardın? Örnek istekler?
jeromej

358
DELETE FROM TABLENAME
DBCC CHECKIDENT ('DATABASENAME.dbo.TABLENAME',RESEED, 0)

Çok yavaş olduğu için milyonlarca kaydınız varsa, bunun muhtemelen istediğiniz şey olmadığını unutmayın.


Bu, kısıtlamayı devre dışı bırakmak ve etkinleştirmekten daha hızlı, daha hızlı bir yoldu.
sensei

Bu yalnızca daha az veri içeren tablolar için çalışır. @Pure
Dhanuka777

1
Bu, bir şemayı test
etmeyi

3
Bu hatayı da alabileceğiniz için bu
rotaya gitmenizi tavsiye etmem

Benim için çalışmadı. Hala DELETE deyimi REFERENCE kısıtlamasıyla çakışıyor.
emirhosseini

192

DDL komutu olduğundan TRUNCATE TABLE, tablodaki kayıtlara alt tablodaki bir kayıt tarafından başvuru yapılıp yapılmadığını denetleyemez .

Bu nedenle DELETEçalışır ve TRUNCATE TABLEçalışmaz: çünkü veritabanı başka bir kayıt tarafından referans alınmadığından emin olabilir.


92

olmadan ALTER TABLE

-- Delete all records
DELETE FROM [TableName]
-- Set current ID to "1"
-- If table already contains data, use "0"
-- If table is empty and never insert data, use "1"
-- Use SP https://github.com/reduardo7/TableTruncate
DBCC CHECKIDENT ([TableName], RESEED, 0)

Saklı Yordam Olarak

https://github.com/reduardo7/TableTruncate

Not bu + kayıtları milyonlarca varsa çok yavaş olarak, isterdim ne muhtemelen olmadığını.


3
DELETE FROM, 1 yerine ID 2'den başladıktan sonra reseed new value = 1 kullanıldığında, Technet'ten ( technet.microsoft.com/en-us/library/ms176057%28SQL.90%29.aspx ) Hiçbir satır yoksa oluşturulduğundan beri tabloya eklenir veya TRUNCATE TABLE deyimi kullanılarak tüm satırlar kaldırılır; DBCC CHECKIDENT çalıştırıldıktan sonra eklenen ilk satır kimlik olarak new_reseed_value kullanır. Aksi takdirde, eklenen sonraki satır new_reseed_value + geçerli artış değerini kullanır.
Zoran P.

@ZoranP. lütfen Saklı Yordam varyantına bakın: github.com/reduardo7/TableTruncate
Eduardo Cuomo

4
DBCC CHECKIDENT ([TableName], RESEED, 0) not 1
Tico Fortes

1
@TicoFortes Gönderi güncellendi. Lütfen Saklı Yordam varyantına bakın
Eduardo Cuomo

1
Bu iyi bir yaklaşım değil. Bu soruya aynı cevabın 700 diğer versiyonu tarafından yorumlandığı gibi. İşlem günlüğünü sınırlamak için veritabanınızın Basit kurtarma modunda OLMADIĞI.
pimbrouwers

68

Yukarıda verilen @denver_citizen çözümü benim için işe yaramadı, ama onun ruhunu beğendim, bu yüzden birkaç şeyi değiştirdim:

  • saklı bir prosedür haline getirdi
  • Yabancı anahtarların doldurulma ve yeniden oluşturulma şeklini değiştirdi
  • özgün komut dosyası başvurulan tüm tabloları keser, başvurulan tabloda başka yabancı anahtar başvuruları olduğunda yabancı anahtar ihlali hatasına neden olabilir. Bu komut dosyası yalnızca parametre olarak belirtilen tabloyu keser. Bu saklı yordamı tüm tablolarda doğru sırayla birden çok kez çağırmak kullanıcıya kalmış

Halkın yararı için güncellenmiş senaryo:

CREATE PROCEDURE [dbo].[truncate_non_empty_table]

  @TableToTruncate                 VARCHAR(64)

AS 

BEGIN

SET NOCOUNT ON

-- GLOBAL VARIABLES
DECLARE @i int
DECLARE @Debug bit
DECLARE @Recycle bit
DECLARE @Verbose bit
DECLARE @TableName varchar(80)
DECLARE @ColumnName varchar(80)
DECLARE @ReferencedTableName varchar(80)
DECLARE @ReferencedColumnName varchar(80)
DECLARE @ConstraintName varchar(250)

DECLARE @CreateStatement varchar(max)
DECLARE @DropStatement varchar(max)   
DECLARE @TruncateStatement varchar(max)
DECLARE @CreateStatementTemp varchar(max)
DECLARE @DropStatementTemp varchar(max)
DECLARE @TruncateStatementTemp varchar(max)
DECLARE @Statement varchar(max)

        -- 1 = Will not execute statements 
 SET @Debug = 0
        -- 0 = Will not create or truncate storage table
        -- 1 = Will create or truncate storage table
 SET @Recycle = 0
        -- 1 = Will print a message on every step
 set @Verbose = 1

 SET @i = 1
    SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
    SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
    SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'

-- Drop Temporary tables

IF OBJECT_ID('tempdb..#FKs') IS NOT NULL
    DROP TABLE #FKs

-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
       OBJECT_NAME(constraint_object_id) as ConstraintName,
       OBJECT_NAME(parent_object_id) as TableName,
       clm1.name as ColumnName, 
       OBJECT_NAME(referenced_object_id) as ReferencedTableName,
       clm2.name as ReferencedColumnName
  INTO #FKs
  FROM sys.foreign_key_columns fk
       JOIN sys.columns clm1 
         ON fk.parent_column_id = clm1.column_id 
            AND fk.parent_object_id = clm1.object_id
       JOIN sys.columns clm2
         ON fk.referenced_column_id = clm2.column_id 
            AND fk.referenced_object_id= clm2.object_id
 --WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
 WHERE OBJECT_NAME(referenced_object_id) = @TableToTruncate
 ORDER BY OBJECT_NAME(parent_object_id)


-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
   BEGIN
        IF @Verbose = 1
     PRINT '1. Creating Process Specific Tables...'

  -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
  CREATE TABLE [Internal_FK_Definition_Storage] 
  (
   ID int not null identity(1,1) primary key,
   FK_Name varchar(250) not null,
   FK_CreationStatement varchar(max) not null,
   FK_DestructionStatement varchar(max) not null,
   Table_TruncationStatement varchar(max) not null
  ) 
   END 
ELSE
   BEGIN
        IF @Recycle = 0
            BEGIN
                IF @Verbose = 1
       PRINT '1. Truncating Process Specific Tables...'

    -- TRUNCATE TABLE IF IT ALREADY EXISTS
    TRUNCATE TABLE [Internal_FK_Definition_Storage]    
      END
      ELSE
         PRINT '1. Process specific table will be recycled from previous execution...'
   END


IF @Recycle = 0
   BEGIN

  IF @Verbose = 1
     PRINT '2. Backing up Foreign Key Definitions...'

  -- Fetch and persist FKs             
  WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
   BEGIN
    SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
    SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
    SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
    SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
    SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)

    SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
    SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
    SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 

    INSERT INTO [Internal_FK_Definition_Storage]
                        SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'

    END   
    END   
    ELSE 
       PRINT '2. Backup up was recycled from previous execution...'

       IF @Verbose = 1
     PRINT '3. Dropping Foreign Keys...'

    -- DROP FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1


    IF @Verbose = 1
       PRINT '  > Dropping [' + @ConstraintName + ']'

             END     


    IF @Verbose = 1
       PRINT '4. Truncating Tables...'

    -- TRUNCATE TABLES
-- SzP: commented out as the tables to be truncated might also contain tables that has foreign keys
-- to resolve this the stored procedure should be called recursively, but I dont have the time to do it...          
 /*
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN

    SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > ' + @Statement
          END
*/          


    IF @Verbose = 1
       PRINT '  > TRUNCATE TABLE [' + @TableToTruncate + ']'

    IF @Debug = 1 
        PRINT 'TRUNCATE TABLE [' + @TableToTruncate + ']'
    ELSE
        EXEC('TRUNCATE TABLE [' + @TableToTruncate + ']')


    IF @Verbose = 1
       PRINT '5. Re-creating Foreign Keys...'

    -- CREATE FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1


    IF @Verbose = 1
       PRINT '  > Re-creating [' + @ConstraintName + ']'

          END

    IF @Verbose = 1
       PRINT '6. Process Completed'


END

11
Bu cevap daha fazla oyu hak ediyor! Aslında yapabilseydim sana bir bira alırım, Peter :)
nsimeonov

Bu, test için verilerinin bazı büyük tablolarını hızlı bir şekilde temizlemek için bugün bana çok yardımcı oldu, Buradaki kaliteli çalışma için teşekkürler.
Craig Selbert

4
Bu kod parçası için teşekkür ederim. Ancak dikkat edin, devre dışı bırakılan FK'leri kontrol etmek için ek bir mantık eklemelisiniz. Aksi takdirde, şu anda devre dışı bırakılmış kısıtlamaları etkinleştirirsiniz.
Andre Figueiredo

2
@AndreFigueiredo'nun önerileriyle bir versiyon yaptım. Gitlab üzerine koyuyorum: gitlab.com/ranolfi/truncate-referenced-table . Kodu cevabınıza dahil etmekten çekinmeyin.
Marc.2377

1
Bu harika, ancak tablolarınız varsayılan (dbo) şemada değilse işe yaramayacağını unutmayın.
Sidewinder94

19

delete deyimini kullanarak bu tablodaki tüm satırları sildikten sonra aşağıdaki komutu kullanın

delete from tablename

DBCC CHECKIDENT ('tablename', RESEED, 0)

EDIT: SQL Server için sözdizimi düzeltildi


9
TRUNCATEgünlüğü önler ve DELETEbüyük tablolardan çok daha hızlıdır . Bu nedenle, bu gerçek bir eşdeğer çözüm değildir.
siride

1
Nasıl bu cevabı farklı olduğu biri verildi, bir yıl önce?
Ofer Zelig

17

Eh, bulamadık çünkü örnekler arasında çok basit olan benim kullandığım çözümü:

  1. Yabancı anahtarı bırakın;
  2. Tabloyu kes
  3. Yabancı anahtarı yeniden oluştur

İşte gidiyor:

1) Hataya neden olan yabancı anahtar adını bulun (örneğin: FK_PROBLEM_REASON, alanlı ID, tablodan TABLE_OWNING_CONSTRAINT) 2) Bu anahtarı tablodan çıkarın:

ALTER TABLE TABLE_OWNING_CONSTRAINT DROP CONSTRAINT FK_PROBLEM_REASON

3) İstenen tabloyu kes

TRUNCATE TABLE TABLE_TO_TRUNCATE

4) İlk tabloya anahtarı tekrar ekleyin:

ALTER TABLE TABLE_OWNING_CONSTRAINT ADD CONSTRAINT FK_PROBLEM_REASON FOREIGN KEY(ID) REFERENCES TABLE_TO_TRUNCATE (ID)

Bu kadar.


Yabancı anahtar başvuruları olan birden çok tablonuz varsa bu çalışmaz. Tüm veritabanı boyunca çok sayıda yabancı anahtar sınırlamasını kaldırmanız gerekir.
jbright

13

İşte süreci otomatikleştirmek için yazdığım bir senaryo. Umut ediyorum bu yardım eder.

SET NOCOUNT ON

-- GLOBAL VARIABLES
DECLARE @i int
DECLARE @Debug bit
DECLARE @Recycle bit
DECLARE @Verbose bit
DECLARE @TableName varchar(80)
DECLARE @ColumnName varchar(80)
DECLARE @ReferencedTableName varchar(80)
DECLARE @ReferencedColumnName varchar(80)
DECLARE @ConstraintName varchar(250)

DECLARE @CreateStatement varchar(max)
DECLARE @DropStatement varchar(max)   
DECLARE @TruncateStatement varchar(max)
DECLARE @CreateStatementTemp varchar(max)
DECLARE @DropStatementTemp varchar(max)
DECLARE @TruncateStatementTemp varchar(max)
DECLARE @Statement varchar(max)

        -- 1 = Will not execute statements 
 SET @Debug = 0
        -- 0 = Will not create or truncate storage table
        -- 1 = Will create or truncate storage table
 SET @Recycle = 0
        -- 1 = Will print a message on every step
 set @Verbose = 1

 SET @i = 1
    SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
    SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
    SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'

-- Drop Temporary tables
DROP TABLE #FKs

-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
       OBJECT_NAME(constraint_object_id) as ConstraintName,
       OBJECT_NAME(parent_object_id) as TableName,
       clm1.name as ColumnName, 
       OBJECT_NAME(referenced_object_id) as ReferencedTableName,
       clm2.name as ReferencedColumnName
  INTO #FKs
  FROM sys.foreign_key_columns fk
       JOIN sys.columns clm1 
         ON fk.parent_column_id = clm1.column_id 
            AND fk.parent_object_id = clm1.object_id
       JOIN sys.columns clm2
         ON fk.referenced_column_id = clm2.column_id 
            AND fk.referenced_object_id= clm2.object_id
 WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
 ORDER BY OBJECT_NAME(parent_object_id)


-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
   BEGIN
        IF @Verbose = 1
     PRINT '1. Creating Process Specific Tables...'

  -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
  CREATE TABLE [Internal_FK_Definition_Storage] 
  (
   ID int not null identity(1,1) primary key,
   FK_Name varchar(250) not null,
   FK_CreationStatement varchar(max) not null,
   FK_DestructionStatement varchar(max) not null,
   Table_TruncationStatement varchar(max) not null
  ) 
   END 
ELSE
   BEGIN
        IF @Recycle = 0
            BEGIN
                IF @Verbose = 1
       PRINT '1. Truncating Process Specific Tables...'

    -- TRUNCATE TABLE IF IT ALREADY EXISTS
    TRUNCATE TABLE [Internal_FK_Definition_Storage]    
      END
      ELSE
         PRINT '1. Process specific table will be recycled from previous execution...'
   END

IF @Recycle = 0
   BEGIN

  IF @Verbose = 1
     PRINT '2. Backing up Foreign Key Definitions...'

  -- Fetch and persist FKs             
  WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
   BEGIN
    SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
    SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
    SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
    SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
    SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)

    SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
    SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
    SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 

    INSERT INTO [Internal_FK_Definition_Storage]
                        SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'

   END
    END   
    ELSE 
       PRINT '2. Backup up was recycled from previous execution...'

       IF @Verbose = 1
     PRINT '3. Dropping Foreign Keys...'

    -- DROP FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Dropping [' + @ConstraintName + ']'
             END     

    IF @Verbose = 1
       PRINT '4. Truncating Tables...'

    -- TRUNCATE TABLES
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
    SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > ' + @Statement
          END

    IF @Verbose = 1
       PRINT '5. Re-creating Foreign Keys...'

    -- CREATE FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Re-creating [' + @ConstraintName + ']'
          END

    IF @Verbose = 1
       PRINT '6. Process Completed'

2
Dikkatli ol. Ben de senaryonuza anahtarlar üzerinde referans eylemleri eklemek istiyorsunuz yoksa basamaklı ayarları kaybedersiniz.
alphadogg

1
Bu benim için işe yaramadı, ama onun ruhunu sevdim, bu yüzden birkaç şeyi değiştirdim: saklı bir prosedür yabancı anahtarların doldurulma şeklini değiştirdi ve orijinal komut dosyasını yeniden oluşturdu, referans alınan tüm tabloları kesiyor, bu referans alındığında yanlış olabilir tablonun yabancı anahtar referansları olduğu için kısaltılamaz. Parametre olarak belirtilen ancak tablo kesilecek Bu versiyonda, tüm başvurulan tablo burada bu konuya güncellenen tolution yayınlanan bu senaryoyu çağırmadan önce elle kesilmiş olmalıdır stackoverflow.com/a/13249209/157591
Peter Szanto

1
@alphadogg Bu referans eylemleri bulmanın bir yolu var mı? İnternette dolaşıyorum ve onları bulamıyorum. İsterseniz resmi bir soru olarak gönderebilirim.
Michael - Clay Shirky

1
Gelecekteki ziyaretçilere not: sys.foreign_keystabloda yer almaktadır. ( Referans )
Michael - Clay Shirky

@Michael: BİLGİ_SCHEMA.REFERENTIAL_CONSTRAINTS ( msdn.microsoft.com/en-us/library/ms179987.aspx )
adresini

13

siz bu adımı takip edebilir reseeding tabletablonun verileri silebilirsiniz.

delete from table_name
dbcc checkident('table_name',reseed,0)

bir hata gelirse, birincil tabloyu yeniden göndermeniz gerekir.


1
Her ne kadar bu iyi çalışıyor olsa da, işlem günlüğünün tablodaki kayıtların sayısı ile işlem günlüğüne yalnızca bir kayıt koyan 'kesme tablosuna' göre artacağını unutmayın. Çoğu tablolar için büyük bir anlaşma değil ama milyonlarca + satır varsa o zaman bir sorun olabilir.
David

9
SET FOREIGN_KEY_CHECKS = 0; 

truncate table "yourTableName";

SET FOREIGN_KEY_CHECKS = 1;

8
Bu soru, FOREIGN_KEY_CHECKS ayarı olmayan MS SQL Server ile ilgilidir
Elezar

1
Bu MySQL çalışacağını düşünüyorum, ama MS SQL Server değil
Cocowalla

8

Doğru anlıyorsam, ne istiyorsun DB yapmak için entegrasyon testlerini içeren temiz bir ortam oluşturmak .

Buradaki yaklaşımım, tüm şemayı bırakmak ve daha sonra yeniden yaratmak olacaktır.

Nedenleri:

  1. Muhtemelen zaten bir "şema oluştur" komut dosyanız var. Test izolasyonu için tekrar kullanılması kolaydır.
  2. Şema oluşturmak oldukça hızlı.
  3. Bu yaklaşımla, komut dizinizi her bir fikstürün YENİ bir şema (geçici bir adla) oluşturmasını sağlamak için oldukça kolaydır ve daha sonra test armatürlerini paralel olarak çalıştırmaya başlayarak test takımınızın en yavaş kısmını daha hızlı hale getirebilirsiniz. .

1
Tüm şemayı 'kesmek' değil, düşürmek istiyorum. Bunu, entegrasyon testlerinin Kurulum yönteminde yapmak istiyorum. DB oluşturma komut dosyasını entegrasyon testlerinden çağırmak ... gideceğim ilk çözüm değil.
ripper234

7

Web üzerinde başka bir yerde bulundu

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'
-- EXEC sp_MSForEachTable 'DELETE FROM ?' -- Uncomment to execute
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'

3
Muhtemelen 'ALTER TABLOSU olmalı mı? KONTROL KONTROL TÜMÜNÜ SINIRLAYIN
Andriy M

20
-1: Sorunun sorduğu gibi truncate komutuyla bunun işe yaramadığını doğruladım. Bkz. Stackoverflow.com/questions/3843806/…
Lynn Crumbling

7

Kısıtlamaları bırakmazsanız bir tabloyu kesemezsiniz. Devre dışı bırakma da çalışmaz. her şeyi bırakmalısın. Ben tüm kısıtlamaları bırakıp sonra yeniden oluşturmak bir komut dosyası yaptım.

Bir işleme koyduğunuzdan emin olun;)

SET NOCOUNT ON
GO

DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200)
)

INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'

UPDATE @table SET
PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME

UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME

UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME

--DROP CONSTRAINT:

DECLARE @dynSQL varchar(MAX);

DECLARE cur CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
'
FROM
@table

OPEN cur

FETCH cur into @dynSQL
WHILE @@FETCH_STATUS = 0 
BEGIN
    exec(@dynSQL)
    print @dynSQL

    FETCH cur into @dynSQL
END
CLOSE cur
DEALLOCATE cur
---------------------



   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!

    truncate table your_table

   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!

---------------------
--ADD CONSTRAINT:

DECLARE cur2 CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
'
FROM
@table

OPEN cur2

FETCH cur2 into @dynSQL
WHILE @@FETCH_STATUS = 0 
BEGIN
    exec(@dynSQL)

    print @dynSQL

    FETCH cur2 into @dynSQL
END
CLOSE cur2
DEALLOCATE cur2

6

@denver_citizen ve @Peter Szanto'nun cevapları benim için pek işe yaramadı, ancak bunları hesaplamak için değiştirdim:

  1. Kompozit Tuşlar
  2. Silme ve Güncelleme Hakkında eylemleri
  3. Yeniden eklerken dizini kontrol etme
  4. Dbo dışındaki şemalar
  5. Aynı anda birden fazla tablo
DECLARE @Debug bit = 0;

-- List of tables to truncate
select
    SchemaName, Name
into #tables
from (values 
    ('schema', 'table')
    ,('schema2', 'table2')
) as X(SchemaName, Name)


BEGIN TRANSACTION TruncateTrans;

with foreignKeys AS (
     SELECT 
        SCHEMA_NAME(fk.schema_id) as SchemaName
        ,fk.Name as ConstraintName
        ,OBJECT_NAME(fk.parent_object_id) as TableName
        ,SCHEMA_NAME(t.SCHEMA_ID) as ReferencedSchemaName
        ,OBJECT_NAME(fk.referenced_object_id) as ReferencedTableName
        ,fc.constraint_column_id
        ,COL_NAME(fk.parent_object_id, fc.parent_column_id) AS ColumnName
        ,COL_NAME(fk.referenced_object_id, fc.referenced_column_id) as ReferencedColumnName
        ,fk.delete_referential_action_desc
        ,fk.update_referential_action_desc
    FROM sys.foreign_keys AS fk
        JOIN sys.foreign_key_columns AS fc
            ON fk.object_id = fc.constraint_object_id
        JOIN #tables tbl 
            ON OBJECT_NAME(fc.referenced_object_id) = tbl.Name
        JOIN sys.tables t on OBJECT_NAME(t.object_id) = tbl.Name 
            and SCHEMA_NAME(t.schema_id) = tbl.SchemaName
            and t.OBJECT_ID = fc.referenced_object_id
)



select
    quotename(fk.ConstraintName) AS ConstraintName
    ,quotename(fk.SchemaName) + '.' + quotename(fk.TableName) AS TableName
    ,quotename(fk.ReferencedSchemaName) + '.' + quotename(fk.ReferencedTableName) AS ReferencedTableName
    ,replace(fk.delete_referential_action_desc, '_', ' ') AS DeleteAction
    ,replace(fk.update_referential_action_desc, '_', ' ') AS UpdateAction
    ,STUFF((
        SELECT ',' + quotename(fk2.ColumnName)
        FROM foreignKeys fk2 
        WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
        ORDER BY fk2.constraint_column_id
        FOR XML PATH('')
    ),1,1,'') AS ColumnNames
    ,STUFF((
        SELECT ',' + quotename(fk2.ReferencedColumnName)
        FROM foreignKeys fk2 
        WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
        ORDER BY fk2.constraint_column_id
        FOR XML PATH('')
    ),1,1,'') AS ReferencedColumnNames
into #FKs
from foreignKeys fk
GROUP BY fk.SchemaName, fk.ConstraintName, fk.TableName, fk.ReferencedSchemaName, fk.ReferencedTableName, fk.delete_referential_action_desc, fk.update_referential_action_desc



-- Drop FKs
select 
    identity(int,1,1) as ID,
    'ALTER TABLE ' + fk.TableName + ' DROP CONSTRAINT ' + fk.ConstraintName AS script
into #scripts
from #FKs fk

-- Truncate 
insert into #scripts
select distinct 
    'TRUNCATE TABLE ' + quotename(tbl.SchemaName) + '.' + quotename(tbl.Name) AS script
from #tables tbl

-- Recreate
insert into #scripts
select 
    'ALTER TABLE ' + fk.TableName + 
    ' WITH CHECK ADD CONSTRAINT ' + fk.ConstraintName + 
    ' FOREIGN KEY ('+ fk.ColumnNames +')' + 
    ' REFERENCES ' + fk.ReferencedTableName +' ('+ fk.ReferencedColumnNames +')' +
    ' ON DELETE ' + fk.DeleteAction COLLATE Latin1_General_CI_AS_KS_WS + ' ON UPDATE ' + fk.UpdateAction COLLATE Latin1_General_CI_AS_KS_WS AS script
from #FKs fk


DECLARE @script nvarchar(MAX);

DECLARE curScripts CURSOR FOR 
    select script
    from #scripts
    order by ID

OPEN curScripts

WHILE 1=1 BEGIN
    FETCH NEXT FROM curScripts INTO @script
    IF @@FETCH_STATUS != 0 BREAK;

    print @script;
    IF @Debug = 0
        EXEC (@script);
END
CLOSE curScripts
DEALLOCATE curScripts


drop table #scripts
drop table #FKs
drop table #tables


COMMIT TRANSACTION TruncateTrans;

4

truncate benim için çalışmadı, silmek + reseed en iyi çıkış yoludur. Eğer silme + yeniden satış yapmak için çok sayıda tablo üzerinde yineleme yapmanız gereken bazılarınız varsa, kimlik sütunu olmayan bazı tablolarla ilgili sorunlarla karşılaşabilirsiniz, aşağıdaki kod denemeden önce kimlik sütununun var olup olmadığını kontrol eder yeniden tohumlamak

    EXEC ('DELETE FROM [schemaName].[tableName]')
    IF EXISTS (Select * from sys.identity_columns where object_name(object_id) = 'tableName')
    BEGIN
        EXEC ('DBCC CHECKIDENT ([schemaName.tableName], RESEED, 0)')
    END

4

Aşağıdaki yolları yazdım ve parametreleştirmeye çalıştım, böylece bunları Bir'de çalıştırabilir Query documentveya Onlarla kolayca faydalı olabilirsinizSP .

A) Sil

Eğer masa kayıtların değil milyonlarca Bu iş iyi ve herhangi Alter komutları vardır :

---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE @DbName AS NVARCHAR(30) = 'MyDb'         --< Db Name
DECLARE @Schema AS NVARCHAR(30) = 'dbo'          --< Schema
DECLARE @TableName AS NVARCHAR(30) = 'Book'      --< Table Name
------------------ /Just Fill Parameters Value ----------------

DECLARE @Query AS NVARCHAR(500) = 'Delete FROM ' + @TableName

EXECUTE sp_executesql @Query
SET @Query=@DbName+'.'+@Schema+'.'+@TableName
DBCC CHECKIDENT (@Query,RESEED, 0)
  • Yukarıdaki cevabımda , soruda bahsedilen sorunun çözülme yöntemi @ s15199d cevabına dayanmaktadır .

B) Kes

Eğer masa kayıtların milyonlarca ya da herhangi bir problemi yoktur Alter komutu sizin kodları, o zaman bu birini kullanın:

--   Book                               Student
--
--   |  BookId  | Field1 |              | StudentId |  BookId  |
--   ---------------------              ------------------------ 
--   |    1     |    A   |              |     2     |    1     |  
--   |    2     |    B   |              |     1     |    1     |
--   |    3     |    C   |              |     2     |    3     |  

---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE @DbName AS NVARCHAR(30) = 'MyDb'
DECLARE @Schema AS NVARCHAR(30) = 'dbo'
DECLARE @TableName_ToTruncate AS NVARCHAR(30) = 'Book'

DECLARE @TableName_OfOwnerOfConstraint AS NVARCHAR(30) = 'Student' --< Decelations About FK_Book_Constraint
DECLARE @Ref_ColumnName_In_TableName_ToTruncate AS NVARCHAR(30) = 'BookId' --< Decelations About FK_Book_Constraint
DECLARE @FK_ColumnName_In_TableOfOwnerOfConstraint AS NVARCHAR(30) = 'Fk_BookId' --< Decelations About FK_Book_Constraint
DECLARE @FK_ConstraintName AS NVARCHAR(30) = 'FK_Book_Constraint'                --< Decelations About FK_Book_Constraint
------------------ /Just Fill Parameters Value ----------------

DECLARE @Query AS NVARCHAR(2000)

SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' DROP CONSTRAINT '+@FK_ConstraintName
EXECUTE sp_executesql @Query

SET @Query= 'Truncate Table '+ @TableName_ToTruncate
EXECUTE sp_executesql @Query

SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' ADD CONSTRAINT '+@FK_ConstraintName+' FOREIGN KEY('+@FK_ColumnName_In_TableOfOwnerOfConstraint+') REFERENCES '+@TableName_ToTruncate+'('+@Ref_ColumnName_In_TableName_ToTruncate+')'
EXECUTE sp_executesql @Query
  • Yukarıdaki cevabımda , soruda bahsedilen sorunun çözülme yöntemi @LauroWolffValenteSobrinho cevabına dayanmaktadır .

  • Birden fazla CONSTRAINT varsa, benim gibi kodlarını yukarıdaki sorguya eklemelisiniz

  • Ayrıca kısıtlamayı etkinleştirmek için yukarıdaki kod tabanını @SerjSagan yanıtını değiştirebilirsiniz.


3

Bu sorunun çözümü benim. PK'yi değiştirmek için kullandım, ama aynı fikir. Umarım bu yararlı olur)

PRINT 'Script starts'

DECLARE @foreign_key_name varchar(255)
DECLARE @keycnt int
DECLARE @foreign_table varchar(255)
DECLARE @foreign_column_1 varchar(255)
DECLARE @foreign_column_2 varchar(255)
DECLARE @primary_table varchar(255)
DECLARE @primary_column_1 varchar(255)
DECLARE @primary_column_2 varchar(255)
DECLARE @TablN varchar(255)

-->> Type the primary table name
SET @TablN = ''
---------------------------------------------------------------------------------------    ------------------------------
--Here will be created the temporary table with all reference FKs
---------------------------------------------------------------------------------------------------------------------
PRINT 'Creating the temporary table'
select cast(f.name  as varchar(255)) as foreign_key_name
    , r.keycnt
    , cast(c.name as  varchar(255)) as foreign_table
    , cast(fc.name as varchar(255)) as  foreign_column_1
    , cast(fc2.name as varchar(255)) as foreign_column_2
    , cast(p.name as varchar(255)) as primary_table
    , cast(rc.name as varchar(255))  as primary_column_1
    , cast(rc2.name as varchar(255)) as  primary_column_2
    into #ConTab
    from sysobjects f
    inner join sysobjects c on  f.parent_obj = c.id 
    inner join sysreferences r on f.id =  r.constid
    inner join sysobjects p on r.rkeyid = p.id
    inner  join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
    inner  join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
    left join  syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
    left join  syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
    where f.type =  'F' and p.name = @TablN
 ORDER BY cast(p.name as varchar(255))
---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will drop all reference FKs
---------------------------------------------------------------------------------------------------------------------
DECLARE @CURSOR CURSOR
/*Fill in cursor*/

PRINT 'Cursor 1 starting. All refernce FK will be droped'

SET @CURSOR  = CURSOR SCROLL
FOR
select foreign_key_name
    , keycnt
    , foreign_table
    , foreign_column_1
    , foreign_column_2
    , primary_table
    , primary_column_1
    , primary_column_2
    from #ConTab

OPEN @CURSOR

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table,         @foreign_column_1, @foreign_column_2, 
                        @primary_table, @primary_column_1, @primary_column_2

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC ('ALTER TABLE ['+@foreign_table+'] DROP CONSTRAINT ['+@foreign_key_name+']')

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2
END
CLOSE @CURSOR
PRINT 'Cursor 1 finished work'
---------------------------------------------------------------------------------------------------------------------
--Here you should provide the chainging script for the primary table
---------------------------------------------------------------------------------------------------------------------

PRINT 'Altering primary table begin'

TRUNCATE TABLE table_name

PRINT 'Altering finished'

---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will add again all reference FKs
--------------------------------------------------------------------------------------------------------------------

PRINT 'Cursor 2 starting. All refernce FK will added'
SET @CURSOR  = CURSOR SCROLL
FOR
select foreign_key_name
    , keycnt
    , foreign_table
    , foreign_column_1
    , foreign_column_2
    , primary_table
    , primary_column_1
    , primary_column_2
    from #ConTab

OPEN @CURSOR

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC ('ALTER TABLE [' +@foreign_table+ '] WITH NOCHECK ADD  CONSTRAINT [' +@foreign_key_name+ '] FOREIGN KEY(['+@foreign_column_1+'])
        REFERENCES [' +@primary_table+'] (['+@primary_column_1+'])')

    EXEC ('ALTER TABLE [' +@foreign_table+ '] CHECK CONSTRAINT [' +@foreign_key_name+']')

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2
END
CLOSE @CURSOR
PRINT 'Cursor 2 finished work'
---------------------------------------------------------------------------------------------------------------------
PRINT 'Temporary table droping'
drop table #ConTab
PRINT 'Finish'

3

İçin MS SQL, yeni sürümleri, en azından, sadece böyle koduyla, kısıtlarını devre dışı bırakabilirsiniz:

ALTER TABLE Orders
NOCHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO

TRUNCATE TABLE Customers
GO

ALTER TABLE Orders
WITH CHECK CHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO

Bence bunun işe yaramadığını tespit ettik? Belki daha yeni sürümler için geçerlidir?
Coops

2
Fwiw, bu OP'nin sürümünde (2005) çalışmıyor ve ayrıca halefinde (MSSQL2008) çalışmıyor.
CB

3

Aşağıdakiler benim için FK kısıtlamalarıyla bile çalışır ve aşağıdaki yanıtları yalnızca belirtilen tabloları bırakmak için birleştirir :


USE [YourDB];

DECLARE @TransactionName varchar(20) = 'stopdropandroll';

BEGIN TRAN @TransactionName;
set xact_abort on; /* automatic rollback https://stackoverflow.com/a/1749788/1037948 */
    -- ===== DO WORK // =====

    -- dynamic sql placeholder
    DECLARE @SQL varchar(300);

    -- LOOP: https://stackoverflow.com/a/10031803/1037948
    -- list of things to loop
    DECLARE @delim char = ';';
    DECLARE @foreach varchar(MAX) = 'Table;Names;Separated;By;Delimiter' + @delim + 'AnotherName' + @delim + 'Still Another';
    DECLARE @token varchar(MAX);
    WHILE len(@foreach) > 0
    BEGIN
        -- set current loop token
        SET @token = left(@foreach, charindex(@delim, @foreach+@delim)-1)
        -- ======= DO WORK // ===========

        -- dynamic sql (parentheses are required): https://stackoverflow.com/a/989111/1037948
        SET @SQL = 'DELETE FROM [' + @token + ']; DBCC CHECKIDENT (''' + @token + ''',RESEED, 0);'; -- https://stackoverflow.com/a/11784890
        PRINT @SQL;
        EXEC (@SQL);

        -- ======= // END WORK ===========
        -- continue loop, chopping off token
        SET @foreach = stuff(@foreach, 1, charindex(@delim, @foreach+@delim), '')
    END

    -- ===== // END WORK =====
-- review and commit
SELECT @@TRANCOUNT as TransactionsPerformed, @@ROWCOUNT as LastRowsChanged;
COMMIT TRAN @TransactionName;

Not:

Ben hala tablolar onları silmek istediğiniz sırayla (yani önce bağımlılıkları öldürmek) ilan yardımcı olur düşünüyorum. Bu yanıtta görüldüğü gibi , belirli adları döngü yerine tüm tabloları

EXEC sp_MSForEachTable 'DELETE FROM ?; DBCC CHECKIDENT (''?'',RESEED, 0);';

Herkes Yabancı Anahtarlarınız olduğunda çalışmadığını belirttiğinden diğer komut dosyalarına gerçekten denemedim. Bu yüzden denedim ve bu benim için hile yaptı.
Vivendi

1
DELETE ile aynı değildirTRUNCATE . Bu işlem günlüklerinizi dolduracaktır.
Dan Bechard

@ Dan, muhtemelen iyi bir nokta; Bahsettiğim gibi, buradaki diğer cevapları birleştirdim ...
drzaus

@drzaus Küçük / orta ölçekli tablolar için iyi çalışır, ancak sabit diski dolduran işlem günlüğünü dolduran bir silme komutu nedeniyle çevrimdışı bir üretim SQL sunucum vardı. En azından, büyük bir tabloda denemeden önce işlem günlüklerinizin maksimum boyutta olduğundan emin olun.
Dan Bechard

2

Bu cevapların hiçbiri benim durumumdaki gibi çalışmadıysa, bunu yapın:

  1. Düşme kısıtlamaları
  2. Boş değerlere izin vermek için tüm değerleri ayarlama
  3. Tabloyu kes
  4. Bırakılan kısıtlamaları ekleyin.

İyi şanslar!


bu konuda herhangi bir sql örnek?
Kiquenet

2

Otomatik artırmayı silin ve sıfırlayın:

delete from tablename;

sonra

ALTER TABLE tablename AUTO_INCREMENT = 1;

Teşekkürler, bu iyi çalıştı.
Bay Polywhirl

1

Tek yol, kesmeyi yapmadan önce yabancı anahtarları bırakmaktır. Verileri kırptıktan sonra, dizinleri yeniden oluşturmanız gerekir.

Aşağıdaki komut dosyası, tüm yabancı anahtar kısıtlamalarını bırakmak için gerekli SQL'i oluşturur.

DECLARE @drop NVARCHAR(MAX) = N'';

SELECT @drop += N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
    + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS ct
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id];

SELECT @drop

Sonra, aşağıdaki komut dosyası yabancı anahtarları yeniden oluşturmak için gerekli SQL'i oluşturur.

DECLARE @create NVARCHAR(MAX) = N'';

SELECT @create += N'
ALTER TABLE ' 
   + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
   + ' ADD CONSTRAINT ' + QUOTENAME(fk.name) 
   + ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the columns in the constraint table
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.parent_column_id = c.column_id
    AND fkc.parent_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
  + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
  + '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the referenced columns
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.referenced_column_id = c.column_id
    AND fkc.referenced_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
  ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs 
  ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;

SELECT @create

Tüm yabancı anahtarları bırakmak için oluşturulan komut dosyasını çalıştırın, tabloları kısaltın ve ardından tüm yabancı anahtarları yeniden oluşturmak için oluşturulan komut dosyasını çalıştırın.

Sorgular buradan alınır .


0

SSMS'de Anahtarı gösteren Diyagram açıktı. Anahtarı sildikten ve dosyayı kısalttıktan sonra yeniledim, daha sonra Şemaya tekrar odaklandım ve bir Kimlik kutusunu temizleyip geri yükleyerek bir güncelleme oluşturdum. Diyagramı kaydetmek, "Çalışırken veritabanında değişiklikler yapıldı" iletişim kutusundan bir Kaydet iletişim kutusu getirdi, Evet'i tıklattığınızda Anahtar geri yüklendi ve Diyagramdaki kilitli kopyadan geri yüklendi.


0

Bunu herhangi bir sıklıkta yapıyorsanız, hatta bir programda bile olsa, kesinlikle, kesinlikle bir DML ifadesi kullanmam. İşlem günlüğüne yazma maliyeti çok yüksektir ve tüm veritabanınıSIMPLE kesmek kurtarma moduna saçmadır.

En iyi yol, ne yazık ki zor ya da zahmetli yol. Olmak:

  • Düşme kısıtlamaları
  • Tabloyu kes
  • Kısıtlamaları yeniden oluştur

Bunu yapma sürecim aşağıdaki adımları içerir:

  1. SSMS'de söz konusu tabloya sağ tıklayın ve Bağımlılıkları Görüntüle'yi seçin.
  2. Referans verilen tabloları not edin (varsa)
  3. Nesne gezginine geri dönün, Keys düğümünü genişletin ve yabancı anahtarları not edin (varsa)
  4. Komut dosyasını başlat (bırak / kes / yeniden oluştur)

Bu yapıdaki Komut gereken a içinde yapılabilir begin tranve commit tranbloğun.


-3

Önce alt tablodaki kısıtlamaları devre dışı bıraktığınız sürece, bir alt tabloda yabancı anahtar kısıtlamaları olan bir ana tablodaki TRUNCATE tablosunu kullanabileceğinizi gördüm . Örneğin

Yabancı anahtar CONSTRAINT child_par_ref alt tabloda, referanslar PARENT_TABLE

ALTER TABLE CHILD_TABLE DISABLE CONSTRAINT child_par_ref;
TRUNCATE TABLE CHILD_TABLE;
TRUNCATE TABLE PARENT_TABLE;
ALTER TABLE CHILD_TABLE ENABLE CONSTRAINT child_par_ref;

1
Bu, ALTER TABLE için geçerli bir SQL Server sözdizimi değildir. {ENABLE | DISABLE (DEVRE DIŞI)} CONSTRAINT. Bkz: msdn.microsoft.com/en-us/library/ms190273.aspx
jason_ruz

-3

En kolay yol:
1 - phpmyadmin girin
2 - Sol sütundaki tablo adını
tıklayın 3 - İşlem'i tıklayın (üst menü)
4 - "Masayı boşaltın (TRUNCATE)
5 - Devre dışı bırak kutusu" Yabancı anahtar kontrollerini etkinleştir "
6 - Tamamlandı !

Resim eğitimine bağlantı
Eğitimi: http://www.imageno.com/wz6gv1wuqajrpic.html
(Üzgünüz, buraya resim yüklemek için yeterli itibarım yok: P)


2
OP, MSSQL'i belirtti. MySQL'e özel bir cevap verdiniz.
yeniden düzenlendi

-4

Deneyebilirsin DELETE FROM <your table >;.

Sunucu size kısıtlamanın ve tablonun adını gösterir ve bu tabloyu silerek ihtiyacınız olanları silebilirsiniz.


6
Sorudaki ikinci ifadesini okuyun. Bunu yapabileceğini biliyor, ama istediği bu değil
renanleandrof

-7
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE table1;
TRUNCATE table2;
SET FOREIGN_KEY_CHECKS=1;

başvuru - kısaltılmış yabancı anahtar kısıtlı tablo

MYSQL'de benim için çalışmak


1
Belirtilen sürüm dışında, bununla ilgili başka bir şey var mı? Kullanılması veya tamamen önlenmesi tavsiye edilir mi?
Andy Ibanez

1
@AndyIbanez MySQL, MSSQL'den farklı bir versiyon değil, MSSQL'den tamamen farklı bir üründür.
Dan Bechard

1
doğru cevap Herkesin neden negatif verdiğini bilmiyorum
sunil
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.