简体   繁体   English

使用外键创建Oracle表,该外键引用实例化视图上的主键

[英]Creating Oracle tables with foreign keys that reference primary keys on materialized views

I have several materialized views in Oracle which I can query to get information. 我在Oracle中有几个实例化视图,可以查询以获得信息。

Now I want to create several tables with foreign keys referencing those MVs and to do so, I have already "added" the corresponding primary keys to the MVs (as stated in adding primary key to sql view ). 现在,我想用引用这些MV的外键创建几个表,并这样做,我已经将相应的主键“添加”到了MV(如在sql view添加主键所述)。

Then, when I execute my SQL create table query, I get an Oracle (ORA-02270) error: no matching unique or primary key for this column-list error at position 0, right at the beginning... 然后,当我执行SQL 创建表查询时,出现一个Oracle(ORA-02270)错误:此列列表错误在位置0的开头没有匹配的唯一键或主键 ...

Am I doing something wrong? 难道我做错了什么? Is it possible what I am trying to do? 我可能要做什么? If not, how is it usually done? 如果没有,通常如何做?

The documentation states that: 文档指出:

View Constraints 查看约束

Oracle does not enforce view constraints . Oracle 不强制执行视图约束 However, operations on views are subject to the integrity constraints defined on the underlying base tables. 但是,对视图的操作受基础基表上定义的完整性约束的约束。 This means that you can enforce constraints on views through constraints on base tables. 这意味着您可以通过基本表上的约束对视图施加约束。

and also: 并且:

View constraints are a subset of table constraints and are subject to the following restrictions: 视图约束是表约束的子集,并受到以下约束:

  • ... ...
  • View constraints are supported only in DISABLE NOVALIDATE mode . 仅在DISABLE NOVALIDATE模式下支持视图约束 You cannot specify any other mode. 您不能指定任何其他模式。 You must specify the keyword DISABLE when you declare the view constraint. 声明视图约束时,必须指定关键字DISABLE。 You need not specify NOVALIDATE explicitly, as it is the default. 您无需显式指定NOVALIDATE,因为它是默认值。
  • ... ...

In practice, the above means that although constrains on views can be created, they are blocked and do not work . 实际上,以上内容意味着尽管可以创建视图约束, 但是它们被阻止并且不起作用 So as if they were not at all. 好像它们根本不一样。


Apart from this, think for a moment what sense it would have foreign key constrainst created on tables, that would refer to a materialized view: 除此之外,请想一想,在表上创建外键约束是什么意思,它指的是物化视图:

  • tables are always "online" and have always "fresh" data 表始终是“在线”,并且始终是“新鲜”数据
  • materialized views can contain stale data 物化视图可能包含过时的数据

Imagine this case: You insert a record X into some table. 设想这种情况:您将记录X插入某个表中。 This record is not visible in the materialized view yet, because the view is not refreshed at this moment. 该记录在实例化视图中尚不可见,因为此刻该视图尚未刷新。 Then you try to insert record X into another table that has a foreign key constraint pointing to that materialized view. 然后,您尝试将记录X插入到另一个具有指向该实例化视图的外键约束的表中。 What the database should do ? 数据库应该做什么? Should the database reject the insert statement (since for now X is not visible yet in the view and the foreign key exists) ? 数据库是否应该拒绝插入语句(因为现在X在视图中尚不可见并且外键存在)? If yes, then what about data integrity ? 如果是,那么数据完整性如何? Mayby should it block amd wait until the view is refreshed ? 也许它应该阻止amd等到视图刷新吗? Should it force the view to start refreshing or not in such a case? 在这种情况下,是否应强制视图开始刷新?

As you can see, such a case involves many questions and difficult problems in the implementation, so Oracle simply does not allow for constrains on views. 如您所见,这种情况在实现中涉及许多问题和难题,因此Oracle根本不允许对视图进行约束。

When there are materialized views referenced by other tables' foreign keys, you have to take note on your views refresh method and how it affects your foreign keys. 当存在其他表的外键引用的物化视图时,您必须记下视图刷新方法及其对外键的影响。 Two things may prevent you from refreshing your materialized views: 有两件事可能会阻止您刷新实例化视图:

1) The data in the tables referencing your views may reference lines that need to be updated or deleted. 1)引用您的视图的表中的数据可能引用了需要更新或删除的行。 In that case you have to fix your data. 在这种情况下,您必须修复数据。

2) Your views' refresh method is complete. 2)您的视图的刷新方法已完成。 In complete refresh Oracle deletes all data in your mviews tables and repopulates them by rerunning their queries as you can see in Oracle site documentation - Refresh Types , while in fast refresh only the differences are applied to your mviews tables. 在完全刷新中,Oracle删除mviews表中的所有数据,并通过重新运行它们的查询来重新填充它们,如您在Oracle站点文档-刷新类型中所看到的那样,而在快速刷新中,仅将差异应用于mviews表。 Fast refresh is an incremental refresh and it won't work only if your foreign keys aren't respected by your data. 快速刷新是一种增量刷新,并且仅当您的外键不受数据尊重时才起作用。

Now if there are mviews that can't be created with fast refresh (what Oracle calls them "Complex queries") then you can alter constraints to these mviews to deferrable as you can see here . 现在,如果无法通过快速刷新创建mview(Oracle称之为“复杂查询”),则可以将这些mview的约束更改为可延迟,如此处所示

That way even complete refresh will work because Oracle only validates deferrable constraints by the end of current transaction. 这样一来,即使是完全刷新也将起作用,因为Oracle仅在当前事务结束之前验证可推迟的约束。 Therefore, as long as your refresh method is atomic, Oracle will issue an DELETE and than INSERT all rows back, all in one transaction. 因此,只要您的刷新方法是原子的,Oracle就会在一个事务中发出DELETE,然后将所有行插入INSERT。

In other words, in the next command to refresh your mview keep parameter atomic_refresh as true: 换句话说,在下一个刷新mview的命令中,将参数atomic_refresh保持为true:

dbms_mview.refresh(LIST=>'MVIEW', METHOD =>'C', ATOMIC_REFRESH => TRUE);

By the way, this parameter's default value is TRUE, so just don't mention it and it will work. 顺便说一句,此参数的默认值为TRUE,所以不要提及它,它将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM