「数据库系统原理」读书笔记-第七章
第七章:§7 Relational Database Design
§7.1 Features of Good Relational Designs
关系模式的设计如果直接根据 E-R 图来导出,那么,E-R 图的好坏就决定了关系模式的好坏。
假如一开始,我们设计了一个这样的关系模式:
$in_dep(ID, name, salary, dept_name, building, budget)$
这看上去很不错,因为它是 instructor 和 department 的自然连接,有许多查询可以用更少的 JOIN 来实现。但是仔细想想,这造成了冗余的问题。
一方面,部门的 building 和 budget 这些本来在 department 表中存在的内容需要被重复存储,可能会存在冗余的问题;另一方面,假如创建了一个新的部门,没有老师入职,那么在 in_dep 中表示不了这个部门。
§7.1.1 Decomposition
对于有冗余的关系模式,就需要分解它们。当然,如果过于极端,每个关系模式都只有一个属性,那就表示不了任何关系。不过考虑下面这个没那么极端的例子:
$employee(ID, name, street, city, salary)$
我们可以把它分解为下面的两个模式,毕竟,分解这种东西,想分就分嘛:
$employee1(ID, name)$
$employee2(name, street, city, salary)$
我的理解是,分解就是 JOIN 的逆操作。
看看,这个分解有一个问题,问题出现在两个员工同名的情形。假如两个不同的个体具有同一个名字,那么,这样分解的两个模式在 JOIN 的时候会出现错误的混合这种情形。还是费些笔墨写个例子吧:
$(57766, Kim, Main, Perryridge, 75000)$
$(98776, Kim, North, Hampton, 67000)$
分解之后,得到
$(57766, Kim)$
$(98776, Kim)$
以及
$(Kim, Main, Perryridge, 75000)$
$(Kim, North, Hampton, 67000)$
把这两个分解 JOIN 起来,就会得到 4 个合并的元组,而不是原先的两个。这样的分解,就叫做有损分解,反之,叫无损分解。
更多的元组,却表示了更少的信息,蕴含了信息量的理论。
§7.1.2 无损分解
令 $R$ 是一个关系模式,$R_1$ 和 $R_2$ 是 $R$ 的一个分解。也就是说,从属性的角度来看,$R = R_1 + R_2$。如果是一个无损分解,那么,把 $R$ 用 $R_1$ 和 $R_2$ 来替换,不会有信息的损失。
什么时候有信息的损失呢?也就是对于一个关系实例 $r(R)$,我们必须使用 $r_1(R_1)$ 和 $r_2(R_2)$ 来表示它,而不能只使用 $r_(R)$。为什么会这样,就是因为 JOIN 的时候出现了错误的混合。
更准确地,如果是无损连接分解的,那么对所有合法的实例,关系 $r$ 包含和下列 SQL 语句相同的元组:
1 | SELECT * |
回到上面的例子,employee 的分解就是有损的,因为原来的关系实例 $r$ 并不等于上面查询的结果,而是上面结果的子集。
为什么更多的元组会有更少的信息呢?因为关系模式需要表示关系。分解之后的两个关系模式产生了更多的元组,因而无法正确地表示关系。这一联系丧失了,则意味着信息量少了。
§7.1.3 Normalization Theory
现在我们就可以看一看什么是好的一个关系模式了。一个好的关系模式应该不存在冗余信息。
设计一个好的关系模式需要用到正则化技术,它氛围两步走:(1) 判断当前的关系模式是不是一种好的模式(可以存在很多种好的模式);(2) 如果当前的模式不是一个好的模式,则把它分解为一些小的关系模式,使得达到一个范式。分解必须是无损的。
为了确定关系模式是否是范式,需要用到现实世界的额外信息。最常见的手段是函数依赖。
§7.2 Decomposition Using Functional Dependencies
§7.2.1 Notational Conventions
略。
§7.2.2 Keys and Functional Dependencies
现实生活中最常见的约束可以用键或者函数依赖来表示。之前我们讨论过键,这里来看看扩展了的键——函数依赖。
之前我们说,一组属性能够成为键,在于它可以确定一个元组。现在,对函数依赖来说,它有两个组成部分,形如 $\alpha \to \beta$。$\alpha$ 是一个属性集,它可以唯一确定 $\beta$。
我们说,如果一个实例的所有元组对都有 $t_1[\alpha] = t_2[\alpha] \implies t_1[\beta] = t_2[\beta]$,则这个实例满足函数依赖 $\alpha \to \beta$。
如果一个模式的所有合法实例都满足 $\alpha \to \beta$ 的话,就说这个模式满足这个函数依赖。
理解这个点,只需要区分两个概念:实例和模式。前者是后者的一个实例化,后者是前者的抽象。
函数依赖的作用有两点:
- 测试某些关系是否满足给定的函数依赖 $F$;
- 在合法关系上添加约束后,只需要关注具有函数依赖的那些关系,其他的不需要考虑。
有些函数依赖是平凡的,比如 $A \to A$、$AB \to A$。
怎么读函数依赖呢?我通常是这样,比如对于函数依赖 $A \to B$,读作:$A$ 一样的话,$B$ 也一样。
对于一个函数依赖集 $F$ 来说,有可能推断出一些 $F$ 中没有的函数依赖成立。我们把所有能够由 $F$ 推断出来的函数依赖集记作 $F^+$。$F^+$ 包含了 F 中的所有函数依赖,定义为 $F$ 的闭包。
§7.2.3 Lossless Decomposition and Functional Dependencies
用函数依赖可以判断一个分解是否是无损的。具体来说,如果一个 $R$ 的分解 $R_1$ 和 $R_2$ 是无损的,则在 $F^+$ 中至少有以下一个条件满足:
- $R_1 \cap R_2 \to R_1$
- $R_1 \cap R_2 \to R_2$
换句话说,也就是 $R_1$ 和 $R_2$ 的交集必须成为 $R_1$ 或 $R_2$ 的主键。
这是很好理解的,因为,只有交集是主键,才能确保在 JOIN 的时候不存在混合连接的问题。
比如上面的例子,交集 name 就不能成为任何一个分解后的模式的主键,则说明分解是有损的。
技术上说,在关系模式上需要施加两个约束:
- $R_1 \cap R_2$ 是 $r_1$ 的主键;
- $R_1 \cap R_2$ 在 $r_2$ 中要引用 $r_1$,形成外键引用。
当然,这个判断方法只是充分的,不是必要的。这涉及到多值依赖的问题,后续会再讨论。
§7.3 Normal Forms
这里介绍两个范式:BCNF 和 3NF。
§7.3.1 Boyce-Codd Normal Form
一个我们最喜欢的范式是 BCNF,它基于函数依赖理论去除了所有的冗余。
§7.3.1.1 Definition
一个关系模式 $R$ 关于一个函数依赖集 $F$ 满足 BCNF,如果对于 $F^+$ 中所有的函数依赖,至少以下一个成立:
- 这个函数依赖是平凡的;
- 函数依赖左侧的条件是模式 $R$ 的超码。
换句话说,对于任何一个非平凡的函数依赖,箭头左侧的内容应该是这个模式的超码,可以确定模式的元组。
那么,如果一个模式不是 BCNF 的,如何转变为 BCNF 呢?
很简单,如果一个模式不是 BCNF,则至少存在一个非平凡的函数依赖 $\alpha \to \beta$,其中 $\alpha$ 不是模式 $R$ 的超码。
那么,新创建一个关系模式,由 $\alpha \cup \beta$ 组成。然后,在原来的关系模式中删除 $\beta$,但是要保留 $\alpha$。
举个例子,在 $in_dep(ID, name, salary, dept_name, building, budget)$ 中,存在两个函数依赖:$ID \to name, dept_name, salary$ 和 $dept_name \to building, budget$。
显然 ID 是个超码,但是 dept_name 不是。所以,把 dept_name,building,budget 提取出来,创建一个新的关系。把老关系去掉箭头右侧的部分,保留 dept_name。
这样,形成两个新的关系模式:
- $ID, name, salary, dept_name$;
- $dept_name, building, budget$。
之所以要强调,保留 dept_name,是因为有时候,箭头右侧会包含箭头左侧的内容。如果进行第一次 BCNF 分解后,得到的模式还不满足 BCNF,则需要进一步分解。
§7.3.1.2 BCNF and Dependency Preservation
我们之前讲过,数据库要检查许多约束。如果这种约束的检查在一个关系上就可以完成,肯定是很高效的事情。然而,BCNF 可能会阻碍这一目的。
举个例子。原来,一个学生只能选一个导师。现在改了,一个导师只能隶属于某个学院,而学生可以选许多导师,但是在一个学院只能选一个导师。
现在,可以使用一个三元组来表示这一关系:
$dept_advisor(s_ID, i
_ID, dept_name)$
根据上面的文字描述,在这一模式上需要满足两个函数依赖:
- $i_ID \to dept_name$
- $s_ID, dept_name \to i_ID$
这两个函数依赖中,第一个的 $i_ID$ 并不是超码,所以需要分解,最终得到以下两个新的模式:
$i_ID, dept_name$
$s_ID, i_ID$
这两个模式是符合 BCNF 的,但是上文的第二个函数依赖无法在任何一个模式中被检查,只能通过把两个模式并起来才能检查。
由于这种数据库设计必须通过 JOIN 才能检查函数依赖,所以这种设计被叫做非依赖保持的。
因为以来保持非常好,所以我们需要啊考虑另一种比 BCNF 弱一些的范式,它允许依赖保持。
§7.3.2 Third Normal Form
3NF 只比 BCNF 多了一个条件,不过为了严谨,还是把 3NF 需要的所有条件列出来,新增的条件是最后一条:
- $\alpha \to \beta$ 是平凡的函数依赖;
- $\alpha$ 是 $R$ 的超码;
- 在 $\beta - \alpha$ 的每一个属性 $A$ 被包含在 $R$ 的候选码中。
注意,第三点并不是要求一个候选码包含所有的 $\beta - \alpha$ 的属性。这些属性可以被不同的候选码包含,但是至少要被一个候选码包含。
还是看看之前的例子:
- $i_ID \to dept_name$
- $s_ID, dept_name \to i_ID$
我们之前说到,第一个函数依赖的存在导致数据库模式不满足 BCNF。不过,这里,$dept_name - i_ID$ 后得到的 $dept_name$ 在候选码中,因而符合 3NF 的第三条。
§7.3.3 Comparison of BCNF and 3NF
3NF 相较于 BCNF 有一个很大的优势,在于依赖保持。但它也有不足,也就是有时候,我们必须用空值来表示重复的信息。
总的来说,设计数据库要达成的 3 个目标是:
- BCNF
- 无损
- 依赖保持
然而,由于开销的原因,市面上绝大多数数据库系统都没有提供除了 key 之外的其他函数依赖约束的设计。总而言之,理论是理论,实操目前不太好实现。(反正我是不会实现,已被数据库内核劝退)
§7.3.4 Higher Normal Forms
有时候,用函数依赖理论分解模式的时候,无法避免冗余的信息。比如,考虑一个教授可以有许多小孩,也可以有许多座机电话。那么,这两个多值属性就需要分别用两个模式来表示。
$(ID, child_name)$
$(ID, phone_number)$
然而,其实也可以合在一起:
$(ID, child_name, phone_number)$
我们可以验证,合并后的结果满足 BCNF,因为其上没有函数依赖约束。然而,这个想法并不是很好,因为如果教授有两个小孩,两个座机号码,则需要从 $2 \times 2 = 4$ 条记录来存储。
$$
(123, A, 6666)
(123, A, 8888)
(123, B, 6666)
(123, B, 8888)
$$
当然,你也可以选择其中的两条来记录,如第一条和最后一条,这样不存放冗余信息。然而,这样可能会导致一些错误的蕴含,因为事实上,A 也可以和 8888 关联,但是只选取两条记录可能丢失了这种关联。
对于这种依赖,会在 7.6 和 7.7 讨论。
§7.4 Funtional-Dependency Theory
为了验证一个数据库设计是否满足某些范式,了解函数依赖理论是很必要的。比如,在 BCNF 和 3NF 的定义中,都要求对 $F^+$ 中的所有函数依赖,满足一些性质。然而,函数依赖的闭包,如何计算呢?接下来就会讨论这些问题。
§7.4.1 Closure of a Set of Functional Dependencies
对于一个函数依赖集 $F$,我们可以证明在 $F$ 外的一些函数依赖也在模式上成立。当我们验证范式的时候,不能只考虑 $F$ 中哦共的,而是考虑所有($F^+$)中的函数依赖。
函数依赖集 $F$ 的闭包 $F^+$ 指的是所有通过 $F$ 能推理得到的函数依赖的集合。
以下的几个推理规则可以加快计算速度,它们叫做 Armstrong 公理:
- 自反律 如果 $\alpha$ 是一个属性集合并且 $\beta \subseteq \alpha$,则 $\alpha \to \beta$ 成立。
- 增广律 如果 $\alpha \to \beta$ 成立,并且 $\gamma$ 是一个属性集合,则 $\gamma\alpha \to \gamma\beta$ 成立。
- 传递律 如果 $\alpha \to \beta$ 成立且 $\beta \to \gamma$ 成立,则 $\alpha \to \gamma$ 成立。
Armstrong 公理是正确且完备的。通过它可以推导以下 3 个推论:
- 合并律 如果 $\alpha \to \beta$ 成立且 $\alpha \to \gamma$ 成立,那么 $\alpha \to \beta\gamma$ 成立。
- 分解律 如果 $\alpha \to \beta\gamma$ 成立,那么 $\alpha \to \beta$ 成立,$\alpha \to \gamma$ 也成立。
- 伪传递律 如果 $\alpha \to \beta$ 成立且 $\gamma\beta \to \delta$ 成立,那么 $\alpha\gamma \to \delta$ 也成立。
上面的三个推论都可以通过基本的 Armstrong 公理来证明,这里赘述一下。
合并律的证明只需要在两个依赖上运用增广律,得到 $\beta\gamma$ 和 $\alpha\beta$ 的形式,再运用一次传递律。
分解律对箭头右侧的两个属性运用自反律,然后运用传递律。
伪传递律使用一次增广律,然后运用传递律即可。
下面展示一个找 $F^+$ 的算法:
1 | F+ = F |
当然,这种算法很可能非常冗长。7.4.2 介绍另一种算法。
§7.4.2 Closure of Attribute Sets
属性集的闭包指的是,某个属性 $\alpha$ 通过函数依赖能够确定的属性集合,记作 $\alpha^+$。
算法如下:
1 | result := α |
属性闭包有如下的用处:
- 测试 $\alpha$ 是不是超码;
- 判断 $\alpha \to \beta$ 是否成立
- 另一种计算 $F^+$ 的方式。
§7.4.3 Canonical Cover
为了花费更小的开销验证函数依赖集 $F$,需要用到正则覆盖这个概念。引入这一概念之前,先定义什么是冗余属性。
冗余属性有两种可能,从左侧删除属性和从右侧删除属性。
先讨论从左侧删除,这一操作会让新的函数依赖集更强。因为原来需要 $m$ 个属性才能确定等式右侧,现在只需要 $m - 1$ 个。
既然函数依赖集更强了,有必要考察,到底被删除的属性是不是冗余的。换言之,删除前比较弱的函数依赖集能否蕴含新的函数依赖集呢?如果可以,则说明属性是冗余的。
从右侧删除道理类似,这一操作会让新的属性集更弱。因为,原来能推出 $m$ 个属性,现在只能推出 $m - 1$ 个了。
原来的函数依赖集更强,那么就需要考察下新的函数依赖集能否蕴含原来的出来。
道理我都懂,但是,怎么判断这种蕴含关系呢?事实上,其实不用查看整个函数依赖集的蕴含关系,毕竟我们只对集合进行了一个属性的删除,只需要考察和这一删除相关的函数依赖是否能被蕴含。
就从左侧删除而言,新的依赖集更强。那么,考察旧的依赖集能否推出新的依赖集。不过,其实只需要在乎一个函数依赖能否被推出。哪一个呢?是让新的依赖集更强的那个,也就是 $(\alpha - A) \to \beta$。
总结一下,我们要验证上述的函数依赖在弱的函数依赖集($F$)中是否能蕴含得到。怎么理解这种强的关系呢?弱的函数依赖集需要 $\alpha \to \beta$ 才能确定 $\beta$,但是新的函数依赖集可以去掉 $\alpha$ 中 $A$ 这一条件。
所以,验证左侧删除的属性是否冗余的方法是,在 $F$ 中计算 $(\alpha - A)^+$,考察其是否包含 $\beta$。
从右侧删除则同理,这次是新的函数依赖集($F’$)更弱。反过来想,$F$ 强在哪里呢?强在 $\alpha \to \beta$,因为 $F’$ 只能做到 $\alpha \to (\beta - A)$。不过更具体些,$F$ 强在 $\alpha \to A$。
那么,就需要在 $F’$ 上验证 $\alpha \to A$ 是否成立。
计算正则覆盖的算法如下:
1 | Fc = F |
有时候,如果一个函数依赖的某一侧全部是冗余的,那么,可以放心地把整个函数依赖删掉。
如 $A \to B$,$A \to C$, $C \to B$ 这三个函数依赖中,第一个就是多余的,因为在 $F’$ 中,仍然能得到 $A \to B$。
当然,正则覆盖不一定是唯一的,但是各个正则覆盖是等价的,就像极大无关组一样。
§7.4.4 Dependency Preservation
学习函数依赖理论后,就可以更准确地刻画依赖保持这一概念。
先引入一个概念,叫做 $F$ 在 $R_i$ 上的限制:令 $F$ 是一个模式 $R$ 上的函数依赖。$F$ 在 $R_i$ 上的限制指的是所有在 $F^+$ (注意是 $F^+$)中只包含 $R_i$ 中属性的函数依赖的集合。
令 $F’ = F_1 \cup F_2 \cup \cdots \cup F_n$,其中 $F_i$ 是 $F$ 在 $R_i$ 上的限制。如果 $F’^+ = F+$,则这个分解是依赖保持分解。
根据定义,一个朴素的算法是这样的:
1 | 计算 F+ |
然而,因为它要计算 $F^+$,所以开销很大。因此,有以下两个解决方案:
- 如果 $F$ 中的每个函数依赖都可以在分解中的某个关系上进行检测,则分解是依赖保持的;
- 指数级的算法。
前者不一定每次都能成功,因此我们更关注后者。
算法:
1 | result = a |
换句话说,每一轮都要对每个 $R_i$ 和 result 的共有元素算一下再 $F$ 下的属性闭包,再交上 $R_i$。如果 result 包含了 $\alpha \to \beta$ 中 $\beta$ 的所有属性,则这一条依赖被保持了。
§7.5 Algorithms for Decomposition Using Functional Dependencies
§7.5.1 BCNF Decomposition
前面讲过,对 BCNF 的验证,只需要根据定义就好了。但是,定义需要计算 $F^+$,开销很大。不过好消息是,有更高效的测试方法。
§7.5.1.1 Testing for BCNF
为了验证一个关系模式 $R$ 是否满足 BCNF,可以简化为诶两种情形:
- 检查非平凡的函数依赖是否违反了 BCNF,即 $\alpha^+ \neq R$;
- 检查一个关系模式 $R$ 是否满足 BCNF,只需要检查所有 $F$ 中的函数依赖即可,不需要检查所有 $F^+$ 的。
这真是一个天大的好消息,然而,第 2 点可能对分解之后的模式不适用。
例:有 $(A, B, C, D, E)$ 上的 $A \to B$ 和 $BC \to D$,分解为 $(A, B)$ 和 $(A, C, D, E)$ 后,看上去后者上没有成立的函数依赖了,但是在 $F^+$ 中却存在 $AC \to D$,令后者不满足 BCNF。
为了解决这一问题,可以应用这一算法:
- 对 $R_i$ 中属性的每一个子集 $\alpha$,计算 $\alpha^+$ 要么包含 $R_i$ 的所有属性,要么不包含 $R_i$ 的任何属性(除了自己)。
对于前者,说明 $\alpha$ 是个超码,OK。对于后者,说明 $F^+$ 中没有非平凡的函数依赖和 $\alpha$ 有关,也 OK。
§7.5.1.2 BCNF Decomposition Algorithm
BCNF 的分解算法,其实和 7.3.1 节的差不多。这里列出来这个算法,兼听则明:
1 | result := R |
说人话,就是对于一个关系模式集合,如果其中有一个关系模式上的函数依赖导致这个关系模式不满足 BCNF,则拆分这个关系模式。
拆分的方法是,先把这个模式从 result 关系模式集合中删掉。
之后,$\beta$ 从原模式中剔除(如果 $\beta$ 中有 $\alpha$ 则保留 $\alpha$),形成第一个新模式。另一个新模式是 $(\alpha, \beta)$。
可以验证这个分解是无损的,因为根据无损分解的定义,分解后两个模式的交集 $\alpha$ 能够在 $(\alpha, \beta)$ 上满足 $\alpha \to \beta$。
§7.5.2 3NF Decomposition
算法如下:
1 | 令 Fc 是 F 的正则覆盖 |
这个算法的思想是,对每个正则覆盖中的函数依赖,都创建了一个模式,满足了 3NF 的定义。同时,它确保了至少有一个模式包含了候选键,从而确保了是无损分解。
§7.5.3 Correctness of the 3NF Algorithm
略。
§7.6 Decomposition Using Multivalued Dependencies
有时候 BCNF 的约束还不够,比如之前我们讲的教授、座机电话和小孩的例子。这种问题出现在多个多值属性交织在一起的情形。
当然,很自然的避免冗余的想法是,把属性分解。如,原来是 $(ID, phone_number, child)$,分解为 $(ID, phone_number)$ 和 (ID, child) 不就好了?但是,这样的分解并没有理论支撑,所以这里引入多值依赖和第四范式 4NF。
§7.6.1 Multivalued Dependencies
函数依赖的目标是消除一些元组的存在,它也叫平等生成依赖,而多值依赖被称为元组生成依赖。
严谨地,令 $r(R)$ 是一个关系模式,$\alpha \subseteq R$ 且 $\beta \subseteq R$,多值依赖 $\alpha \twoheadrightarrow \beta$ 在 $R$ 上成立,
如果对 $r(R)$ 的每个合法实例,对所有的元组对 $t_1$ 和 $t_2$ 使得 $t_1[\alpha] = t_2[\alpha]$,都在 $r$ 中存在 $t_3$ 和 $t_4$,使得
$$
t_1[\alpha] = t_2[\alpha] = t_3[\alpha] = t_4[\alpha]
\
t_3[\beta] = t_1[\beta]
\
t_3[R - \beta] = t_2[ R - \beta]
\
t_4[\beta] = t_2[\beta]
\
t_4[R - \beta] = t_1[ R - \beta]
$$
看起来很复杂,但想要表达的意思是,这一对出现了,和这对属性互补的一对也应该出现。
从多值依赖的定义出发,以下两个规则成立:
- 函数依赖也是多值依赖;
- $\alpha \twoheadrightarrow \beta \implies \alpha \twoheadrightarrow R - \alpha - \beta$
§7.6.2 Fourth Normal Form
第四范式和 BCNF 范式的定义非常像,只是把函数依赖换成了多值依赖。如果一个模式在函数依赖和多值依赖集 $D$ 上满足 4NF,则对 $D^+$ 中的所有形如 $\alpha \twoheadrightarrow \beta$ 多值属性:
- $\alpha \twoheadrightarrow \beta$ 平凡;
- $\alpha$ 是 $R$ 的超码。
§7.6.3 4NF Decomposition
4NF 分解和 BCNF 的分解算法类似,对于导致不满足 4NF 的多值依赖,进行拆分。不再赘述。
§7.7 More Normal Forms
4NF 绝不是最终的范式,还有 PJNF 和 DKNF 等等,但是这两个因为缺少正确和完备的推理,所以用得少。
2NF 只有历史爱好者才会研究。1NF 将会在下一节提到。
§7.8 Atomic Domains and First Normal Form
第一范式解决的是原子取值域的问题。之前我们讲过多值属性,讲过复合属性,这些属性可以再分,因此不是原子属性,不满足 1NF。
当然了,到底原子与否还是要看数据库是怎么用的。比如,整型可以认为是原子了吧?但要是把每一位当做基本单元,还是非原子的。
有时候,非原子的属性很有用,所以现代数据库也支持一些非原子属性。
§7.9 Database-Design Process
§7.9.1 E-R Model and Normalization
如果 E-R 模型选的好,按理来说应该不需要花太大精力正则化。当然,设计的不好另说。
§7.9.2 Naming of Attributes and Relationships
给属性和关系起名,也有讲究。
§7.9.3 Denormalization for Performance
有时候为了性能,需要反范式化。
§7.9.4 Other Design Issues
有时候,一些涉及到时间的设计,crosstabs 并不是很好的选择。
§7.10 Modeling Temporal Data
涉及到时间的数据,比如,某个数据只在某些时间段内有效,需要一些设计原则。在这种情况下,关系、主键并不是永久成立的,而是在一定时间的条件下才成立。