Database 版 (精华区)

发信人: starstar (星语心愿), 信区: Database
标  题: Visual Foxpro 的 数 据 一 致 性 设 计 
发信站: 哈工大紫丁香 (2001年05月19日20:32:24 星期六), 站内信件

浙 江 巨 化 集 团 公 司 江 永 忠 
----      如 何 保 证 数 据 库 系 统 的 数 据 一 致 性 长 期 以 来 一 直
 是 人 们 所 关 心 的 问 题, 传 统 的Xbase 关 系 型 数 据 库 系 统 在 
此 问 题 的 处 理 上 存 在 明 显 的 局 限 性。Visual FoxPro 作 为 一 个
 面 向 对 象 的 数 据 库 系 统, 成 功 地 将 一 套 控 制 信 息 存 储 和
 合 法 检 验 规 则 的 数 据 字 典 引 入 了Xbase 领 域, 从 而 使 数 据 
的 一 致 性 限 制 由 庞 大 的 程 序 代 码 变 成 了 数 据 库 的 一 部 分
, 极 大 地 增 强VFP 的 数 据 处 理 能 力。 

----     " 一 致 性" 这 个 术 语 描 述 了 系 统 中 存 储 的 数 据 资 源
 的 正 确 状 态,VFP 从 数 据 有 效 性、 触 发 器 和 引 用 完 整 性 这 
三 个 方 面 来 维 持 数 据 的 这 种 一 致 性 状 态。 在 此, 我 们 以 一
 个 销 售 系 统 为 例, 阐 述 在VFP 中 数 据 一 致 性 的 设 计 方 法。 


---- 1 . 数 据 的 一 致 性 要 求 

----       VFP 的 数 据 字 典 只 对 数 据 库 有 效, 而 非 针 对 自 由 
表。 就 一 个 销 售 管 理 系 统 而 言, 其 核 心 是 销 售 发 票, 因 此
, 我 们 就 可 以 设 计 一 个 销 售 数 据 库( Sales.DBC), 其 中 主 要
 包 含 以 下 几 个 相 互 关 联 的 数 据 表: 

----      商 品 信 息 表(goods.dbf): 存 储 商 品 的 有 关 信 息。 包
 含 商 品 编 码、 商 品 名 称、 商 品 规 格、 计 量 单 位、 税 率、 参 
考 单 价 等 字 段, 其 中" 商 品 编 码" 为 主 关 键 字。 

----      客 户 信 息 表(customer.dbf): 存 储 有 业 务 关 系 的 客 户
 情 况。 包 含 了 客 户 编 码、 名 称、 地 址、 开 户 银 行、 帐 号、 纳
 税 人 登 记 号 等 字 段, 其 中" 客 户 编 码" 为 主 关 键 字。 

----      销 售 发 票 表(invoice.dbf): 存 储 所 开 发 票 的 信 息。 
包 含 了 发 票 号 码、 开 票 日 期、 客 户 编 码、 备 注、 经 办 人 等 
字 段, 其 中" 发 票 号 码" 为 主 关 键 字, 并 通 过" 客 户 编 码" 与 
客 户 信 息 表 形 成 多 对 一 的 关 联。 

----      销 售 明 细 表(details.dbf): 存 储 与 销 售 发 票 对 应 的
 商 品 的 明 细 信 息。 包 含 了 发 票 号 码、 商 品 编 码、 数 量、 单
 价、 金 额、 税 金 等 字 段, 通 过" 发 票 号 码" 与 销 售 发 票 表 形
 成 多 对 一 的 关 联, 同 时 通 过" 商 品 编 码" 与 商 品 信 息 表 保 
持 多 对 一 的 关 联。 

----     为 确 保 数 据 的 正 确 性, 要 求 有 以 下 的 一 致 性 限 制:
 

开 票 日 期 的 缺 省 值 为 当 天 日 期 

销 售 明 细 表 的 单 价 必 须 大 于 0 

销 售 明 细 表 的 金 额 = 数 量 * 单 价 

客 户 信 息 表 中 的 开 户 行、 帐 号 和 税 号 字 段 均 不 能 为 空 

当 删 除 销 售 发 票 表 的 一 条 记 录 时, 给 出 提 示 信 息, 确 认 后
 删 除 该 记 录, 并 且 对 应 的 销 售 明 细 信 息 自 动 删 除 

当 客 户 信 息 表 的 客 户 编 号 被 修 改 时, 销 售 发 票 表 的 对 应 
客 户 编 号 随 之 改 变 

当 商 品 信 息 表 的 商 品 编 号 被 修 改 时, 销 售 明 细 表 的 对 应 
商 品 编 号 随 之 改 变 

若 在 销 售 发 票 表 中 存 在 某 客 户 编 号, 则 禁 止 删 除 该 客 户 
信 息 

若 在 销 售 明 细 表 中 存 在 某 商 品 编 号, 则 禁 止 删 除 该 商 品 
信 息 
---- 现 在 我 们 就 可 以 通 过VFP 的 数 据 字 典 来 实 现 这 些 一 致 
性 要 求。 

----     2 . 数 据 有 效 性 

----     数 据 有 效 性 分 字 段 级 有 效 性 和 记 录 级 有 效 性, 它 
们 分 别 在Fields Properties ( 字 段 属 性) 和Table Properties( 表 属 
性) 中 进 行 定 义。 

----      在Table Designer( 表 设 计 器) 的 左 下 部 分 可 以 看 到 字
 段 属 性 分 组, 其 中 包 含 了 用 于 字 段 有 效 性 检 测 的 四 个 域
Validation Rule ( 有 效 性 规 则), Validation Text( 字 段 有 效 性 
文 本),Default Value( 缺 省 值) 和Caption( 标 题)。 有 效 性 规 则
 为 一 个 逻 辑 表 达 式, 当 其 返 回 值 为.f. 时, 将 显 示 一 条 内 
容 为 字 段 有 效 性 文 本 的 错 误 信 息。 缺 省 值 为 产 生 新 记 录 
时 该 字 段 的 初 始 化 值。 

----     那 么, 对 于 开 票 日 期 字 段, 可 以 将 其 缺 省 值 属 性 设
 为: 

      Default Value   :date()
     对 于 单 价(price) 字 段, 可 设 为:
     Validation Rule :price>0
     Validation Text :" 商 品 单 价 必 须 大 于 0"
     Default Value   :
     Caption         :" 单 价"

----     字 段 的 有 效 性 规 则 在 焦 点 离 开 字 段 时 即 被 启 动, 
如 果 需 要 同 时 检 测 多 个 字 段 的 情 况, 那 么 就 需 要 用 到 记 
录 级 的 有 效 性 规 则。 记 录 级 有 效 性 规 则 和 字 段 有 效 性 规 
则 一 样 工 作, 只 是 它 在 离 开 记 录 时 启 动, 并 且 只 有 在 项 被
 修 改 时 才 被 检 验。 

---- 点 击Table Designer 中 右 上 角 的Table Properties 按 钮, 你 就 可
 以 在 表 属 性 对 话 框 中 创 建 记 录 级 的 有 效 性 规 则。 对 客 户
 信 息 表, 可 以 建 立 如 下 的 有 效 性 规 则 以 确 保 银 行、 帐 号、
 税 号 均 不 为 空。 

    Validation Rule :!empty(khyh).and.!empty(zh).and.!empty(sh) 
    Validation Text :" 开 户 行、 帐 号 和 税 号 均 不 能 为 空"

---- 3 . 触 发 器 

---- 就 本 质 而 言, 对 于 表 格 里 的 一 个 记 录, 我 们 仅 能 做 三
 件 事 情: 删 除、 修 改 或 建 立, 与 之 对 应 的 三 种 触 发 器 使 我
 们 能 有 效 地 控 制 这 些 事 件 发 生, 它 们 通 常 都 使 用 一 个 函
 数, 当 返 回 的 逻 辑 值 为.t. 就 继 续 执 行, 否 则 就 退 出。 

---- 在 表 属 性 对 话 框 中, 除 了 记 录 有 效 性 规 则 之 外, 还 有
 三 种 触 发 器: INSERT Trigger、UPDATE Trigger 和DELETE Trigger。 如 
果 想 限 制 某 一 事 件 的 发 生, 可 直 接 在 其 域 中 填 入.f., 例 如
: 在UPDATE Trigger 中 填.f., 则 该 表 不 允 许 修 改。 对 于 本 文 例
 示 中 的 销 售 发 票 表, 我 们 可 以 事 先 在 数 据 库 的Stored 
Procedure 中 自 定 义 一 个 函 数Inv_del(), 然 后 在 删 除 触 发 器 中
 填 入: 

    DELETE Trigger:Inv_del()

    自 定 义 函 数Inv_del() 的 代 码 如 下:
    function Inv_del
    *
    *INVOICE.DBF Delete Trigger
    *
    local lnRrt
lnRet=MESSAGEBOX(" 是 否 确 认 删 除
 本 记 录?",4+32+256," 提 示")
    do case
       case lnRet=6
            select DETAILS
            delete for invno=INVOICE.invno
            select INVOICE
            return .t.
       case lnRet=7
            return .f.
endcase

---- 这 样, 当 你 确 认 删 除 销 售 发 票 表 的 一 条 记 录 时, 对 应
 的 销 售 明 细 信 息 将 被 自 动 删 除。 也 许 你 已 经 注 意 到, 本 
例 中 所 示 的 触 发 器, 其 目 的 是 为 了 维 持 数 据 的 完 整 性, 其
 实, 如 果 不 需 要 额 外 的 确 认 提 示, 那 么 在 V F P 中 维 护 
数 据 的 完 整 性 有 更 方 便 的 手 段, 那 就 是 引 用 完 整 性 构 造 
器。 

---- 4 . 引 用 完 整 性 

---- 保 证 所 有 子 记 录 有 一 个 有 效 的 记 录 的 过 程 被 称 为 引 
用 完 整 性, 这 是 确 保 父 子 表 之 间 关 系 的 关 键。 

---- 在Database Designer 中 右 击 鼠 标 打 开 菜 单, 选 择Referential 
Integrity, 进 入 引 用 完 整 性 构 造 器。 该 构 造 器 的 上 部 分 为 
一 个 七 列 的 网 格, 前 两 列 包 含 所 有 父 表 和 子 表 的 名 字, 中
 间 三 列 分 别 显 示 对 更 新、 删 除 和 插 入 操 作 的 引 用 完 整 性
 类 型, 最 后 两 列 为 关 联 表 的 关 键 字。 你 可 以 在 网 格 中 选 
择 一 行( 即 选 中 一 种 关 联), 然 后 为 更 新、 删 除 和 插 入 操 
作 指 定 引 用 完 整 性 的 类 型。 

---- 构 造 器 下 部 分 的 页 框 给 出 了 分 别 对 应 更 新、 删 除 和 插
 入 操 作 的 三 个 页 面, 每 个 页 面 均 提 供 了 三 种 引 用 完 整 性
 类 型(Cascade、Restrict 或Ignore ) 的 单 选 按 钮。 通 俗 地 讲, 这
 三 种 引 用 完 整 性 类 型 的 效 果 分 别 为: 

---- Cascade: 当 父 表 发 生 变 化 时, 在 所 有 子 记 录 中 作 相 同 
的 改 变。 

---- Restrict: 如 果 有 子 记 录, 不 允 许 改 变。 

---- Ignore: 忽 略 子 记 录, 而 只 在 父 记 录 中 修 改。 

---- 至 此, 我 们 可 以 极 其 方 便 地 解 决 本 文 开 始 所 提 的 后 五
 项 数 据 一 致 性 限 制 要 求。 例 如: 

当 客 户 信 息 表 的 客 户 编 号 被 修 改 时, 销 售 发 票 表 的 对 应 
客 户 编 号 随 之 改 变 
---- 从 构 造 器 上 部 网 格 中 选 择 父 表 为Customer 并 且 子 表 为
Invoice 关 联 行 的 Update 列, 并 在Rules for Updating 页 面 中 选 中
Cascade 选 项, 此 时, 网 格 中Update 列 中 的 内 容 应 该 为Cascade,
 连 续 确 认 后 即 可。 

---- 其 它 几 项 要 求 的 解 决 方 法 类 似。 

---- 5 . 几 点 有 益 的 提 示 

---- 虽 然VFP 的 数 据 字 典 的 功 能 极 强, 但 它 也 并 非 是 万 能 的
, 因 此 有 必 要 注 意 以 下 几 个 方 面 的 问 题。 

---- 5 . 1 有 效 性 检 测 的 顺 序 

---- 记 录 有 效 性 规 则 适 所 有 的 记 录, 并 且 无 论 何 时 增 加 或
 修 改 记 录 时 都 被 调 用。 若 使 用 了 字 段 有 效 性 和 触 发 器, 
则 记 录 有 效 性 规 则 必 须 返 回 一 个 逻 辑 值。 记 录 有 效 性 的 
调 用 在 字 段 有 效 性 之 后, 在 触 发 器 之 前。 

---- 5 . 2 缺 省 值 表 达 式 不 能 有 字 段 参 与 

---- 字 段 属 性 中 的 缺 省 值 表 达 式 在 记 录 创 建 时 调 用, 而 不
 是 在 进 入 字 段 时。 对 于" 金 额 = 数 量 * 单 价" 这 样 简 单 的 
限 制, 你 不 能 简 单 地 定 义 金 额 字 段 的Default Value 为" 数 量 *
 单 价", 这 样 你 得 到 的 缺 省 值 将 永 远 是 0。 

---- 5 . 3 更 新 触 发 器 不 能 改 变 启 动 它 的 记 录 值 

---- 同 样 是" 金 额 = 数 量 * 单 价" 的 问 题, 我 们 可 能 会 认 为
 此 时 用 触 发 器 是 理 想 的 时 机, 但 千 万 别 这 么 做, 触 发 器 
不 允 许 改 变 它 自 己 记 录 的 一 个 值, 因 为 这 种 改 变 将 导 致 
更 新 触 发 器 的 再 次 调 用, 进 而 递 归, 形 成 死 锁。 其 实, 这 
个 简 单 的 金 额 问 题 根 本 就 不 能 通 过 数 据 字 典 来 解 决。 

---- 5 . 4 触 发 器 中 不 能 移 动 当 前 记 录 指 针 

---- 当 触 发 器 的 验 证 规 则 试 图 移 动 当 前 工 作 区 中 的 指 针 
时, 你 会 很 不 幸 地 看 到 出 错 信 息"Illegal recursion in rule"。 

---- 5 . 5 自 定 义 函 数 应 事 先 存 储 

---- 当 自 定 义 函 数 在 验 证 规 则 编 辑 框 中 被 引 用 时, 如 果 出
 现 了" 函 数 * * * 没 找 到" 的 出 错 信 息, 通 常 有 两 种 情 形 
引 起 这 个 错 误, 一 是 在 创 建 该 函 数 前 就 输 入 该 函 数 的 调 
用, 二 是 虽 然 在 存 储 过 程 中 创 建 了 该 函 数, 但 没 有 保 存 该
 存 储 过 程。 所 以 一 定 要 保 存 存 储 过 程。 
  


 
 

--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.32]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:205.453毫秒