【问题标题】:Foreign key with distinguisher带区分符的外键
【发布时间】:2019-08-06 20:27:44
【问题描述】:

我有一个表 STATUSES 包含更多表的状态:

TABLE_NAME | STATUS_ID | STATUS_NAME
===========+===========+============
TAB_1      |         1 | New
TAB_1      |         2 | Started
TAB_1      |         3 | Complete
TAB_2      |         1 | Empty
TAB_2      |         2 | Full

表 STATUSES 有两​​列主键 (table_name,status_id)。

然后我有表格TAB_1:

ID | STATUS_ID | TAB_VALUE
===+===========+==========
 1 |         1 | Value1

当我想检索带有状态的表值时,我使用以下 SQL 查询:

SELECT id,tab_value,status_name
FROM tab_1 t
JOIN statuses s ON (s.status_id=t.status_id AND s.table_name='TAB_1')

现在我想创建一个从 TAB_1 到 STATUSES 的外键,但 STATUS_ID 应该用表名来区分!

我试过这样的:

ALTER TABLE tab_1
ADD CONSTRAINT tab_1_status_fk FOREIGN KEY ('TAB_1',status_id)
REFERENCES statuses (table_name,status_id)
ENABLE;

当然,这不起作用(否则我不会在这里)。

是否可以用'distinguisher'创建这样的外键?

【问题讨论】:

    标签: sql database oracle


    【解决方案1】:

    我想我会将表名添加为具有常量值的虚拟列,例如

    alter table tab_1 add (table_name as ('TAB_1'));
    

    然后使用它创建 fk

    ALTER TABLE tab_1
    ADD CONSTRAINT tab_1_status_fk FOREIGN KEY (table_name,status_id)
    REFERENCES statuses (table_name,status_id)
    ENABLE;
    

    编辑:如果您使用 12c 或更高版本,则可以隐藏虚拟列;我认为它仍然适用于 FK...

    alter table tab_1 add (table_name invisible as ('TAB_1'));
    

    【讨论】:

    • 嗯,我不喜欢这个解决方案。这些附加列不是虚拟列,而是包含真实(相同)数据并占用空间(可见或不可见)的真实列。这些表很大,那么更好的解决方案是将合并的状态表拆分为每个表的独立状态表,并与它们创建简单的 FK 关系。
    • 如果在创建列时使用as (EXPRESSION) 子句,它将被创建为虚拟列,即使您不使用virtual 关键字也是如此。在测试表上试一试——虚拟标志将在表 DDL 中设置,它不会在磁盘上分配更多的行存储空间。但你可能是对的,重新架构可能是更好的选择。这是一个尴尬的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多