關於ORA-02273錯誤,之前還真沒有仔細留意過。昨天遇到了這個問題,遂順便總結一番,之後遇到這類問題就能夠直接用下面方案解決。以下所示,咱們首先準備一下測試環境。app
CREATE TABLE TEST.TEST
( OWNER VARCHAR2(30),
OBJECT_ID NUMBER,
OBJECT_NAME VARCHAR2(30)
);
CREATE INDEX TEST.IX_TEST_N1 ON TEST.TEST(OBJECT_ID) TABLESPACE TEST_DATA;
ALTER TABLE TEST.TEST ADD CONSTRAINT PK_TEST PRIMARY KEY (OBJECT_ID) USING INDEX TABLESPACE TEST_DATA;
CREATE TABLE TEST.RF_TEST
(
ID NUMBER,
OBJECT_ID NUMBER
);
ALTER TABLE TEST.RF_TEST ADD CONSTRAINT PK_RF_TEST PRIMARY KEY(ID) USING INDEX TABLESPACE TEST_DATA;
ALTER TABLE TEST.RF_TEST ADD CONSTRAINT FK_RF_TEST FOREIGN KEY(OBJECT_ID ) REFERENCES TEST.TEST(OBJECT_ID);
以下所示,因爲腳本上面的事務,致使TEST.TEST的主鍵約束對應的索引爲IX_TEST_N1。測試
SELECT OWNER
,CONSTRAINT_NAME
,CONSTRAINT_TYPE
,TABLE_NAME
,INDEX_NAME
FROM DBA_CONSTRAINTS
WHERE TABLE_NAME='TEST';
此時假如咱們要調整表TEST.TEST的主鍵,那麼能夠用下面腳本查看一下TEST表的主外鍵約束關係。以下所示:this
SELECT DC.OWNER AS "PARENT_TABLE_OWNER",
DC.TABLE_NAME AS "PARENT_TABLE_NAME",
DC.CONSTRAINT_NAME AS "PRIMARY CONSTRAINT NAME",
DC.STATUS AS "PRIMARY CONSTRAINT STATUS",
DF.CONSTRAINT_NAME AS "REFERENCED CONSTRAINT NAME",
DF.STATUS AS "FOREIGN CONSTRAINT STATUS",
DF.STATUS AS "CHILD_TABLE_OWNER",
DF.TABLE_NAME AS "CHILD_TABLE_NAME" ,
'ALTER TABLE ' || DF.OWNER || '.' || DF.TABLE_NAME || ' DISABLE CONSTRAINT ' || DF.CONSTRAINT_NAME || ';'
FROM DBA_CONSTRAINTS DC,
(SELECT C.OWNER,
C.CONSTRAINT_NAME,
C.R_CONSTRAINT_NAME,
C.TABLE_NAME,
C.STATUS
FROM DBA_CONSTRAINTS C
WHERE CONSTRAINT_TYPE = 'R') DF
WHERE DC.CONSTRAINT_NAME = DF.R_CONSTRAINT_NAME
AND DC.OWNER =UPPER('&OWNER')
AND DC.TABLE_NAME=UPPER('&TABLE_NAME');
刪除表的主鍵約束時,報以下錯誤:「ORA-02273: this unique/primary key is referenced by some foreign keys」spa
SQL> ALTER TABLE TEST.TEST DROP CONSTRAINT PK_TEST;
ALTER TABLE TEST.TEST DROP CONSTRAINT PK_TEST
*
ERROR at line 1:
ORA-02273: this unique/primary key is referenced by some foreign keys
咱們用最上面腳本生成的禁用外鍵約束的腳本,禁用外鍵約束後,而後刪除表TEST.TEST的主鍵約束,依然報ORA-02273錯誤。code
如上所示,不能經過先禁用外鍵約束,而後刪除主鍵約束的這樣操做,搜索了相關資料後,發現只能先刪除外鍵約束,而後才能處理主鍵約束。orm
操做步驟以下:blog
1: 首先生成外鍵約束的建立腳本,後續刪除外鍵約束後,須要從新建立外鍵約束。索引
ORACLE 11g或以上版本使用下面腳本:事務
--此腳本適用於Oracle 11g
SELECT 'ALTER TABLE ' || T1_OWNER || '.' || T1_TABLE_NAME
|| ' ADD CONSTRAINT ' || T1_CONSTRAINT_NAME
|| ' FOREIGN KEY (' || T1_COLUMN_NAMES || ')'
|| ' REFERENCES ' || T2_OWNER || '.' || T2_TABLE_NAME
|| '(' || T2_COLUMN_NAMES || ');' FK_SCRIPT
FROM
(SELECT A.OWNER T1_OWNER
, A.TABLE_NAME T1_TABLE_NAME
, A.CONSTRAINT_NAME T1_CONSTRAINT_NAME
, B.R_CONSTRAINT_NAME T2_CONSTRAINT_NAME
-- CONCATENATE COLUMNS TO HANDLE COMPOSITE
-- FOREIGN KEYS
, LISTAGG(A.COLUMN_NAME,', ')
WITHIN GROUP (ORDER BY A.POSITION)
AS T1_COLUMN_NAMES
FROM DBA_CONS_COLUMNS A
, DBA_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE = 'R'
GROUP BY A.OWNER
, A.TABLE_NAME
, A.CONSTRAINT_NAME
, B.R_CONSTRAINT_NAME
) T1,
(SELECT A.OWNER T2_OWNER
, A.TABLE_NAME T2_TABLE_NAME
, A.CONSTRAINT_NAME T2_CONSTRAINT_NAME
-- CONCATENATE COLUMNS FOR PK/UK REFERENCED
-- FROM A COMPOSITE FOREIGN KEY
, LISTAGG(A.COLUMN_NAME,', ')
WITHIN GROUP (ORDER BY A.POSITION)
AS T2_COLUMN_NAMES
FROM DBA_CONS_COLUMNS A
, DBA_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE IN ( 'P', 'U' )
GROUP BY A.OWNER
, A.TABLE_NAME
, A.CONSTRAINT_NAME ) T2
WHERE T1.T2_CONSTRAINT_NAME = T2.T2_CONSTRAINT_NAME
AND T1.T1_OWNER = T2.T2_OWNER
AND T2.T2_OWNER ='&OWNER'
AND T2.T2_TABLE_NAME = '&TABLE_NAME';
ORACLE 11g以前版本使用下面腳本ip
--此腳本適用於Oracle 10g
SELECT 'ALTER TABLE ' || T1_OWNER || '.' || T1_TABLE_NAME
|| ' ADD CONSTRAINT ' || T1_CONSTRAINT_NAME
|| ' FOREIGN KEY (' || T1_COLUMN_NAMES || ')'
|| ' REFERENCES ' || T2_OWNER || '.' || T2_TABLE_NAME
|| '(' || T2_COLUMN_NAMES || ');' FK_SCRIPT
FROM
(SELECT A.OWNER T1_OWNER
, A.TABLE_NAME T1_TABLE_NAME
, A.CONSTRAINT_NAME T1_CONSTRAINT_NAME
, B.R_CONSTRAINT_NAME T2_CONSTRAINT_NAME
-- CONCATENATE COLUMNS TO HANDLE COMPOSITE
-- FOREIGN KEYS [HANDLES UP TO 5 COLUMNS]
, MAX(DECODE(A.POSITION, 1,
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 2,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 3,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 4,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 5,', '||
A.COLUMN_NAME,NULL))
T1_COLUMN_NAMES
FROM DBA_CONS_COLUMNS A
, DBA_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE = 'R'
GROUP BY A.OWNER
, A.TABLE_NAME
, A.CONSTRAINT_NAME
, B.R_CONSTRAINT_NAME
) T1,
(SELECT A.OWNER T2_OWNER
, A.CONSTRAINT_NAME T2_CONSTRAINT_NAME
, A.TABLE_NAME T2_TABLE_NAME
-- CONCATENATE COLUMNS FOR PK/UK REFERENCED
-- FROM A COMPOSITE FOREIGN KEY
, MAX(DECODE(A.POSITION, 1,
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 2,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 3,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 4,', '||
A.COLUMN_NAME,NULL)) ||
MAX(DECODE(A.POSITION, 5,', '||
A.COLUMN_NAME,NULL))
T2_COLUMN_NAMES
FROM DBA_CONS_COLUMNS A, DBA_CONSTRAINTS B
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND B.CONSTRAINT_TYPE IN ( 'P', 'U' )
GROUP BY A.OWNER
, A.TABLE_NAME
, A.CONSTRAINT_NAME ) T2
WHERE T1.T1_OWNER = T2.T2_OWNER
AND T1.T2_CONSTRAINT_NAME = T2.T2_CONSTRAINT_NAME
AND T2.T2_OWNER ='&OWNER'
AND T2.T2_TABLE_NAME = '&TABLE_NAME';
使用上面腳本生成的腳本爲
ALTER TABLE TEST.RF_TEST ADD CONSTRAINT FK_RF_TEST FOREIGN KEY (OBJECT_ID) REFERENCES TEST.TEST(OBJECT_ID);
2:生成刪除外鍵約束的腳本
SELECT 'ALTER TABLE '
|| OWNER || '.' || TABLE_NAME
|| ' DROP CONSTRAINT '
|| CONSTRAINT_NAME
||';' CONSTRAINT_DISABLE
FROM DBA_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'R'
AND STATUS = 'ENABLED'
AND R_CONSTRAINT_NAME IN
(
SELECT CONSTRAINT_NAME
FROM DBA_CONSTRAINTS
WHERE CONSTRAINT_TYPE IN ('P', 'U')
AND OWNER='&OWNER'
AND TABLE_NAME = '&TABLE_NAME'
);
執行上面腳本生成的腳本,刪除外鍵約束。
SQL> ALTER TABLE TEST.RF_TEST DROP CONSTRAINT FK_RF_TEST;
Table altered.
3:刪除表TEST.TEST的主鍵
SQL> ALTER TABLE TEST.TEST DROP CONSTRAINT PK_TEST;
Table altered.
SQL> SELECT OWNER
2 ,TABLE_NAME
3 ,INDEX_NAME
4 FROM DBA_INDEXES
5 WHERE TABLE_NAME='TEST';
OWNER TABLE_NAME INDEX_NAME
---------- ------------------------------ ------------------------------
TEST TEST IX_TEST_N1
SQL>
以下所示,這種狀況下,刪掉了約束,並不會刪除對應的索引。因此必須手工刪除該索引
4: 在表TEST.TEST上增長主鍵約束, 在表TEST.RF_TEST上添加外鍵約束。
SQL> ALTER TABLE TEST.TEST ADD CONSTRAINT PK_TEST PRIMARY KEY(OBJECT_ID) USING INDEX TABLESPACE TEST_DATA;
Table altered.
SQL> ALTER TABLE TEST.RF_TEST ADD CONSTRAINT FK_RF_TEST FOREIGN KEY (OBJECT_ID) REFERENCES TEST.TEST(OBJECT_ID);
Table altered.
SQL>