关系类属性
此主题仅适用于 ArcEditor 和 ArcInfo。
虽然关系类在 ArcInfo 和 ArcEditor 中既可以创建也可以编辑,但在 ArcView 中只能读取。参与关系类的要素类在 ArcView 中也为只读。
关系类包含多种属性,这些属性可定义源中对象与目标中对象相关联的方法。在创建关系类时指定这些属性。
- 类型:简单或复合
- 源类和目标类
- 主键和外键
- 基数:是一对一、一对多还是多对多的关系?
- 消息通知方向,在要执行自定义级联更新或删除行为的情况下适用
- 是否要为每个关系存储属性
- 名称
- 在 ArcMap 中导航相关记录时显示的前向与后向标注
创建关系后,可以指定规则来优化基数。
简单与复合
在创建关系类时,指定是简单关系类还是复合关系类。
在简单关系中,相关对象可以彼此独立存在。例如,在铁路网络中,可能存在拥有一个或多个相关信号灯的铁路交叉点。但是,铁路交叉点上可以没有信号灯,并且存在信号灯的铁路网络上也可以没有铁路交叉点。
当删除简单关系中的源对象时,与匹配目标对象对应的外键字段值将设置为“空”。此外键行为专用于保持要素间的引用完整性。如果删除源要素,那么外键中的值不会再将该行与源中的要素相关联,因此,将不再需要外键值并将其设置为“空”。外键的唯一用途就是维持目标对象与相关源对象间的关系。如果不存在具有匹配主键值的源要素,则没有保留外键值的理由。如果以后要将相同的目标要素与新的或不同的源要素相关联,则可将 FK 字段从“空”更新至新的 FK 值。
删除目标对象对相关源对象中的主键值不起任何作用。
简单关系可拥有一对一、一对多或多对多基数。
与简单关系相同,复合关系也可在删除对象时保持引用完整性,但它们是以不同的方式来执行此操作。在复合关系中,目标对象无法独立于源对象存在,因此在删除源对象时,也会在此过程中删除相关的目标对象,这称为级联删除。
此依存规则也可通过 ArcMap 的“验证要素”命令来强制执行,该命令在编辑会话中运行,用以测试引用完整性。如果创建了目标对象却未将其与源对象进行关联,“验证要素”将会发出存在错误的警告。
复合关系还有助于在空间上维护要素;在将消息发送设置为“向前”时,移动或旋转源要素会使相关目标要素随其一同移动或旋转。
复合关系在创建时始终为一对多的关系,但使用关系规则可以将其限制为一对一的关系。
源类与目标类
创建关系类时,选择一个类作为源类,选择另一个类作为目标类。不要混淆这两种类至关重要。在复合关系中采用级联删除行为的情况下,这种重要性显而易见。
在简单关系中,正确认识这两种类同样至关重要。这是由于在删除源类中的记录时,简单关系类会在目标类中查找匹配记录,同时将其键字段的值设置为“空”。如果选错了源类,然后删除源类中的对象,则会将错误引入外键字段中。以下示例说明了此错误的发生过程:
实例 1:宗地至区域(错误)
这是一种常见的错误情况。Zone 表包含了对不同分区代码的描述,且在概念上类似于 ArcInfo Workstation 查找表。在这种情况下,Parcel 类为源,Zone 表为目标。这就是在 ArcInfo Workstation 中设置关系的方式。问题是在删除宗地时,Zone 表中匹配记录的键字段 (Zone) 中的值设置为“空”,然后其他具有该分区代码的任何宗地在 Zone 表中不会具有匹配项。
实例 2:区域至宗地(正确)
要更正该问题,将 Zone 表设置为源。删除宗地(目标对象)时,对 Zone 表没有任何影响;删除“分区”代码(源对象)时,只会将匹配宗地记录中 Zone 字段的值设置为“空”,这一点与实际情况相符,因为它们在 Zone 表中不再有匹配的记录。
主键与外键
在关系类中,源中的对象通过其键字段中的值匹配目标中的对象。在下面的示例中,宗地 789 与许可 2 和许可 3 相匹配,因为所有这两个许可记录均具有相同的宗地 ID。
关系的源类中的键字段称为主键,通常缩写为 PK。与真实的主键不一样,在关系的主键字段中的每个对象不需要具有唯一的值。
目标类中的键字段称为外键,通常缩写为 FK。它包含与源类中主键字段的值相匹配的值。此外,键字段的每一行不需要具有唯一的值。
键字段可以具有不同的名称,但必须属于相同的数据类型,并且包含相同种类的信息(如宗地 ID)。除二进制大对象 (BLOB)、日期和栅格外的所有数据类型的字段都可以是键字段。并且可在创建关系类时指定键字段。
当确定主键字段时,有一种选择就是使用行 ID 字段(通常称为 ObjectID 字段)。ObjectID 字段在创建要素类/表或者在注册 ArcSDE 图层/表时由 ArcGIS 自动添加。该字段确保每个记录都具有唯一的 ID。该字段由 ArcGIS 维护,无法对其进行修改。
只要给定对象的 ObjectID 值保留在其原始类中,该值将不会更改,同时如果对象为一个要素,则无法对其进行分割。如果对一个要素进行分割,它将保留原始要素(但会更新几何)并创建一个新要素,该新要素具有一个指定给它的新 ObjectID。因此,只有具有原始 ObjectID 的要素才会保持由 ObjectID 值决定的所有关系。
因此,不依赖 ObjectID 字段而是创建并使用自己的主键字段可能会更好。如下内容描述了您自己的主键字段在执行每个操作时帮助维持关系的方式。
- 在将记录导入到其他要素类或表时,将指定新的 ObjectID 值,同时会丢失基于原始 ObjectID 值的所有关系。但是,如果关系基于其他主键,则主键中的 ID 值在记录导入时不会发生更改。这样就可以在将相关对象集导入到新类时保留关系。
使用复制/粘贴功能时会出现例外情况。复制/粘贴将保留 ObjectID 值,因此如果打算仅采用该方法移动对象,则可以使用 ObjectID 字段作为主键。
- 复制将 ObjectID 字段用作主键字段的关系类时,在同步过程中需要进行额外处理,这可能会影响性能。在某些情况下,还可能导致意外行为。要了解有关在复制中使用 ObjectID 作为主键的详细信息,请参见复制相关数据。
- 在对某个要素进行分割时,原始要素将会保留(几何将进行更新),并创建一个新要素。如果具有基于原始 ObjectID 的关系,则只有在分割过程中创建的两个要素中的一个会维持该关系。但是,如果在分割要素时使用其他字段作为键,则原始要素的 ID 值将会复制到这两个新要素中。因此,在理想情况下,如果将关系类设置为多对多,则相关表中的记录会立即与两个新要素相关联。
如果不会对要素进行分割并能够保证所有对象都保留在其原始类中,则可以使用 ObjectID 作为相应的 ID。如果无法对此作出保证,则最好建立并使用自己的 ID 字段,而不依赖于 ObjectID 字段。
- 在合并两个要素时,新的要素将保留其中一个原始要素的 ObjectID。如果计划合并要素但却不想将要素从其类中移出或对要素进行分割,可以使用 ObjectID 字段作为主键。
基数
关系的基数指定可与目标类中对象数相关联的源类中的对象数。关系可以拥有以下三种基数之一:
一对一:一个源对象仅可以与一个目标对象相关联。例如,一个宗地只能具有一个法定描述。在 ArcGIS 中,该基数也可以包含多对一关系。多对一关系的示例之一就是许多个宗地与相同的法定描述相关联。
一对多:一个源对象可以与多个目标对象相关联。例如,一个宗地可能拥有许多个建筑物。在一对多关系中,“一”方必须为源类,“多”方必须为目标类。
多对多:一个源对象可以与多个目标对象相关联,相反,一个目标对象也可以与多个源对象相关联。例如,一个给定的房产可能拥有许多个所有者,同时一个给定的所有者可能拥有许多房产。
术语“一”和“多”可能会引起误解。“一”事实上是零对一,而“多”事实上是零对多。因此,当您创建宗地与建筑物间的一对多关系时,举例来说,该关系将允许下列所有情况:
- 没有建筑物的宗地
- 没有宗地的建筑物
- 拥有任意数量建筑物的宗地
创建关系后,可通过为关系设置规则来优化基数。可以通过设置规则来指定允许与目标中多个对象相关联的源中的对象数。
关系规则
在创建关系类时,可使用一对一、一对多或多对多的基数对其进行创建。
关系通常需要在多个限制性条件下进行定义。例如,在宗地与建筑物的关系中,您可能需要将每个建筑物与宗地相关联或一个宗地包含最多的建筑物数量。要防止用户忘记将一个建筑物与一个宗地相关联,还要防止用户将过多的建筑物与一个宗地相关联。
如果具有子类型,则可以限制能够与目标中某种对象类型相关联的源中的对象数目和类型。例如,钢制电线杆支持 A 类变压器,而木杆支持 B 类变压器。而且,还可能需要为每个有效的子类型对指定允许的基数范围。例如,钢制电线杆支持 0 至 3 个 A 类变压器,而木杆可以支持 0 至 2 个 B 类变压器。
创建关系类后,可以指定有助于增强这些引用完整性规则的规则:
- 在 ArcCatalog 或“目录”窗口中,右键单击现有的关系类以显示其“关系类属性”对话框,然后单击“规则”选项卡。
- 从源类中选择一个子类型并从目标类中选中相应的子类型。
- 选中源基数以及目标基数的复选框。为规则设置合适的最小基数与最大基数。对话框会阻止您作出最小基数值大于最大基数值的设置,因此,先设置最大基数值。
将关系规则添加至关系类后,该规则将成为唯一存在的有效关系。要使其他关系组合和基数有效,必须添加其他的规则。
在下面的示例中,危险物品垃圾填埋场可与一口或两口深井相关联,或与两口至七口浅井相关联。但是,如果卫生垃圾填埋场与一口深井相关联,但却未在这两种子类型之间创建规则,则“验证要素”命令会将该关系视为无效。
在建立规则并开始编辑后,可以使用 ArcMap 的“验证要素”命令对其进行测试。“验证要素”命令将在任何当前所选的要素违反关系规则时发出通知。
消息通知方向
正如前文所述,在删除复合关系中的源对象时,相关联的目标对象会自动删除。
不论正在使用简单关系还是复合关系,都可能存在需要更新某一要素以触发其相关要素中更新的其他操作。此外,在一个方向、另一个方向或两个方向上均可能需要更新。
- 当移动或旋转要素时,需要相关要素与其一起移动或旋转。
- 当更新要素时,需要相关要素中的属性自动更新。
- 更新源对象可要求相关目标对象进行更新。
- 更新目标对象可要求相关源对象进行更新。
如果您的关系需要此行为,当源对象及目标对象发生变化时,您可以让源对象及目标对象通过发送消息来相互通知,以便相关对象进行相应的更新。
要完成上述操作,请在创建关系时设置消息通知方向。如果更新源对象时要求对相关目标对象也进行更新,则将消息通知方向设置为“向前”。如果更新目标对象时要求对相关源对象也进行更新,则将消息通知方向设置为“向后”。如果以上两种情况都需要,则将消息通知方向设置为“双向”。一旦创建了关系,随后必须将该行为设置到接收消息的对象中,以便它们可以作出响应。
复合关系在消息发送方向设置为“向前”时是唯一的例外情况。在创建复合关系时,如果消息发送方向设置为“向前”,则移动或旋转源对象会使相关目标对象要素与其一起进行自动移动或旋转。假如正确地建立了这种关系,那么在创建这种关系后此功能即可发挥作用,而无需额外的自定义程序设计。
对于其他消息通知方向,均需要自定义程序设计。除非创建复合关系时消将息发送方向设置为“向前”或想要对自定义行为进行编程,否则将消息通知设置为“无”。如若不然,每次执行编辑操作时都会生成不必要的消息,会导致性能降低。
当设置复合关系的方向时请牢记,在删除复合关系中的源对象后,目标中的所有相关对象均会自动删除。不管消息发送设置为“向前”、“向后”、“双向”还是“无”,都会发生这种情况。
方向 |
对简单关系的作用 |
对复合关系的作用 |
---|---|---|
向前 |
除非进行自定义程序设计,否则不起任何作用 |
|
向后 |
除非进行自定义程序设计,否则不起任何作用 |
|
双向 |
除非进行自定义程序设计,否则不起任何作用 |
|
无 |
阻止消息发送,可使性能略微提高 |
|
多对多关系
在一对一和一对多关系中,源类主键中的值会直接与目标类外键中的值相关联。
另一方面,多对多关系需要使用中间表来映射关联。因此,在创建多对多关系时,将自动创建中间表。中间表可将来自源的主键值映射至来自目标的外键值。每一行都将一个源对象与一个目标对象相关联。
在创建中间表时,只会生成字段。ArcGIS 无法得知哪些源对象与哪些目标对象相关联,因此在 ArcMap 中必须手动创建行。填充此表是建立关系过程中最耗时的部分。
关系属性
多对多关系的中间表可选择性地提供第二种用途,即存储关系自身的属性。例如,在宗地数据库中,宗地与所有者之间可能具有关系类,其中所有者拥有宗地,同时宗地由所有者拥有。每种关系的属性应为所有权的百分比。如果需要存储此类属性,可在创建关系时或以后的任何时间将其添加到中间表。
虽然关系属性不是很有用,但当要建立一对一或一对多的关系时,可能恰恰需要存储关系的属性。如果是这种情况,则当创建关系时必须对此进行指定,以便创建中间表。与多对多关系相同,中间表可将来自源的主键值映射至来自目标的外键值,以此来为每种关系存储任意数量的属性。
可在 ArcCatalog 或“目录”窗口中预览中间表以查看其包含的数据。如果将关系类添加到 ArcMap 中,它将显示为一个可以打开并进行操作的表。ArcGIS 不会显示用于其他操作的中间表。例如,无法在要添加或删除字段的 ArcCatalog 或“目录”窗口中显示其属性,并且不支持使用默认值或属性域。
名称
每种关系类都具有一个在目录树中显示的名称。要使数据库结构易于理解,请以能够描述关系的名称对关系类命名。
以源要素类的名称开头,后接 Has 或 Have,然后以目标要素类的名称结尾。例如,AddressHasZones 或 ParcelsHaveOwners。如果关系基数为多对一或多对多,则以复数形式表示源要素类名称,如果关系基数为一对多或多对多,则以复数形式表示目标要素类名称。
使用此方法可通过关系类的名称确定其基数。例如,ParcelsHaveOwners 的两个要素类均使用复数形式,可以想到它是多对多关系。
前向标注与后向标注
前向标注与后向标注在 ArcMap 中的“属性”及“识别结果”对话框中显示,有助于在相关对象间进行导航。
关系类具有如下两种标注:
- 在从源导航至目标时所显示的前向标注。在杆式变压器示例中,该标注可显示为“支持”,这表示此杆支持这些变压器。
- 在从目标导航至源时所显示的后向标注。在杆式变压器示例中,该标注可显示为“已安装”,这表示这些变压器安装在此电线杆上。