---- 在 开 发 中, 我 们有 时 会 遇 到 用 一 个DataWindow 来 表 现 数 据 库 中 多 个 表 中 数据 的 情 形, 这 时DataWindow 用 到 的SQLSelect 语 句 是 一 个 多 张 表连 接 的 视 图。 当 我 们 对 这 样 一 个DataWindow 中 的 数 据 进 行修 改 并 提 交 数 据 库 时, 我 们 将 会 发 现 我 们 并 不 能 简 单地 使 用 一 条dw.update() 来 实 现 同 时 对 数 据 库 中 多 张 表 的 修改。
---- 事 实 上, 系 统 在DataWindow 中 提 交 数 据 库 并 生 成UPDATE 语 句 时 所 根 据 的 仍 然 是 图 一这 个 窗 口。 在 以 前 的 章 节 中 我 们 曾 介 绍 过 利 用 这 个 窗口 中 一 些 不 同 的 选 项 实 现 数 据 库 的 并 发 控 制, 这 里 我们 再 讲 一 下 这 个 窗 口 中 的 选 项 对 生 成UPDATE 语 句 的 其 它影 响。
---- 当 我 们 调 用UPDATE 函 数 时, 这 个 窗 口 中 有 四 个 域 将 被 涉 及:
- Where Clause for Update/Delete where 子 句 的 生 成依 据。 这 个 选 项 主 要 是 用 来 进 行 并 发 控 制 的, 这 里 不再 赘 述。
- UpdateableColumns 可 修 改 的 列。 这 是 一 个我 们 将 遇 到 麻 烦 的 地 方。PowerBuilder 只 能 同 时 对 一 张 要 修改 的 表 进 行 管 理, 所 以 我 们 不 能 一 下 子 指 出 所 有 表 中所 有 要 修 改 的 列。 在 这 里 我 们 只 能 指 出 某 一 张 表 中 要修 改 的 列, 以 后 在 程 序 中 用Modify 语 句 依 次 指 定 其 它 每 一张 表 中 要 修 改 的 列。
- Table to Update 将 要 修 改 的 表。PowerBuilder 只支 持 一 张 表 的 修 改, 所 以 我 们 也 只 能 在 这 里 只 指 定 其中 的 某 一 张 表, 其 余 的 表 也 将 要 利 用Modify 语 句 修 改。
- Unique Key Columns 唯 一 键 的 列。 这 也 是 我们 要 注 意 的 地 方, 因 为PowerBuilder 生 成 的UPDATE 语 句 只 是 在 要修 改 的 表 名 中 使 用DATABASE.OWNER.TABLE 这 样 的 全 称, 而 引 用 某列 时 只 是 简 单 指 出 列 名, 而 不 用DATABASE.OWNER.TABLE.COLUMN 这 样的 全 称。 所 以, 如 果 我 们 这 里 用 到 的 唯 一 列 标 识 不 属于 上 面"Table to Update" 中 定 义 的 表 的 列, 这 一 条SQL 语 句将 出 现 语 法 错 误。
---- PowerBuilder 在DataWindow 中 产 生 的UPDATE 语 句 和DELETE 语 句 如 下:
---- ●UPDATE database.owner.table
---- SET column=somevalue,
---- WHERE UniqueKeyColumn=somevalue;
---- ●DELETE FROM database.owner.table
---- WHERE UniqueKeyColumn=somevalue;
---- 在 一 条SQLUPDATE 和DELETE 语 句 中, 所 有 引 用 的 列 名 均 不 使 用 列 的 全 称, 因 此 对 列名 的 确 定 完 全 由update table 来 决 定, 在UPDATE 语 句 中 所 有 修 改属 性 均 设 为TRUE, 而 且 用 户 进 行 过 修 改 的 列 都 将 加 到SET 子 句 中。PowerBuilder 根 据 用 户 对"Where Clause for Update/Delete" 的 选 择 形 成WHERE 子 句, 由 于 系 统 自 动 地 将 多 个 表 中 所 有的 列 都 加 到SET 子 句 和WHERE 子 句 中, 而PowerBuilder 又 是 根 据 用户 指 定 的update table 来 确 定 列, 因 此 我 们 显 然 是 无 法 得 到一 个 准 确 的SQL 语 句 的。 我 们 来 看 这 样 一 个 实 例( 本 表 可以 在PowerBuilderDEOM 数 据 库 中 得 到, 注 意: 如 果 我 们 希 望 某 一列 不 被 修 改, 我 们 可 以 在DataWindow 画 笔 中 将TABorder 设 置 为0):
CUSTOMER.Customer-ID=101CUSTOMER.FirstName=MichaelsCUSTOMER.LastName=DevlinCUSTOMER.Address=3114 Pioneer AvenueSALES-ORDER.ID=2001SALES-ORDER.order-date=09/14/94我 们 将 其 改 为:CUSTOMER.Address=1905 Maple AvenueSALES-ORDER.order-date=12/11/94
---- 如 果 我 们 只 是用dw.update() 语 句 来 形 成UPDATE 语 句,PowerBuilder 将 自 动 构 造 成 这样 的 一 条 语 句:
---- 上 述 三 条SQL 语句 在 提 交 数 据 库 时 都 将 产 生"Invalid column name ‘id' " 的错 误, 很 明 显,"id" 这 一 个 字 段 并 不 在custumer 这 一 张表 中。 此 外SALES-ORDER 这 张 表 的 内 容 并 没 有 进 行 修 改。
---- 为 真 正 实 现 对多 表 数 据 的 修 改, 我 们 可 以 编 写 这 样 一 个 函 数f-MUpdate()。
integer f-MUpdate(a-dw,as-update-table)a-dw-DataWindow 名 称;as-update-table- 将 要 修 改 的 表 名 的 全 称。Long ll-ipos,ll-maxcol,iString ls-colnam,ls-mod,ls-table-name,ls-err,ls-updatekeyll,ls-qualifier=""// 从 传 递 的 参 数 中 分 离 出 表 名 和 域 名ll-ipos=Pos(as-update-table," ·",l)If(ll-ipos >0)Thenls-qualifier =Left(as-update-table,ll-ipos)as-update-table=Mid(as-update-table,& ll-ipos+1)ll-ipos=Pos(as-update-table," ·",l)If(ll-ipos >0)Thenls-qualifier=ls-qualifier+&Left(as-update-table,ll-ipos)as-update-table=Mid(as-update-table,& ll-ipos+1)end IfEnd If// 得 到 这 个DataWindow 包 含 列 的 数 量
ls-err=a-dw.object.DataWindow.Column.Countll-maxcol=Integer(Is-err)If(ll-maxcol <1)ThenReturn 1
End IF
---- // 确 认DataWindow 中的 每 一 列 是 否 属 于 要 修 改 的 表 中 的 列, 如 是 将 其update 属性 设 为 Yes, 否 则 为No.
FOR i=1 To ll-maxcol
ls-mod="#"+String(i)+".Name"ls-colnam=a-dw.Descibe(ls-mod)ls-table-name=a-dw.Descibe(ls-colnam+&".dbName")ls-table-name=Left(ls-table-name,&)(Pos(ls-table-name," ·",l)-l))
If(Upper(as-update-table)=Upper(ls-table-name))Thenls-mod=ls-colnam+".Update=Yes"Else// 如 果 该 列 不 在 可 修 改 的 表 中,// 而 其 为 主 键 的 属 性 为TRUE// 将 其 列 名 存 在ls-updatekey[ ] 中// 并 将 其 主 键 的 属 性 设 为FALSE。// 由 于PB 不 保 留 列 的 全 名, 我 们 不 能。// 保 留 非 修 改 表 的 键 的 名 称。// 所 以 我 们 将 其 保 留 在 数 组 之 中, 以 便 其 恢 复If(Upper(a-dw.Descibe(ls-colnam+".Key"))=" YES")Thenls-updatekey[UpperBound(ls-updatekey[ ])+1]=ls-colnamls-mod=ls-colnam+".Key=No"If(a-dw.Modify(ls-mod) < >"")ThenReturn-2End IfEnd Ifls-mod=ls-colnam+".Update=No"End IF
// 确 认 修 改 是 否 成 功If(a-dw.Modify(ls-mod) < >"")ThenReturn-2End IF
NEXT
// 将 修 改 表 名 设 置 为 全 称a-dw.object.Data Window.Table.UpdateTable=ls-qualifier+as-update-table
// 修 改DataWindow
If(a-dw.Update(TRUE,FALSE) < >1)ThenReturn-5Else// 将DataWindow 恢 复 为 其 原 来 的 状 态ll-maxcol=UpperBound(ls-updatekey)FOR i=l to ll-maxcolls-mod=ls-updatekey[i]+".key=Yes"If(a-dw.Modify(ls-mod) < >"")ThenReturn-6End IfReturn 0End If
---- 调 用 这 一 函 数时 应 遵 守 以 下 规 则:
- 保 证 数 据 的 参 照 完 整 性, 应 当 先 修改 父 表 后 修 改 子 表;
- 在DataWindow 画 笔 中 为 每 张 表 建 立 唯 一主 键;
- 在 图 一 窗 口 中, 将 该DataWindow 设 为 允 许修 改;
- 指 定 所 涉 及 的 任 意 一 张 表 为 修 改 表, 表 中 的 任 一 列 为 可 修 改 列。 以 保 证DataWindow 有 修 改 权, 这样 我 们 调 用 的 函 数 就 可 以 覆 盖 这 一 设 置。
- 不 要 将 并 发 控 制 选 为key and modified columns, 这 个 函 数 无 法 在 这 一 条 件 下 工 作。
- 将 表 名 的 全 称DATABASE.OWNER.TABLE 传 递 给 这个 函 数, 特 别 是 在 这 个DataWindows 是 对 多 个 数 据 库 进 行 操作 时。
---- 在 上 例 中, 我 们可 以 这 样 调 用 这 个 函 数
f-MUpdate(dw-l," dbo.sales-order")f-MUpdate(dw-l," dbo.customer")