概述
VFP 的 SQLEXEC() 函数允许通过 ODBC 从任何数据源下载数据. 与远程视图不同, SQL Pass-Through 方法没有提供默认的 (自动) 设置来在客户端的游标中的数据改变后从返回的游标更新服务器的数据. 但是, 可以自定义更新所必须的属性来达到更新的目的.
首先, 建议阅读 MSDN 中关于 SQL Pass Through 命令的章节, 特别是解释本文中使用的属性的章节: Tables, KeyFieldList, UpdatableFieldList, UpdateNameList, SendUpdates. 这五个属性是更新远程数据所需要的基本属性.
本文只是一个让 MS SQL Server ODBC 数据源 SPT 游标可更新的例程的源代码. 因数据库的格式表和字段的规范不同, 因此它会需要修改以适应其它数据源. 另外, 示例是非常简单和缺乏处理一些如字段包含空格和一些可能的问题. 这是一个你可以用来改进的示例. 它以概不负责的方式提供.
很容易看到为准备这五个属性来使游标可更新必须的格式. 创建一个简单的数据库, 在数据库中连接到数据源, 然后用必要的 (或简单的) 查询创建视图. 打开视图并用 CursorGetProp() 函数来查看提及的五个属性中保存了什么. 这将给你很多关于你将如何为 SQL Pass-Through 准备这些属性的信息.
只要你愿意你可以组织在服务器上更新你的数据. 例如, 从一个表中或视图中查询数据, 并更新数据到另一个表. 在后端映射字段到另一个字段. 创建不是由查询返回的, 在客户端预填充并只用于更新数据的自定义字段. 用非常复杂的 SELECT 语句查询数据, 执行 SELECT 语句, T-SQL 脚本或储存过程, 然后从客户端更新数据 (这在远程视图中是完全不可能的, 但 SQL Pass-Through 确是可能的).
描述
* 转换 SQL Path Through 游标或远程视图游标为可更新的和 fetchable 游标.
* 参数: 游标名 (必需)
* ID 字段名 (必需)
* SQL server 上的源表名 (必需)
* 逗号分隔的字段,表达式字段列表 (可选)
* logical .T. 是否 ID 字段也是可更新的. (可选)
* NOTE - 要正确地使用该例程, 所有游标中的字段应该与服务器上的字段匹配.
* NOTE2 - 你可以手动地指定 "UpdateNameList" 来匹配游标字段和服务器上的字段.
* 该列表必须是以下格式:
* {游标字段} {服务器表}.{服务器字段}[, ...]
* 注意 '','' 后的空格.
lparameters pcCursorName, pcIDFieldName, pcSourceTables, pcNONUpdatableFields,;
plUpdateIDField
if cursorgetprop(''SourceType'', m.pcCursorName)#2
* 游标不兼容
return .F.
endif
if !empty(cursorgetprop("Tables",m.pcCursorName))
* 已经是可更新的了
return .T.
endif
m.pcSourceTables = chrtran(m.pcSourceTables, '' '', '''')
local llResult, lnFCount, lcFieldsList, lcField, lcKeyField, m.lcUPDFieldsList, lcNewList
m.llResult = CursorSetProp("Tables", ;
iif("." $ m.pcSourceTables, m.pcSourceTables, ;
substr( STRTRAN( '','' + m.pcSourceTables, '','', '',dbo.''), 2) ), m.pcCursorName)
if m.llResult
&& prepare strings for exact substring search
if !(vartype(m.pcNONUpdatableFields) == "C")
m.pcNONUpdatableFields = ""
endif
if !empty(m.pcNONUpdatableFields)
m.pcNONUpdatableFields = '','' + upper(chrtran(m.pcNONUpdatableFields,'' '','''')) + '',''
endif
m.pcIDFieldName = chrtran(m.pcIDFieldName,'' '','''')
m.lcKeyField = '','' + upper(m.pcIDFieldName) + '',''
if '','' $ m.pcSourceTables
m.pcSourceTables = left(m.pcSourceTables,at('','',m.pcSourceTables)-1)
endif
if ''.'' $ m.pcSourceTables
m.pcSourceTables = substr(m.pcSourceTables, at(''.'',m.pcSourceTables)+1)
endif
m.lcFieldsList = '''' && fields for UPDATENAMELIST
m.lcUPDFieldsList = '''' && fields for UPDATABLEFIELDLIST
for m.lnFCount = 1 to FCOUNT(m.pcCursorName)
m.lcField = FIELD(m.lnFCount, m.pcCursorName)
if !('','' + m.lcField + '','' $ m.pcNONUpdatableFields)
m.lcFieldsList = m.lcFieldsList + '','' + m.lcField + '' dbo.'' +;
m.pcSourceTables + ''.'' + m.lcField
if !('','' + m.lcField + '','' $ m.lcKeyField)
m.lcUPDFieldsList = m.lcUPDFieldsList + '','' + m.lcField
endif
endif
endfor
m.lcNewList = cursorgetprop("UpdateNameList", m.pcCursorName)
if !empty(m.lcNewList) and ''.'' $ m.lcNewList
m.lcNewList = STRTRAN(m.lcNewList, '', '', '','')
m.lcNewList = STRTRAN(m.lcNewList, '' '', '' dbo.'')
m.llResult = CursorSetProp("UpdateNameList", ;
STRTRAN(m.lcNewList, '','', '', ''), ;
m.pcCursorName)
else
m.llResult = CursorSetProp("UpdateNameList", substr(m.lcFieldsList, 2),;
m.pcCursorName)
endif
if m.llResult
m.llResult = CursorSetProp("KeyFieldList", m.pcIDFieldName, m.pcCursorName)
if m.llResult
m.llResult = CursorSetProp("UpdatableFieldList",;
substr(m.lcUPDFieldsList,2), m.pcCursorName)
if m.llResult
m.llResult = CursorSetProp("SendUpdates", .T., m.pcCursorName)
endif
endif
endif
endif
return m.llResult