有没有办法引用具有不同数据类型的列?

时间:2017-07-18 06:05:50

标签: sql oracle tsql

我有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)
);

我需要从curr_code中的RECORD_TBLcode CODE_TBL创建一个外键引用。

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列之间的参照完整性?

3 个答案:

答案 0 :(得分:2)

所以情况就是这样。你有一个已经建立的现有表record_tbl(显然,因为改变它“打破了许多功能”)。迟来有人决定在这个表上强制执行关系完整性,但是选择这样做引用不同模式中的表和不同数据类型的列。

Hmmmm。

您的选择是:

  1. 什么都不做。永远是一个选择;你的应用程序在当前状态下存活了一段时间,也许你可以继续忍受累积的技术债务。
  2. 重构其中一个架构。如果你需要强制执行外键 - 让我们面对它,关系完整性是一件好事 - 那么你将不得不改变其中一个列的数据类型。您选择哪一个是项目决策:更改您不拥有的模式中的列是一个政治问题(最初),政治问题通常比技术问题更难。通过更改列类型来重构架构是测试,测试和测试的问题。
  3. 复制。在schema2中构建实体化视图,从schema1.code_tbl复制数据。至关重要的是,定义MView code列匹配schema2.record_tbl.curr_code的数据类型,即varchar2(6)。您现在可以对schema2.mv_code_tbl.code强制执行外键。 注意: MView列中的数据将被格式化为CHAR,即带有尾随空格。

答案 1 :(得分: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

以下是Tom Kyte关于虚拟列的文字: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:676611400346196844

答案 2 :(得分:0)

您无法在不同类型列中创建关系。 为什么必须在数据库中创建关系?您只能使用代码连接表。