2017-07-18 42 views
2

我有2種模式/如圖所示表:有什麼方法可以引用具有不同數據類型的列?

CREATE TABLE schema1.code_tbl 
(code  CHAR(6) PRIMARY KEY, 
    description CHAR(30) 
); 

CREATE TABLE schema2.record_tbl 
(rec_id VARCHAR(10) PRIMARY KEY, 
    curr_code VARCHAR(6), 
    remarks VARCHAR(30) 
); 

我需要CODE_TBL創建從curr_codeRECORD_TBLcode的外鍵引用。

ALTER TABLE schema2.record_tbl 
ADD CONSTRAINT record_code_fk 
FOREIGN KEY (curr_code) 
REFERENCES schema1.code_tbl (code); 

這顯然給了我一個ORA-02267(列類型與引用的列不兼容)錯誤。

我無法更改CODE_TBL中的代碼列,因爲我沒有擁有或控制schema1。我無法更改RECORD_TBL中的curr_code列,因爲它會破壞我應用程序中的許多功能,因爲我們不考慮尾隨空格。

是否有任何其他方式來強制執行2列之間的參照完整性?

回答

2

如果SCHEMA2上的Oracle 11g及以上,使用虛擬列可以解決你的問題,但是這會改變你的表,你正試圖避免的結構。如果你能管理它,在這裏是如何可以做到

SQL> CREATE TABLE code_tbl 
    2 (code  CHAR(6) PRIMARY KEY, 
    3 description CHAR(30) 
    4 ); 
Table created 

SQL> 
SQL> CREATE TABLE record_tbl 
    2 (rec_id VARCHAR2(10) PRIMARY KEY, 
    3 curr_code VARCHAR2(6), 
    4 remarks VARCHAR2(30) 
    5 ); 
Table created 

SQL> INSERT INTO code_tbl(code, description) VALUES ('ABC', 'Test Data'); 
1 row inserted 

SQL> INSERT INTO record_tbl(rec_id, curr_code, remarks) VALUES ('1', 'ABC', 'Test Row'); 
1 row inserted 

SQL> SELECT * FROM record_tbl; 
REC_ID  CURR_CODE REMARKS 
---------- --------- ------------------------------ 
1   ABC  Test Row 

SQL> SELECT * FROM code_tbl; 
CODE DESCRIPTION 
------ ------------------------------ 
ABC Test Data 

SQL> ALTER TABLE record_tbl ADD curr_code_v CHAR(6) AS (trim(curr_code)); 
Table altered 

SQL> SELECT * FROM record_tbl; 
REC_ID  CURR_CODE REMARKS      CURR_CODE_V 
---------- --------- ------------------------------ ----------- 
1   ABC  Test Row      ABC 

SQL> 
SQL> ALTER TABLE record_tbl 
    2 ADD CONSTRAINT record_code_fk 
    3 FOREIGN KEY (curr_code_v) 
    4 REFERENCES code_tbl (CODE); 
Table altered 

SQL> INSERT INTO record_tbl(rec_id, curr_code, remarks) VALUES ('2', 'ABC', 'Test Row 2'); 
1 row inserted 

SQL> INSERT INTO record_tbl(rec_id, curr_code, remarks) VALUES ('3', 'XYZ', 'Test Row 2'); 
INSERT INTO record_tbl(rec_id, curr_code, remarks) VALUES ('3', 'XYZ', 'Test Row 2') 
ORA-02291: integrity constraint (USER_X.RECORD_CODE_FK) violated - parent key not found 

以下是湯姆凱特關於虛擬列的話: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:676611400346196844

+0

謝謝你的回答。我已經在我的本地設置上進行了測試,效果很好。雖然我的老闆和DBA會批准這樣的措施(改變生產中的表格結構總是有點棘手),但我仍然可以肯定地說,從技術上講這是一個可行的解決方案。 – sml485

0

您不能在不同類型的列中創建關係。 爲什麼你必須在數據庫中創建關係?您只能使用代碼連接表格。

+1

歷史的教訓是對付你。在應用程序中執行關係完整性而不是數據庫不可避免地導致數據損壞。 – APC

2

所以情況是這樣的。你有一個現有的表record_tbl這是很好的(顯然,因爲改變它「打破許多職能」)。遲來有人決定在該表上強制執行關係完整性,但選擇在不同數據類型的列中引用不同架構中的表。

嗯。

的選項有:

  1. 什麼也不做。總是一個選擇;您的應用程序在當前狀態下存活了一段時間,也許您可​​以繼續接受應計技術債務。
  2. 重構其中一個模式。如果你需要執行外鍵 - 讓我們面對它,關係完整性是一件好事 - 那麼你將不得不改變其中一列的數據類型。你選擇哪一個是一個項目決策:改變你不擁有的模式中的列是一個政治問題(最初),政治問題通常比技術問題更難。通過更改列類型來重構模式是測試,測試和測試的問題。
  3. 複製。在schema2中構建實體化視圖,該視圖從schema1.code_tbl複製數據。最重要的是,定義MView code列匹配schema2.record_tbl.curr_code的數據類型,即varchar2(6)。您現在可以對schema2.mv_code_tbl.code執行外鍵。 注意: MView列中的數據將被格式化爲CHAR,即具有尾隨空格。
+0

謝謝你的建議。不幸的是,這是我正在使用的遺留系統。我不確定爲什麼我的前任這樣設計它。 Schema2過去有自己可以引用的'code_tbl'的副本,但由於我未知的原因(可能保留2個代碼表太過繁重)而被刪除。外鍵考慮顯然沒有提出,因爲當我接手這個系統時沒有任何東西。 – sml485

相關問題