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)
页面执行时间:213.694毫秒