सभी मुख्य विदेशी कुंजियों को कैस्केड प्राथमिक कुंजी अपडेट


11

क्या यह संदर्भित करने वाले सभी विदेशी कुंजियों के बीच अपडेट को कैस्केडिंग करने के साथ प्राथमिक कुंजी स्तंभ मान अपडेट करना संभव है?

# EDIT 1: जब मैं फॉलोइनक क्वेरी चलाता हूं

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

, मैं देख रहा हूं कि update_referential_action 0. पर सेट है। इस प्रकार मेरे प्राथमिक कुंजी कॉलम को अपडेट करने के बाद NO ACTION लिया जाता है। मैं उन्हें CASDADE UPDATE पर बनाने के लिए विदेशी कुंजियों को कैसे अपडेट कर सकता हूं ?

# EDIT 2:
अपने स्कीमा में सभी विदेशी कुंजियों को बनाने या छोड़ने की स्क्रिप्ट के लिए निम्नलिखित स्क्रिप्ट चलाएं ( यहां से ली गई हैं )

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 विदेशी कुंजी स्क्रिप्ट उत्पन्न करने के लिए, घोषणा खंड में 'DROP' के बराबर होने के लिए @ वैल्यू को संशोधित करें:

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

जवाबों:


9

यदि आपने विदेशी कुंजी बाधाओं को परिभाषित किया है, ON UPDATE CASCADEतो प्राथमिक कुंजी मान जो बदल गया था, उस बाधा के साथ सभी विदेशी कुंजी को नीचे करना चाहिए।

यदि आपके पास ON UPDATE CASCADEबाधा नहीं है , तो आपको अपडेट पूरा करने के लिए स्क्रिप्ट बनाने की आवश्यकता होगी।

संपादित करें: चूंकि आपके पास ON UPDATE CASCADEबाधा नहीं है , लेकिन आप चाहते हैं कि यह स्थापित हो, यह थोड़ा काम है। SQL सर्वर एक नई सेटिंग में बाधाओं को बदलने का समर्थन नहीं करता है।

प्रत्येक तालिका के माध्यम से पुनरावृति करना आवश्यक है जिसमें पीके तालिका में एक एफके बाधा है। FK के साथ प्रत्येक तालिका के लिए:

  1. मौजूदा FK बाधा को गिराने में सक्षम करें।
  2. प्रश्न में FK के लिए OND UPDATE CASCADE बाधा बनाने के लिए फिर से लिखें।

इसके लिए थोड़ा प्रयास करना पड़ता है, लेकिन इसके परिणामस्वरूप आपके अवरोध को आपके मामले के लिए ठीक से निर्धारित किया जाएगा।

EDIT 2: आपके लिए आवश्यक जानकारी sys.foreign_keys में पाई जाती है। आप सभी आवश्यक जानकारी प्राप्त करने के लिए उस तालिका से चयन कर सकते हैं।

जॉन पॉल कुक की एक पोस्ट यहाँ मिल सकती है:

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

यह कोड एक डेटाबेस में सभी FK बाधाओं को छोड़ देगा और बनाएगा। आपको अपने डेटाबेस में केवल वही परिवर्तन करने में सक्षम होना चाहिए जो आप चाहते हैं।


अधिक जानकारी के लिए मेरा संपादन देखें
मौनिम

क्या आप जानते हैं कि सभी विदेशी कुंजी @RLF को कैसे स्क्रिप्ट किया जाता है?
मौनिम

@mounaim - स्क्रिप्ट बनाने पर एक नोट के साथ अपडेट किया गया।
RLF

मैं एक ही चीज़ पर काम कर रहा था और उसी लिंक पर मेरा संपादन देखें @RLF
mounaim

1
डीबीए एसई पर कोड ब्लॉक को शामिल करना बेहतर है क्योंकि अन्य वेबसाइटों के लिंक बाद में टूट सकते हैं :)
मौनिम

4

आपको यकीन है। ON UPDATE CASCADEवह है जो आप ढूंढ रहे हैं।

यहाँ एक छोटा सा तरीका है: http://sqlandme.com/2011/08/08/sql-server-how-to-cascade-updates-and-deletes-to-related-tables/

मूल रूप से, जब आप पीके को संशोधित करते हैं, तो कैस्केड बाहर निकल जाएगा और इसे संदर्भित सभी FK को अपडेट करेगा। यह आपके CREATEबयान में किया जा सकता है , जैसे कि आप कर रहे थेCASCADE DELETE

जब आप ऐसा करते हैं तो चीजों पर नज़र रखें, क्योंकि मैं इसे समझता हूं, CASCADE वास्तव में अलगाव के स्तर पर चलता है SERIALIZABLE(सामान्य रूप से, READ COMMITTEDडिफ़ॉल्ट रूप से SQL चलाता है ) तो किसी भी अवरुद्ध मुद्दों के लिए देखें।

अलगाव के स्तर पर अतिरिक्त जानकारी इस लेख में पाई जा सकती है: http://msdn.microsoft.com/en-us/library/ms173763.aspx


3

CASCADE UPDATE के रूप में सभी विदेशी कुंजियों को परिभाषित करें

अगर आपने ऐसा नहीं किया है, तो आपको करना पड़ेगा

  1. नई प्राथमिक कुंजी के साथ एक नई पंक्ति बनाएँ
  2. सभी चाइल्ड टेबल को अपडेट करें
  3. पुरानी पंक्ति निकालें

.. निश्चित रूप से लेनदेन में और अन्य बाधाओं के लिए बाहर देखना जो विफल हो सकते हैं


साभार @ जीबीएन। क्या मेरी विदेशी कुंजियों को अपडेट करना संभव है या मुझे केवल उन्हें छोड़ना होगा और उन्हें ऑन-केस अपडेट क्लॉज़ के साथ फिर से बनाना होगा?
मुनीम डेम

ड्रॉप और रीक्रिएट ...
gbn 15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.