ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: hyefeifei

[原创] 再讲ADO

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2016-4-22 11:54 | 显示全部楼层
本帖已被收录到知识树中,索引项:ADO技术
好东西呀,先顶!!!!

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-4-22 15:03 | 显示全部楼层
本帖最后由 hyefeifei 于 2016-5-16 15:08 编辑


  下面简单讲一下upEmp的代码,先插点题外话,说几句错误处理,我之前的贴子里推荐并提供下载了二本书,一本为《Excel专业开发》,另一本为《VBA高级开发指南》,这两本书里都提供了复杂的错误处理代码,拷过来就可以用,大家可以找找。示例代码(upEmp)中仅做了简单的错误处理,为使初学者明白,说明见图:

1.jpg

  下面开始摘要讲一下sub upEmp程序:

  1. Open strSQL, Conn, adOpenStatic, adLockOptimistic, adCmdText
  当程序执行完这句时,value, OriginalValue, UnderlyingValue三个属性的值均已经确定,为1100。

  2. rst.Properties("Update Resync") = adResyncConflicts

  Recordset有一个属性集合Properties,这个集合中的属性来自于:
  a: 当使用客户端临时表时,即cursorlocation值为aduseclient时,临时表引擎提供的属性。
  b: 当你连接不同的数据库时(sqlserver,oracle,access等),不同的数据库各自支持的属性。

  Properties集合中有一个Update Resync属性,它来自于a,值可以是下表中的常量:

常量
描述
adResyncNone
0
修改后不取回数据
adResyncAutoIncrement
1
默认值,取回新记录的自动增加字段的值
adResyncConflicts
2
取回由于开放式更新冲突导致更新失败的记录的基本值
adResyncUpdates
4
向数据库递交更新后,取回这些记录的当前内容
adResyncInserts
8
向数据库递交新记录后,取回它们的当前内容

  这里我们用的是红字处的值,作用下面会讲到。

  3.  !sal = !sal + 500
  当程序执行到这句时,value的值变为1600,OriginalValue, UnderlyingValue的值还都为1100。

  4.  .Update
  当程序执行到这句时,ado会拿 UnderlyingValue 的值,与此刻数据库sal字段的值去比,如果之前没人修改过数据库sal字段的值,则顺利更新数据库。
  如果假如有人提前把数据库这个字段的值改为了1700,那么UnderlyingValue的值1100就会与数据库的值不同,此时会发生什么?
  这个时候,ado会提示错误信息,错误信息见前面的贴图,同时ado还会在数据库上执行 select * from emp where empno=7876并返回数据。
  当执行完select * from emp where empno=7876后,此时UnderlyingValue的值变为1700,与数据库端的值相同了。

  5. 看这句:'rst!sal.Value = rst!sal.Value - rst!sal.OriginalValue + rst!sal.UnderlyingValue
  你看这句是被注释掉的,所以直接执行下句Resume,然后会跳到.Update,此时因为Underlyingvalue的值为1700,与数据库端的值是相同的,所以会顺利更新数据库,数据库端的sal值会被更新为1600。

  假如天不凑巧,此时此刻有人又先你一步把数据库端的值由1700改为了1800,会发生什么?这你自己去想。
  假如这句没被注释掉,会发生什么?

  现在我们看一下此时三个属性的值 value:1600,OriginalValue:1100,UnderlyingValue:1700
  所以这句执行完,rst!sal.value的值会变为1600-1100+1700即2200。也就是说,不管别人怎么修改此人的工资,我都会再此基础上给此人加500元工资。

  这句执行完,会跳到.Update,执行完后,数据库端的sal值修改为2200。

  待续..............

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-4-24 18:07 | 显示全部楼层
本帖最后由 hyefeifei 于 2016-5-16 15:09 编辑

假如数据库表没有主键怎么办?

  见图:

Image 009.jpg


  前面我们讲到,你用临时表更新数据库时,当执行到update时,ado会取得当前记录的主键值,然后会以主键和要修改字段的原值为条件,进行修改,如上图。

  但是,如果数据库表没有主键呢?

  你可以执行下面的语句:

  SELECT * INTO empn FROM emp

  在数据库中把emp表复制为empn,这个复制出来的表,会有原原表的结构及数据,但主键,外键,约束之类的不会被复制。

  以这个表为例,看下面程序:
  
strSQL = "select ename, sal from empn"
With rst
    .cursorlocation = adUseClient
    .Open strSQL, Conn, adOpenStatic, adLockOptimistic, adCmdText
    .Properties("Update Criteria") = adCriteriaAllCols
    .Find "ename='ADAMS'"
    !sal = !sal + 500
    .Update
End With

  当程序执行到Update,ado会把什么语句提交给服务器呢?注意此时empn没有主键。实际上ado会把select后面出现的字段的值都做为条件,语句如下:

  UPDATE empn SET sal=1600 WHERE ename='ADAMS' AND sal=1100

  当把这个语句提交给数据库时,可想而知,所以叫ADAMS且工资为1100的人工资都会加500,同时,会返回出错信息:“键列信息不足或不正确。更新影响到多行”。而此时数据库已经更改了,
这当然不是我们希望的。

  怎么解决呢?

  a.给表加上主键。b.使用 select * from empn 取回所有字段数据,这个以所以字段为条件,绝不会有重复记录了。

  大家注意到程序中有 .Properties("Update Criteria") = adCriteriaAllCols一句,其实这句在这里并没什么作用,那它在哪里起作用,又起到什么作用呢?待续..........

TA的精华主题

TA的得分主题

发表于 2016-4-27 20:43 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
下午下载安装了SQL Server Express 2014,英文版的,一头雾水,不知如何下手

TA的精华主题

TA的得分主题

发表于 2016-4-28 11:11 | 显示全部楼层
hyefeifei 发表于 2016-4-22 10:27
  adLockOptimistic参数意味着当程序执行到rst.Update时,才需要连接服务器,把操作查询语句传给数据库 ...

好好学习,进一步消化,期待下一讲。

TA的精华主题

TA的得分主题

发表于 2016-4-28 11:37 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2016-5-1 12:17 | 显示全部楼层
谢谢楼主的讲解。
照着视频的步骤安装了VMware,然后是安装win server 2008 R2*64,
提示“主机不支持Intel VT-x”.(查了,不是BIOS设置的问题,老机子愣是没这功能)。
郁闷啊!以后换个机子再说了。届时还得请教楼主。
单机版的SQL如何学习,楼主能否给点建议。

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-5-1 21:42 | 显示全部楼层
本帖最后由 hyefeifei 于 2016-5-16 15:12 编辑


  前面讲到recordset的UpdateCriteria属性,这个属性只对有主键的表起作用。它的作用何在呢?代码片断如下:
  
strSQL = "Select id,cname, sal from emp"
With rst
        .cursorlocation = adUseClient
        .Open strSQL, Conn, adOpenStatic, adLockOptimistic
        .Properties("Update Criteria") = adCriteriaUpdCols
        .Filter = "cname='James'"
        .Fields("sal").Value = 777
        .Update
End With

  此段代码把emp表中James的工资更新为777,emp表id为主键。

  当执行这段程序时,ado必须把代码翻译成sqlserver能懂的sql语句,才能在服务器上执行。

  当你直接用sql语句更新James的薪酬时,你或许会用下面的语句:

  Update emp set sal = 777 where cname = ’James’

  但是ado不会这么做,因为这么做的话,如果有重名的,会把所有James的工资都改了,那么,ado会如何做呢?它会把这个语句提交数据库:

  Update emp set sal = 777 where id = 101 and sal = 500(这里假设James的id为101,原工资为500)

  这里需要注意的是,即使id没有出现在select的后面,ado也会把上面语句提交数据库,因为ado在打开recordset时,提取了表的元数据,知道主键信息,所以能找到James的id。

  这样一来,重名带来的风险就不存在了,但是为什么ado会把James原来的工资放在where后面呢(and sal=500)?

  我们假设一种情况来说明:当你打开表,看到James的工资为500,想给他长到777时,恰好在此之前,其他人因为James违反了公司某项制度,把他的工资降到了400,而此时,如果where条件中没有sal=500的话,长工资这一行为就会成功,而这往往是不希望发生的。

  所以提交 Update emp set sal=777 where id = 101 and sal = 500 语句,可使在这种情况下,长工资失效,同时会返回一个错误值,而便于你引用此错误值对此情况处理。

  这些内容,前面我们都讲过,那么,如果你说,我不管那么许多,我就想给他长到777,这时怎么办?

  这就要引用Properties("UpdateCriteria")属性了,把这个属性的值设置为adCriteriaKey,ado就会把更新语句翻译成:

  Update emp set sal = 777 where id = 101

  提交数据库,这样一来,你做的修改就会覆盖其他人的修改了。

  Properties("UpdateCriteria")属性有以下三个值:

adCriteriaKey
0
仅使用基于查询更新的WHERE子句中关键字段的值
adCriteriaAllCols
1
使用基于查询更新的WHERE子句中字段的初值
adCriteriaUpdCols
2
默认值,使用基于查询更新的WHERE子句中被修改字段的初值和关键字段的值

  对三个值的用法见下图:

Image 017.jpg


  说明如下:

  1 当表无主键时,update时,ado会提交:

  update 表名 set 修改字段名 = 新值 where 修改字段名 = 原值 and 字段1 = 原值 and 字段2 = 原值,……

  即where后面会跟select语句中出现的所有字段,此时不论updatecriteria属性取何值,都相当于取adCriteriaAllCols值,'可知此属性在表无主键时无用。

  2 当表有主键时,updatecriteria属性取adCriteriaKey值时,ado会提交:

  update 表名 set 修改字段名 = 新值 where 主键 = a

  3 当表有主键时,updatecriteria属性取adCriteriaUpdCols值时,ado会提交:

  update 表名 set 修改字段名 = 新值 where 主键 = a and 修改字段名 = 原值

  此时,因为是默认的,所以updatecriteria属性设置也可省略。

  4 当无主键时,如果两条记录相同(select后面的字段完全相同,不含在select后面的字段不算),更新时会报错。

  总结一下,只有下列情况才需要设置这个属性:

  a 当有主键时,希望覆盖别人的修改,用此属性,设置值为adCriteriaKey

  b 当有主键时,希望别人对select语句后面出现的所有字段的修改都会影响到此次更新,用此属性,设置值为adCriteriaAllCols
  


TA的精华主题

TA的得分主题

发表于 2016-5-4 08:53 | 显示全部楼层
hyefeifei 发表于 2016-5-1 21:42
[/td][/tr]
[/table]
  此段代码把emp表中James的工资更新为777,emp表id为主键。

好好学习!期待下一讲。

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-5-6 14:33 | 显示全部楼层
zhouzhongchi 发表于 2016-5-1 12:17
谢谢楼主的讲解。
照着视频的步骤安装了VMware,然后是安装win server 2008 R2*64,
提示“主机不支持Inte ...

你可以安装server2003 32位版+sql2000,应该可以装上
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-12 06:04 , Processed in 0.052551 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表