我在客户端上将Oracle 11g 2.0.1.0与Spatial和Oracle SQL Developer一起使用。我有一个Places
带有主键的表ID
和一个Coordinates
带有tw列的视图:ID
引用中的文章Places
和SDO geometry Point
。
我想使用以下SQL创建实例化视图:
CREATE MATERIALIZED VIEW PlaceCoordinates
NOCACHE NOPARALLEL BUILD IMMEDIATE
USING INDEX
REFRESH ON DEMAND COMPLETE
DISABLE QUERY REWRITE AS
SELECT Places.ID, Coordinates.Point
FROM Places
LEFT OUTER JOIN Coordinates ON Places.ID = Coordinates.ID
ORDER BY Places.ID
这给了我这个错误:
ORA-30373:在此上下文中不支持对象数据类型
不管我按什么排序(即使只是有点愚蠢的东西1
),我都会遇到相同的错误。但是,如果我删除该ORDER BY
语句,它将正常工作。如果我只是做一个普通的SELECT
而不创建实例化视图,那么它也可以很好地进行排序。
为什么我不能排序?反正有这个问题吗?
关键是,在物化视图中执行ORDER BY没有任何意义。
在幕后,物化视图实际上只是一个表,当它基于的表被更新时,它会自动更新。但是,成为桌子意味着无法保证任何排序。即使初始MV以所需的顺序存储,也无法保证在应用更新后它将保持不变。确保按正确顺序获得结果的唯一方法是从MV中选择时使用显式的ORDER BY。
您可以将ORDER BY包含在视图(不是实体视图)中,并且在您使用该视图时将被应用:从视图中进行选择,则不需要任何ORDER BY。但这是非常糟糕的做法。这意味着应用程序可能在不知不觉中依赖于视图提供的某些假定顺序-直到有人决定从视图中删除ORDER BY,然后所有地狱松开。
关键是:如果应用程序需要特定顺序的结果,那么它必须在其发出的SELECT中通过包含ORDER BY来说明。
也就是说,查看您的MV定义,由于在基表(位置和坐标)上进行的更改似乎永远不会更新:您说它是“按需刷新”。换句话说,您(或一些自动过程)会定期触发一次完整刷新。这与创建新表完全相同。您也可以这样做:
CREATE TABLE PlaceCoordinates AS
SELECT Places.ID, Coordinates.Point
FROM Places
LEFT OUTER JOIN Coordinates ON Places.ID = Coordinates.ID;
并在每次要刷新PLACECOORDINATES表时(删除旧表后)运行此命令。它比MV机械更简单,更高效。另一种方法是一次创建表,然后在必要时截断并填充它:
CREATE TABLE PlaceCoordinates (
ID NUMBER PRIMARY KEY,
Point SDO_GEOMETRY
);
和
TRUNCATE TABLE PlaceCoordinates;
INSERT INTO PlaceCoordinates (ID, Point)
SELECT Places.ID, Coordinates.Point
FROM Places
LEFT OUTER JOIN Coordinates ON Places.ID = Coordinates.ID;
这样就可以指定ID为主键-总是一个好主意。当然,不要忘记在POINT列上定义适当的空间索引(假设您要在地图上显示这些点或对其进行查询)。好的做法是在刷新内容之前先删除该索引,然后再重新创建它(MV方法也需要此索引)。
无论选择哪种方法(您指定的MV或表),PLACECOORDINATES都不会反映PLACES和COORDINATES表的实时状态。它只会反映您上次手动完全刷新MV或重新加载表格时的状态。如果这是可以接受的,那么您已经准备就绪。
如果希望PLACECOORDINATES更接近其他两个表的状态,而不必完全刷新/重新加载它(例如每分钟),那么您需要定义MV,以便仅从源表中的更改中刷新它。这意味着您需要在那些将记录更改以便将其应用到MV的表上具有“材料视图日志”。但是,这只会在您指定的时间间隔或手动请求刷新时发生。但合理地,不要超过每分钟。当然不是每秒。
如果PLACECOORDINATES必须在发生变化时反映PLACES和COORDINATES中的所有更改(=“实时”),那么唯一的保证方法是使其成为一个表并在PLACES和COORDINATES上触发,从而自动将更改应用于PLACECOORDINATES上的那些表当它们发生时。
也许在这种情况下,最好直接从基表中读取。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句