วิธีการเพิ่ม 'ON DELETE CASCADE' ในคำสั่ง ALTER TABLE


130

ฉันมีข้อ จำกัด ของคีย์ต่างประเทศในตารางของฉันฉันต้องการเพิ่ม ON DELETE CASCADE ลงไป

ฉันได้ลองสิ่งนี้:

แก้ไขตาราง child_table_name
  แก้ไขข้อ จำกัด fk_name
  คีย์ต่างประเทศ (child_column_name)
  อ้างอิง parent_table_name (parent_column_name) ในการลบ cascade;

ไม่ทำงาน

แก้ไข: มี
คีย์ต่างประเทศอยู่แล้วมีข้อมูลในคอลัมน์คีย์ต่างประเทศ

ข้อความแสดงข้อผิดพลาดที่ฉันได้รับหลังจากดำเนินการคำสั่ง:

ORA-02275: ข้อ จำกัด ในการอ้างอิงดังกล่าวมีอยู่แล้วในตาราง

มีปัญหาอะไร? คำสั่งถูกปฏิเสธการลบไม่เกิดขึ้น ..
Thorsten

คำตอบ:


162

คุณไม่สามารถเพิ่มON DELETE CASCADEข้อ จำกัด ที่มีอยู่แล้วได้ คุณจะต้องdropและcreateกลับข้อ จำกัด เอกสารที่แสดงให้เห็นว่าMODIFY CONSTRAINTข้อเท่านั้นที่สามารถปรับเปลี่ยนสถานะของข้อ จำกัด (เช่น: ENABLED/DISABLED... )


86

ครั้งแรกdropที่สำคัญต่างประเทศของคุณและพยายามคำสั่งดังกล่าวของคุณใส่แทนadd constraint modify constraintตอนนี้เป็นคำสั่ง:

ALTER TABLE child_table_name 
  ADD CONSTRAINT fk_name 
  FOREIGN KEY (child_column_name) 
  REFERENCES parent_table_name(parent_column_name) 
  ON DELETE CASCADE;

24
เขาให้รหัสทั้งหมดแก่เรามันเป็นข้อได้เปรียบสำหรับคนที่ไม่มีส่วนเกี่ยวข้องกับ postgres
Matthis Kohli

1
@WiiMaxx ผู้ก่อตั้งผู้ชายขี้หึง lol คำตอบนี้สำคัญกว่าคำตอบแรกเนื่องจากให้รหัสด้วย ..
ฉันเป็นคนโง่ที่สุด

11

PL * SQL นี้จะเขียนไปยัง DBMS_OUTPUT สคริปต์ที่จะทิ้งข้อ จำกัด แต่ละข้อที่ไม่มีการลบน้ำตกและสร้างขึ้นใหม่ด้วยการลบ cascade

หมายเหตุ: การรันเอาต์พุตของสคริปต์นี้ถือเป็นความเสี่ยงของคุณเอง ควรอ่านสคริปต์ผลลัพธ์และแก้ไขก่อนที่จะดำเนินการ

DECLARE
      CURSOR consCols (theCons VARCHAR2, theOwner VARCHAR2) IS
        select * from user_cons_columns
            where constraint_name = theCons and owner = theOwner
            order by position;
      firstCol BOOLEAN := TRUE;
    begin
        -- For each constraint
        FOR cons IN (select * from user_constraints
            where delete_rule = 'NO ACTION'
            and constraint_name not like '%MODIFIED_BY_FK'  -- these constraints we do not want delete cascade
            and constraint_name not like '%CREATED_BY_FK'
            order by table_name)
        LOOP
            -- Drop the constraint
            DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' DROP CONSTRAINT ' || cons.CONSTRAINT_NAME || ';');
            -- Re-create the constraint
            DBMS_OUTPUT.PUT('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' ADD CONSTRAINT ' || cons.CONSTRAINT_NAME 
                                        || ' FOREIGN KEY (');
            firstCol := TRUE;
            -- For each referencing column
            FOR consCol IN consCols(cons.CONSTRAINT_NAME, cons.OWNER)
            LOOP
                IF(firstCol) THEN
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT(') REFERENCES ');

            firstCol := TRUE;
            -- For each referenced column
            FOR consCol IN consCols(cons.R_CONSTRAINT_NAME, cons.R_OWNER)
            LOOP
                IF(firstCol) THEN
                    DBMS_OUTPUT.PUT(consCol.OWNER);
                    DBMS_OUTPUT.PUT('.');
                    DBMS_OUTPUT.PUT(consCol.TABLE_NAME);        -- This seems a bit of a kluge.
                    DBMS_OUTPUT.PUT(' (');
                    firstCol := FALSE;
                ELSE
                    DBMS_OUTPUT.PUT(',');
                END IF;
                DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
            END LOOP;                                    

            DBMS_OUTPUT.PUT_LINE(')  ON DELETE CASCADE  ENABLE VALIDATE;');
        END LOOP;
    end;

11

ตามที่อธิบายไว้ก่อนหน้านี้:

ALTER TABLE TABLEName
drop CONSTRAINT FK_CONSTRAINTNAME;

ALTER TABLE TABLENAME
ADD CONSTRAINT FK_CONSTRAINTNAME
    FOREIGN KEY (FId)
    REFERENCES OTHERTABLE
        (Id)
    ON DELETE CASCADE ON UPDATE NO ACTION;

ดังที่คุณเห็นคำสั่งเหล่านี้ต้องแยกจากกันก่อนอื่นจึงวางแล้วเพิ่ม


สิ่งนี้ไม่ถูกต้องสำหรับ Oracle
a_horse_with_no_name

เพิ่งทดสอบใน SqlServer แต่เป็นไปได้ที่คุณจะต้องgoใช้เซมิโคลอนเช่นเดียวกับใน postgres และ SqlServer เอง แต่รหัสหลักที่เหลือเป็นมาตรฐาน sql ทดสอบกับเซมิโคลอนฉันเพิ่งเปลี่ยน
David Silva-Barrera

[หรือ]ไม่ถูกต้องใน SQL มาตรฐาน (และ Oracle) นอกจากนี้ Oracle ยังไม่สนับสนุน on updateประโยคสำหรับคีย์นอก
a_horse_with_no_name

คุณถูกต้อง[ ]เฉพาะ SqlServer ฉันจะทำความสะอาดให้มากขึ้น เกี่ยวกับon updateฉันไม่สามารถพูดอะไรเกี่ยวกับ.
David Silva-Barrera

11

คำตอบสำหรับผู้ใช้ MYSQL:

ALTER TABLE ChildTableName 
DROP FOREIGN KEY `fk_table`;
ALTER TABLE ChildTableName 
ADD CONSTRAINT `fk_t1_t2_tt`
  FOREIGN KEY (`parentTable`)
  REFERENCES parentTable (`columnName`)
  ON DELETE CASCADE
  ON UPDATE CASCADE;

ยินดีต้อนรับสู่ StackOverflow โปรดเรียนรู้เกี่ยวกับการจัดรูปแบบรหัสในstackoverflow.com/editing-help ฉันแก้ไขโค้ดเพื่อให้คุณอ่านได้ง่ายขึ้น
Adrian W

3

สำหรับใครก็ตามที่ใช้ MySQL:

ถ้าคุณมุ่งหน้าเข้าไปในของPHPMYADMINหน้าเว็บและนำทางไปยังตารางที่มีคีย์ต่างประเทศที่คุณต้องการที่จะปรับปรุงสิ่งที่คุณต้องทำคือการคลิกRelational view ที่ตั้งอยู่ในStructureแท็บและเปลี่ยนการเลือกตัวเลือกเมนูOn deleteCascade

ภาพด้านล่าง:

ป้อนคำอธิบายภาพที่นี่


OP มาจากปี 2009 มีการติดแท็กคำถามของ Oracle และ PHPMYADMIN เป็นส่วนประกอบซอฟต์แวร์ของบุคคลที่สามสำหรับ MySQL
vegatripy

7
จริงที่สุด. แต่ฉัน Googled สำหรับคำถามนี้อยากรู้วิธีทำใน MySQL และ Google ก็พาฉันมาที่นี่ ใช่คำถามนี้ถูกแท็กด้วย Oracle ดังนั้นคำตอบนี้จึงไม่ถูกต้อง ... แต่จะเป็นประโยชน์กับผู้อ่านเช่นตัวฉันที่สะดุดเจอคำตอบนี้ ดังนั้นจึงไม่เพิ่มมูลค่าให้กับหน้านี้แม้ว่าจะไม่ได้เป็นของออราเคิลที่เฉพาะเจาะจง ดังนั้นขอบคุณ James111!
Mike Gledhill

3

นี่คือวิธีแก้ปัญหาที่มีประโยชน์! ฉันใช้ SQL Server 2008 R2

ตามที่คุณต้องการแก้ไขข้อ จำกัด FK โดยเพิ่ม ON DELETE / UPDATE CASCADE ให้ทำตามขั้นตอนเหล่านี้:

หมายเลข 1:

คลิกขวาที่ข้อ จำกัด และคลิกเพื่อปรับเปลี่ยน

ป้อนคำอธิบายภาพที่นี่

หมายเลข 2:

เลือกข้อ จำกัด ของคุณทางด้านซ้าย (หากมีมากกว่าหนึ่งข้อ) จากนั้นทางด้านขวาให้ยุบจุด " INSERT And UPDATE Specification " และระบุการดำเนินการในแถว Delete Rule หรือ Update Rule เพื่อให้เหมาะกับความต้องการของคุณ หลังจากนั้นปิดกล่องโต้ตอบ

ป้อนคำอธิบายภาพที่นี่

หมายเลข 3:

ขั้นตอนสุดท้ายคือการบันทึกการปรับเปลี่ยนเหล่านี้ (แน่นอน!)

ป้อนคำอธิบายภาพที่นี่

PS: มันช่วยฉันจากการทำงานมากมายเพราะฉันต้องการแก้ไขคีย์หลักที่อ้างถึงในตารางอื่น


สมบูรณ์แบบตรงกับสิ่งที่ฉันต้องการเช่นกัน!
Wildview

1

หากคุณต้องการเปลี่ยนคีย์ต่างประเทศโดยไม่ทิ้งคุณสามารถทำได้:

ALTER TABLE child_table_name  WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.