VFP+SQL编程方法讨论与经验分享

2024-03-25 09:58

本文主要是介绍VFP+SQL编程方法讨论与经验分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://community.csdn.net/Expert/topic/4126/4126818.xml?temp=6.805056E-02


VFP是一个简单实用的编程工具,但数据库一般用其本身的DBF数据库,对于SQL可能每个人都用不同的看法,各位高手有什么好的方法、经验、建议全都拿出来,供大家分享,谢谢!

以下是我平时对SQL的使用点滴,欢迎各位指点!

**************************************************************
*-- vfpsql
*-- parameters :tcDatabase,tcServer,tcUserId,tcPassword
*-- Sql Connect
**************************************************************
FUNCTION VFPSql()
PARAMETERS tcDatabase,tcServer,tcUserId,tcPassword

SET MULTILOCKS ON

LOCAL lcSqlConnectStr
PUBLIC gcSqlConnectstr
IF TYPE("gcSqlConnectstr")<>"C"
gcSqlConnectstr = ""
ENDIF
lcSqlConnectStr =''

IF TYPE("_gnSqlConnectHandle") = "N" AND _gnSqlConnectHandle > 0
disVFPSql()
ENDIF
PUBLIC _gnSqlConnectHandle
_gnSqlConnectHandle =0
IF PARAMETERS()>=3 AND VARTYPE(tcDatabase)='C' AND VARTYPE(tcServer)='C' AND VARTYPE(tcUserId)='C'
IF EMPTY(tcPassword)
tcPassword = ''
ENDIF
lcSqlConnectStr ="driver={Sql Server};Database=&tcDatabase;server=&tcServer;uid=&tcUserId;pwd=&tcPassword"
_gnSqlConnectHandle = SQLSTRINGCONNECT(lcSqlConnectStr)
ELSE
IF gcSqlConnectstr <> ""
lcSqlConnectStr = gcSqlConnectstr
_gnSqlConnectHandle = SQLSTRINGCONNECT(lcSqlConnectStr)
ENDIF
ENDIF
gcSqlConnectstr = lcSqlConnectStr
LOCAL iLoopCount
iLoopCount = 1
DO WHILE _gnSqlConnectHandle <= 0 AND iLoopCount <=3
DO prgDataConnect
iLoopCount = iLoopCount + 1
ENDDO
RETURN _gnSqlConnectHandle>0
*- VFPSQL END

************************************************
*--   disVFPSql()
*--   Sql Disconnect
************************************************

FUNCTION disVFPSql()
IF TYPE("_gnSqlConnectHandle")<>'N' OR _gnSqlConnectHandle<=0
Return
ENDIF
SQLDISCONNECT(_gnSqlConnectHandle)
RELEASE _gnSqlConnectHandle
RETURN
*- DisVFPSql END

***************************************
*-- SqlDo()
*-- PARAMETERS tcSqlString: 查询语句
*--tcCurName : 结果集存放表
*- 功能: 执行查询
**************************************
FUNCTION SqlDo
LPARAMETERS tcSqlString,tcCurName
LOCAL lnReturn

*-- 检查连接
IF TYPE("_gnSqlConnectHandle")<>"N" or _gnSqlConnectHandle<=0
IF !vfpsql()
*-- 连接失败,返回 0
RETURN 0
ENDIF
ENDIF
IF TYPE('tcSqlString')<>'C' OR EMPTY(tcSqlString)
RETURN 0
ENDIF
IF EMPTY(tcCurName) OR TYPE("tcCurName") <>'C'
lnReturn = SQLEXEC(_gnSqlConnectHandle,tcSqlString)
ELSE
lnReturn = SQLEXEC(_gnSqlConnectHandle,tcSqlString,tcCurName)
ENDIF
RETURN lnReturn
*- SqlDo END


*-- Opendb
********************************************************
*-- OpenDB
*
*- 功能:打开table Or View
*
*-参数说明 tcCurName   : 临时表名
*-         tcSqlTblName: Sql数据表名(默认tcCurName)
*   tcFldsList   : 字段列表(默认为全部 *)
**********************************************************
FUNCTION OpenDB
LPARAMETERS tcCurName,tcSqlTblName,tcFldsList
IF VARTYPE(tcCurName)<>"C"
MESSAGEBOX("参数错误,不能打开数据表或视图!",48,"错误")
RETURN .F.
ENDIF
IF EMPTY(tcSqlTblName)
tcSqlTblName = tcCurName
ENDIF
IF EMPTY(tcFldsList)
tcFldsList = "*"
ENDIF
*-- 执行查询
lnReturn = Sqldo("select &tcFldsList From &tcSqlTblName ","&tcCurName.")
*-- 打开开放式表缓冲
IF lnReturn > 0
cursorsetprop("buffering",5, "&tcCurName.")
ENDIF
RETURN lnReturn>0
*-- OpenDB END


********************************************************
*-- CloseDB
*
*- 功能:关闭table Or View
*
*-参数说明 tcCurName   : 临时表名
*-
**********************************************************
FUNCTION CloseDB
LPARAMETERS tcCurName
IF VARTYPE(tcCurName)<>"C"
MESSAGEBOX("参数错误,非法数据表或视图!",48,"错误")
RETURN .F.
ENDIF

IF SELECT(tcCurName) > 0
USE IN &tcCurName
ENDIF
RETURN .T.
*-- CloseDB END

 

**********************************************************************
*- SaveData
*--
*-- 参数说明 tcCurName   : 临时表名
*--         tcSqlTblName: Sql数据表名(默认tcCurName)
*--   tcKeyFld   : 关键字段名称(一定要有,否则默认为ID),
*-- 程序要根据该字段来定位记录,
*-- 功能:从临时表保存到 SQL数据库中,注意,临时表要启用缓冲模式
**********************************************************************
FUNCTION savedata
LPARAMETERS tcCurName,tcSqlTblName,tcKeyFld
LOCAL lcFldList,lcFldListTmp,lnNextModifyRec,lcFldValue,lnFldCnt
LOCAL lcSqlString,lnSqlReturn
LOCAL lcOldAlias,lcOldDele,lcOldSafe
LOCAL laFlds(1)
LOCAL  i,llNeedAddDH

IF TYPE("tcCurName")<>'C' OR ;
EMPTY(tcCurName) OR ;
SELECT(tcCurName)=0
MESSAGEBOX("表名错误!",48,"错误提示")
RETURN
ENDIF
lcOldDele = SET("Deleted")
lcOldSafe = SET("Safety")
SET DELETED OFF
SET SAFETY OFF
lcOldAlias = ALIAS()

SELECT (tcCurName)
IF cursorgetprop('buffering')=1
MESSAGEBOX("数据表没有启用缓冲模式,程序无法识别!",48,"错误提示")
RETURN .F.
ENDIF
IF EMPTY(tcSqlTblName) OR TYPE("tcSqlTblName")<>'C'
tcSqlTblName = tcCurName
ENDIF
IF EMPTY(tcKeyFld)
tcKeyFld = 'Id'
ENDIF

lnFldCnt = AFIELDS(laFlds)
lcFldList = ''
FOR i = 1 TO lnFldCnt
IF !EMPTY(lcFldList)
lcFldList = lcFldList +','
ENDIF
lcFldList = lcFldList + laFlds(i,1)
ENDFOR
lnNextModifyRec = GETNEXTMODIFIED(0)
lnSqlReturn = SQLDO("BEGIN TRANSACTION")
IF lnSqlReturn =-1
RETURN .F.
ENDIF

DO WHILE lnNextModifyRec <>0
GO lnNextModifyRec
lcFldListtmp = ''
lcSqlString = ''
DO case
CASE DELETED()&&删除
lcSqlString = "Delete From "+tcSqlTblName + IIF(TYPE(tcKeyFld) $ "NI",;
" Where &tcKeyFld. = "+TRANSFORM(EVALUATE(tcCurName+".&tcKeyFld.")),;
" Where &tcKeyFld. = '"+TRANSFORM(EVALUATE(tcCurName+".&tcKeyFld."))+"'")

CASE RECNO()<0  &&新增
lcSqlString = "" &&"insert into "+tcSqlTblName +" ("+lcFldList+") Values ("
FOR i = 1 TO lnFldCnt
lcFldValue = EVALUATE(tcCurName+'.'+laFlds(i,1))
IF EMPTY(lcFldValue)
Loop
ENDIF
IF !EMPTY(lcFldListtmp)
lcFldListtmp = lcFldListtmp +','
ENDIF
lcFldListtmp = lcFldListtmp + laFlds(i,1)
DO case
CASE laFlds(i,2)$'NI'
lcFldValue = TRANSFORM(lcFldValue)
CASE laFlds(i,2)='L'
IF lcFldValue
lcfldValue = '1'
ELSE
lcfldValue = '0'
ENDIF

OTHERWISE
lcFldValue ="'"+ TRANSFORM(lcFldValue)+"'"
ENDCASE
IF !EMPTY(lcSqlString)
lcSqlString =lcSqlString +','
ENDIF
lcSqlString =lcSqlString + lcFldValue
ENDFOR
lcSqlString ="insert into "+tcSqlTblName +" ("+lcFldListtmp+") Values ("+lcSqlString +')'
OTHERWISE
lcSqlString = "Update "+tcSqlTblName +" set "
llNeedAddDH = .F.
FOR i = 1 TO lnFldCnt
IF GETFLDSTATE(i)<>2
LOOP
ENDIF
DO case
CASE laFlds(i,2)$'NI'
lcFldValue = laflds(i,1)+'='+TRANSFORM(EVALUATE(tcCurName+'.'+laFlds(i,1)))
CASE laFlds(i,2)='L'
IF EVALUATE(tcCursorName+'.'+laFlds(i,1))
lcfldValue = laflds(i,1)+'=1'
ELSE
lcfldValue = laflds(i,1)+'=0'
ENDIF
OTHERWISE
lcFldValue =laflds(i,1)+" = '"+ TRANSFORM(EVALUATE(tcCurName+'.'+laFlds(i,1)))+"'"
ENDCASE
IF NOT llNeedAddDH
llNeedAddDH = .T.
Else
lcSqlString =lcSqlString +','
ENDIF
lcSqlString =lcSqlString + lcFldValue
ENDFOR
lcSqlString =lcSqlString + IIF(TYPE(tcKeyFld) $ "NI",;
" Where &tcKeyFld. = "+TRANSFORM(EVALUATE(tcCurName+".&tcKeyFld.")),;
" Where &tcKeyFld. = '"+TRANSFORM(EVALUATE(tcCurName+".&tcKeyFld."))+"'")
ENDCASE

lnSqlReturn = sqlDo(lcSqlString)
IF lnSqlReturn=-1
SQLDO("Rollback")
MESSAGEBOX("保存失败!"+CHR(13)+CHR(10)+lcSqlString)
_cliptext = lcSqlstring
TABLEREVERT(.T.)
RETURN .F.
ENDIF
lnNextModifyRec = GETNEXTMODIFIED(lnNextModifyRec)
ENDDO
lnSqlReturn = SQLDO(" COMMIT TRANSACTION ")
TABLEUPDATE(.T.)
IF !EMPTY(lcOldAlias) AND ALIAS()<>lcOldAlias
SELECT (lcOldAlias)
ENDIF
IF lcOldDele='ON'
SET DELETED on
ENDIF
IF lcOldSafe = 'ON'
SET SAFETY on
ENDIF
RETURN .T.

*-- 调用SQL设置
PROCEDURE prgdataconnect
LOCAL lcDataPath,lcTextString
LOCAL loForm
_gnSqlConnectHandle = 0
IF _gnSqlConnectHandle <=0
loFormCon = CREATEOBJECT("fmConnect")
loFormCon.Show(1)
ENDIF
**********************************************
*- 定义连接表单
*********************************************
DEFINE CLASS fmConnect as Form
 &&-"driver={Sql Server};Database=Hjasset;server=jianqy;uid=sa;pwd=")
Caption = 'SQL服务器连接'
Width = 300
Height = 182
BorderStyle = 2
maxbutton = .F.
minButton = .F.
ShowWindow = 1
Autocenter = .T.
alwaysontop = .T.
desktop = .T.
windowType = 1
Name = 'fmConnect'
ADD OBJECT lblServer as label WITH Caption = '服务器:',;
   left = 15,;
   Width = 80,;
   Top = 20,;
   Height= 22,;
   Alignment = 1,;
   BackStyle = 0,;
   Visible = .T.
  
ADD OBJECT txtServer as textbox WITH left = 95,;
     Width = 160,;
     Top = 17,;
    Height= 25,;
    Value = '(Local)',;
   Visible = .T.
ADD OBJECT lblDatabase as label WITH Caption = '数据库:',;
   left = 15,;
   Width = 80,;
   Top = 50,;
   Height= 22,;
   Alignment = 1,;
   BackStyle = 0,;
   Visible = .T.
ADD OBJECT txtDatabase as textbox WITH left = 95,;
     Width = 160,;
     Top = 47,;
    Height= 22,;
    Value = 'pubs',;
   Visible = .T.
  
ADD OBJECT lblUid as label WITH Caption = '用户名:',;
   left = 15,;
   Width = 80,;
   Top = 80,;
   Height= 22,;
   Alignment = 1,;
   BackStyle = 0,;
   Visible = .T.
ADD OBJECT txtUid as textbox WITH left = 95,;
   Width = 160,;
   Top = 77,;
   Height= 22,;
   Value = 'sa',;
   Visible = .T.
ADD OBJECT lblPwd as label WITH Caption = '密 码:',;
   left = 15,;
   Width = 80,;
   Top = 110,;
   Height= 22,;
   Alignment = 1,;
   BackStyle = 0,;
   Visible = .T.
ADD OBJECT txtPwd as textbox WITH left = 95,;
     Width = 160,;
     Top = 107,;
    Height= 22,;
    passwordchar= '*',;
    Value = '',;
   Visible = .T.
ADD OBJECT btnConnect as Commandbutton WITH left = 35,;
     Width = 100,;
     Top = 150,;
    Height= 22,;
    Value = '',;
   Visible = .T.,;
   Caption = '连 接'
ADD OBJECT btnCancel as Commandbutton WITH left = 165,;
     Width = 100,;
     Top = 150,;
    Height= 22,;
    Value = '',;
   Visible = .T.,;
   Caption = '取 消'
ADD OBJECT cntShp1 as Container WITH left = 0,;
     Width = 300,;
     Top = 142,;
    Height= 1,;
   Visible = .T.,;
   SpecialEffect = 1  
PROCEDURE destroy

PROCEDURE load

PROCEDURE init

PROCEDURE txtPwd.Keypress
LPARAMETERS nKeyCode, nShiftAltCtrl
IF nKeyCode = 3 OR nKeyCode = 24
NODEFAULT
ENDIF
PROCEDURE btnConnect.click
LOCAL lcServer,lcDatabase,lcUid,lcPwd,lcSqlStrConnect
lcServer = ALLTRIM(thisform.txtServer.Value)
lcDatabase = ALLTRIM(thisform.txtDatabase.Value)
lcUid = ALLTRIM(thisform.txtUid.Value)
lcPwd = ALLTRIM(thisform.txtPwd.Value)
IF EMPTY(lcServer)
MESSAGEBOX("请输入SQL服务器的名称!",48,"系统提示")
thisform.txtServer.setfocus
RETURN
ENDIF
lcSqlStrConnect="driver={Sql Server};"+;
IIF(EMPTY(lcDatabase),'',"Database="+lcDatabase+";")+;
"server="+lcServer+";uid="+lcUid+";pwd="+lcPwd
_gnSqlConnectHandle = SQLSTRINGCONNECT(lcSqlStrConnect)
gcSqlConnectstr = lcSqlStrConnect
ON ERROR
IF _gnSqlConnectHandle > 0
MESSAGEBOX("连接成功!",64,"SQL连接")
thisform.Release
ELSE
MESSAGEBOX("连接失败!"+CHR(13)+CHR(10)+"请重新输入连接项",64,"SQL连接")
thisform.txtServer.setfocus
ENDIF
PROCEDURE btnCancel.click
thisform.Releas*-- 以pubs 为例
&&连接SQL
vfpsql()
&&打开authors
opendb("authors")
&&修改
repl au_lname with 'dfjkdjfkdj' for au_id = '722-51-5454'
&&保存到SQL
savedata("authors","authors","au_id")

一、采用ado方式,可能代码会很多,但是会很灵活,而且可以让前台没有dbc文件了,如果采用远程视图方式,就不会写这么多代码了,但是必须要定义DBC(数据库)用于保存远程视图及连接等,前一种方式,楼主已经写的比较通俗简明了,我对后一种简单补充一下。
1.建立数据库,然后建立与后台数据库的连接(当然可以用INI文件等先保存定义,然后动态设定)
2.建立远程视图表
3.打开表同时设置表的缓冲级别,一般为行缓冲和表缓冲
4.修改后如果保存=tableupdate(.t.),放弃=tablerevert(.t.)
5.可以通过捕获返回的错误信息,显示给用户.如
IF TABLEUPDATE(.T.)
=MESSAGEBOX("更新完毕!",48,"系统信息")
ELSE
=AERROR(ERR)
IF !EMPTY(ERR(2))
=SHOWWARN("错误信息:"+ALLTRIM(SUBSTR(UPPER(ERR(2)),AT('[SQL SERVER]',UPPER(ERR(2)),1)+12)))
ENDIF
XX=SHOWCHOICE("是否取消此次操作?")
IF XX=1
=TABLEREVERT(.T.)
ELSE
RETURN
ENDIF
ENDIF
=REQUERY()
二、当然了,现在最好使用的还是CursorAdapter方式,它即有了ado方式的灵活,又有了远程视图的简易,还有了后台升级方便等优点。具体使用请参考网上的一些说明,在些从简了。



 
ENDDEFINE


这篇关于VFP+SQL编程方法讨论与经验分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/844649

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal