2017-07-18 26 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_TBLcodeからRECORD_TBLcurr_codeから外部キー参照を作成する必要があります。

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

これは明らかに私にエラーORA-02267(参照される列と互換性のない列タイプ)を与えます。

CODE_TBLのコード列を変更することはできません。私はschema1を所有していないか、制御していないためです。 curr_codeの列をRECORD_TBLに変更することはできません。なぜなら、末尾の空白を考慮していないため、アプリケーションの多くの機能が壊れるからです。

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が確立されています(明らかに、変更すると「多くの機能を中断する」ため)。後で誰かがこのテーブルのリレーショナル・インテグリティを強制することに決めましたが、別のスキーマのテーブルを別のデータ型のカラムで参照することを選択しました。

Hmmmm。

あなたのオプションは以下のとおりです。

  1. は何もしません。常にオプションです。あなたのアプリケーションは、ある期間、現在の状態で生き残っています。おそらく、あなたは未払いの技術的負債で暮らし続けることができます。
  2. スキーマの1つをリファクタリングします。外部キーを強制する必要がある場合は、リレーショナル・インテグリティは良いことです。次に、列の1つのデータ型を変更する必要があります。どちらを選択するかはプロジェクトの決定です。所有していないスキーマの列を変更することは政治的な問題であり、通常は政治的な問題は技術的な問題よりも困難です。列のタイプを変更してスキーマをリファクタリングすることは、テスト、テスト、テストの問題です。
  3. レプリケーション。 schema1.code_tblのデータをコピーするschema2のマテリアライズド・ビューを作成します。重大なことに、schema2.record_tbl.curr_codeのデータ型、つまりvarchar2(6)と一致するMView code列を定義します。 schema2.mv_code_tbl.codeに対して外部キーを適用できるようになりました。 注: MView列のデータは、末尾のスペースでCHAR、つまりフォーマットされます。
+0

アドバイスありがとうございます。残念なことに、これは私が作業しているレガシーシステムです。私の先人がなぜこのように設計したのか分かりません。 Schema2は、それが参照できる 'code_tbl'の独自のコピーを持っていましたが、それ以来、私にはわからない理由で削除されています(おそらく2つのコードテーブルを管理するのは大変でした)。私がシステムを引き継いだときには、外部キーの考慮事項は明らかに持ち上がっていませんでした。 – sml485

関連する問題