Tüm referans yabancı anahtarlara kademeli birincil anahtar güncellemesi


11

Birincil anahtar sütun değerini, güncelleştirmeyi referans alan tüm yabancı anahtarlar arasında basamaklayarak güncellemek mümkün müdür?

# EDIT 1: followinq sorgusunu çalıştırdığımda

select * from sys.foreign_keys where referenced_object_id=OBJECT_ID('myTable') 

, Update_referential_action değerinin 0 olarak ayarlandığını görüyorum. Bu nedenle, birincil anahtar sütunlarımı güncelledikten sonra HİÇBİR EYLEM alınmaz. Yabancı anahtarları CASCADE GÜNCELLEMESİNDE yapmak için nasıl güncelleyebilirim ?

# EDIT 2:
Şemanızdaki tüm yabancı anahtarların oluşturulmasını veya bırakılmasını komut dosyası oluşturmak için aşağıdaki komut dosyasını çalıştırın ( buradan alınır )

DECLARE @schema_name sysname;

DECLARE @table_name sysname;

DECLARE @constraint_name sysname;

DECLARE @constraint_object_id int;

DECLARE @referenced_object_name sysname;

DECLARE @is_disabled bit;

DECLARE @is_not_for_replication bit;

DECLARE @is_not_trusted bit;

DECLARE @delete_referential_action tinyint;

DECLARE @update_referential_action tinyint;

DECLARE @tsql nvarchar(4000);

DECLARE @tsql2 nvarchar(4000);

DECLARE @fkCol sysname;

DECLARE @pkCol sysname;

DECLARE @col1 bit;

DECLARE @action char(6);  

DECLARE @referenced_schema_name sysname;



DECLARE FKcursor CURSOR FOR

     select OBJECT_SCHEMA_NAME(parent_object_id)

         , OBJECT_NAME(parent_object_id), name, OBJECT_NAME(referenced_object_id)

         , object_id

         , is_disabled, is_not_for_replication, is_not_trusted

         , delete_referential_action, update_referential_action, OBJECT_SCHEMA_NAME(referenced_object_id)

    from sys.foreign_keys

    order by 1,2;

OPEN FKcursor;

FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name

    , @referenced_object_name, @constraint_object_id

    , @is_disabled, @is_not_for_replication, @is_not_trusted

    , @delete_referential_action, @update_referential_action, @referenced_schema_name;

WHILE @@FETCH_STATUS = 0

BEGIN



      IF @action <> 'CREATE'

        SET @tsql = 'ALTER TABLE '

                  + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)

                  + ' DROP CONSTRAINT ' + QUOTENAME(@constraint_name) + ';';

    ELSE

        BEGIN

        SET @tsql = 'ALTER TABLE '

                  + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)

                  + CASE @is_not_trusted

                        WHEN 0 THEN ' WITH CHECK '

                        ELSE ' WITH NOCHECK '

                    END

                  + ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name)

                  + ' FOREIGN KEY (';

        SET @tsql2 = '';

        DECLARE ColumnCursor CURSOR FOR

            select COL_NAME(fk.parent_object_id, fkc.parent_column_id)

                 , COL_NAME(fk.referenced_object_id, fkc.referenced_column_id)

            from sys.foreign_keys fk

            inner join sys.foreign_key_columns fkc

            on fk.object_id = fkc.constraint_object_id

            where fkc.constraint_object_id = @constraint_object_id

            order by fkc.constraint_column_id;

        OPEN ColumnCursor;

        SET @col1 = 1;

        FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;

        WHILE @@FETCH_STATUS = 0

        BEGIN

            IF (@col1 = 1)

                SET @col1 = 0;

            ELSE

            BEGIN

                SET @tsql = @tsql + ',';

                SET @tsql2 = @tsql2 + ',';

            END;

            SET @tsql = @tsql + QUOTENAME(@fkCol);

            SET @tsql2 = @tsql2 + QUOTENAME(@pkCol);

            FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;

        END;

        CLOSE ColumnCursor;

        DEALLOCATE ColumnCursor;

       SET @tsql = @tsql + ' ) REFERENCES ' + QUOTENAME(@referenced_schema_name) + '.' + QUOTENAME(@referenced_object_name)

                  + ' (' + @tsql2 + ')';

        SET @tsql = @tsql

                  + ' ON UPDATE ' + CASE @update_referential_action

                                        WHEN 0 THEN 'NO ACTION '

                                        WHEN 1 THEN 'CASCADE '

                                        WHEN 2 THEN 'SET NULL '

                                        ELSE 'SET DEFAULT '

                                    END

                  + ' ON DELETE ' + CASE @delete_referential_action

                                        WHEN 0 THEN 'NO ACTION '

                                        WHEN 1 THEN 'CASCADE '

                                        WHEN 2 THEN 'SET NULL '

                                        ELSE 'SET DEFAULT '

                                    END

                  + CASE @is_not_for_replication

                        WHEN 1 THEN ' NOT FOR REPLICATION '

                        ELSE ''

                    END

                  + ';';

        END;

    PRINT @tsql;

    IF @action = 'CREATE'

        BEGIN

        SET @tsql = 'ALTER TABLE '

                  + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)

                  + CASE @is_disabled

                        WHEN 0 THEN ' CHECK '

                        ELSE ' NOCHECK '

                    END

                  + 'CONSTRAINT ' + QUOTENAME(@constraint_name)

                  + ';';

        PRINT @tsql;

        END;

    FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name

        , @referenced_object_name, @constraint_object_id

        , @is_disabled, @is_not_for_replication, @is_not_trusted

        , @delete_referential_action, @update_referential_action, @referenced_schema_name;

END;

CLOSE FKcursor;

DEALLOCATE FKcursor;  

DROP yabancı anahtarlar komut dosyasını oluşturmak için, @action değerini bildirim yan tümcesinde 'DROP' değerine eşit olacak şekilde değiştirin:

DECLARE @action char(6) = 'DROP';

Yanıtlar:


9

Yabancı Anahtar kısıtlamalarını tanımladıysanız ON UPDATE CASCADE, değiştirilen Birincil Anahtar değeri, bu kısıtlamaya sahip tüm Yabancı Anahtarlara kadar basamaklandırılmalıdır.

Eğer yoksa ON UPDATE CASCADEkısıtlamayı, o zaman güncellemeyi tamamlamak için komut dosyaları oluşturmak gerek olacaktır.

DÜZENLEME: ON UPDATE CASCADEKısıtlama olmadığından , ancak bu kurulumu yapmak istediğiniz için, biraz iş var. SQL Server, kısıtların yeni bir ayara değiştirilmesini desteklemez.

PK tablosuna FK kısıtlaması olan her tabloyu yinelemek gerekir. FK'li her masa için:

  1. ALTER TABLE, mevcut FK kısıtlamasını düşürür.
  2. Söz konusu FK için ON UPDATE CASCADE kısıtlamasını oluşturmak için tekrar ALTER TABLE.

Bu biraz çaba gerektirir, ancak kısıtlamanızın davanıza uygun şekilde ayarlanmasına neden olur.

DÜZENLEME 2: İhtiyacınız olan bilgiler sys.foreign_keys dizininde bulunur. İhtiyacınız olan tüm bilgileri almak için bu tablodan seçim yapabilirsiniz.

John Paul Cook'tan bir yazı burada bulunabilir:

( http://social.technet.microsoft.com/wiki/contents/articles/2958.script-to-create-all-foreign-keys.aspx )

Bu kod bırakılır ve bir veritabanında TÜM FK kısıtlamaları oluşturur. Bundan yalnızca veritabanınızda olmasını istediğiniz değişiklikleri yapabilmeniz gerekir.


daha fazla bilgi için düzenlememe bakın
mounaim

Tüm yabancı anahtarları @RLF nasıl yazacağınızı biliyor musunuz?
mounaim

@mounaim - Komut dosyasını oluşturma hakkında bir notla güncellendi.
RLF

Aynı şey üzerinde çalışıyordum ve aynı bağlantı benim düzenleme görmek @RLF
mounaim

1
DBA SE'de kod bloklarını buraya eklemek daha iyidir çünkü diğer web sitelerine bağlantılar daha sonra
kesilebilir

4

Emin olabilirsin. ON UPDATE CASCADEaradığınız şey bu.

İşte nasıl yapılır: http://sqlandme.com/2011/08/08/sql-server-how-to-cascade-updates-and-deletes-to-related-tables/

Temel olarak, PK'yi değiştirdiğinizde, kademeli dışarı çıkacak ve ona başvuran tüm FK'leri güncelleyecektir. Bu, sizin yaptığınız gibi, CREATEifadenizde yapılabilir.CASCADE DELETE

Bunu yaparken şeylere dikkat edin, çünkü anladığım kadarıyla CASCADE aslında sahne arkasında yalıtım seviyesinde SERIALIZABLE(normalde SQL READ COMMITTEDvarsayılan olarak çalışır ) çalışır, bu nedenle herhangi bir engelleme sorununa dikkat edin.

Yalıtım seviyeleri hakkında ek bilgi bu makalede bulunabilir: http://msdn.microsoft.com/en-us/library/ms173763.aspx


3

Tüm yabancı anahtarları CASCADE UPDATE olarak tanımlayın

Bunu yapmadıysanız, yapmanız gerekir

  1. Yeni birincil anahtarla yeni bir satır oluşturma
  2. Tüm alt tabloları güncelle
  3. Eski satırı kaldır

.. tabii bir işlemde ve başarısız olabilecek diğer kısıtlamalara dikkat etmek


teşekkürler @gbn. Yabancı anahtarlarımı güncellemek mümkün mü yoksa sadece bırakıp ON CASCADE UPDATE yan tümcesiyle yeniden oluşturmam gerekiyor mu?
mounaim

Bırak ve yeniden
oluştur
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.