First we try, then we trust

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  183 随笔 :: 111 文章 :: 3132 评论 :: 358 引用

第1章 数据库基础

1.1 一个肤浅的定义

什么是数据库?这是一个很难回答的问题,经典的教科书往往都是从信息、数据说起,直到数据库。这里我想直接给出一个不准确的,肤浅的定义(这也是最早的FoxBASE时代,绝大多数人对数据库的认识):

【定义】:(1)一个库便是一张二维表格,表由表头(字段)与表的内容(记录)组成。(2)建立在该表上的操作主要包括:检索、插入、删除、更新。

这个定义与现有数据库存在很大差异,但并不影响作为这部分内容的开端。从上面的定义中我们可以看到,数据库中记录信息的表与建立在表上的操作是密不可分的。另外,常见的库操作有四种:检索、插入、删除、更新。

1.2 遭遇异常

在这个原始的概念驱使下,很多人就开始了数据库的设计历程,让我们来看这样一个例子:

【要求】:构建一用来描述在校学生的数据库,要求记录的学生如下属性:学号、姓名、年龄、系别。

很多人会觉得这太简单了,在上面的数据库概念的指引下,我们可以很容易的给出如下设计:

表 1-1 初始的数据库设计

学号 姓名 年龄 系别
1 张三 20 经管系
2 李四 22 机械系
3 王五 21 经管系
4 赵六 23 自动化

该设计很好的将学号、姓名、年龄、系别属性记录了下来,并且支持检索、插入、删除、更新操作。然而这是不是一个完美的设计呢?在讨论之前让我们先回答几个问题(尽管很多人对以下几个问题嗤之以鼻)。

问题1:学校有几个系?(答:3个)

问题2:经管系有几个学生?(答:2个)

每次讲到这里,总有很多学生对此不屑一顾,当我问到"你们是怎么知道的?"时候,很多人只是说"看出来的呗。"其实这两个问题不是用"看出来"就可以解释清楚的。最好的回答应当是"数出来的"(晕!)。问题1的答案是通过去掉系别列中的重复行后,数一数剩余的行数得到的。问题2的答案是通过数一数系别为经管系的行数得到的。那好,我们先把这两种解题方法放在这里以备后面查阅。

让我们再来看看建立在该表上的几种操作,检索已经说过了,这里不再提,我们看看插入、删除以及更新操作,这里有如下几个要求:

1、国家刚刚审批通过允许学校开设一个新的系"艺术系",然而艺术系的学生要等到两个月后才能招进来。

2、李四毕业了,不再是"在校学生"了,将其删除。

3、经管系现要更名成"经济管理学院"。

呵呵,我们已经开始遭遇"插入异常"、"删除异常"、"更新异常"了。如何插入一个没有学生的系呢?这是一个两难的问题。由于学校有艺术系,为了能够在检索"学校有几个系"时检索到4,我们不得不插入一行,该行的系别字段记录上"艺术系",而艺术系没有学生,所以我们还得让学号、姓名、年龄字段空着(如表 1 2所示)。

表 1-2 插入艺术系

学号 姓名 年龄 系别
1 张三 20 经管系
2 李四 22 机械系
3 王五 21 经管系
4 赵六 23 自动化
(空) (空) (空) 艺术系

此时如果我再问"艺术系有几个学生"时,恐怕有些人的脸色就不那么好看了吧。这回通过数一数系别为艺术系的行数就无法得到准确的艺术系人数答案了。因此解题逻辑不得不也发生变化:如果人数为1,判断学号、姓名、年龄是否为空,如果为空则为0人,否则为1人。你觉得这回的检索还那么简单吗?

再来看删除操作也不是想删就删了。如果你把李四一行删除,你会惊奇的发现机械系没有了!所以也不得不修改删除逻辑,如果某系只剩下最后一条记录,就不能删除了,而起清空学号、姓名、年龄字段的内容,这么做好吗?

更新操作似乎也存在一些问题。在上面的设计种,经管系更名需要修改两行数据,假设刚刚修改完第一行,正要修改下一行,停电了,死机了,反正机器无法正常运转。当你下次开机后数一数有几个系呢?

1.3 解决异常

上面的问题有没有解决的办法呢?有!数据库规范化理论给出了我们解决的办法(关于第一范式、第二范式、第三范式等内容可以参考《数据库原理》),那就是"拆分"。我们可以通过将上表拆分成如下两表的形式解除异常:

表 1-3 学生库

学号 姓名 年龄 系别代号
1 张三 20 1
2 李四 22 2
3 王五 21 1
4 赵六 23 3

表 1-4 系别库

系别代号 系别
1 经管系
2 机械系
3 自动化

这两张表通过系别代号关联起来,保留了原有信息,但该设计消除了上面提到的异常。读者可以自行尝试在当前设计下重新执行上面的检索、插入、删除与更新操作,看看还有没有异常发生?

1.4 数据表述与认知矛盾

从上面的例子我们可以看到,为了消除在数据库操作过程中出现的插入异常、删除异常以及更新异常,我们必须利用数据库规范化理论对数据库的设计加以规范处理。但如果校长希望你提供一份学生名单时,你提供给校长的该是什么呢?毫无疑问,校长最希望见到的是表 1-1,而绝非表 1-3与表 1-4。因此这就引出了新的问题:数据库的使用者与数据库的设计者在对数据的认知上往往是不一致的。数据库的使用者希望看到的是直观、易懂的数据,而数据库的设计者希望设计出来的方案易于修改、便于扩充,容易进行系统开发。因此,真正的数据库设计必须很好的解决这两者之间的矛盾。现代的数据库都提供了众多的方法解决这个问题(将在1.1.5中给予说明)。我们这里不妨再看一个认知矛盾的例子。

假如需要通过数据库记录一树型结构的数据(就像Windows中的文件夹),我们如何来用二维表格加以描述呢?用户当然希望看到的是一棵树,而数据库设计者面临的问题是如何将树二维表格化。这个工作我们可以通过如下的映射关系实现:

图 1-1 需要表述的树型结构

表 1-5 使用二维表格表述树形结构

ID ParentID FoderName
1 1 Program Files
2 1 AC3Filter
3 2 pic
4 1 ACD Systems
5 4 ACDSee
6 4 FotoCanvas
7 4 FotoSlate

我们可以看到,表 1-5利用ID字段与ParentID字段描述了文件夹间的父子关系,进而通过二维表格记录下了树型结构的内容。

总之,数据认知矛盾是不可避免的,通过各种办法,我们总能让数据库的使用者与数据库的设计者在数据表述问题上相互平衡。我们至少可以通过两种途径解决这种认知矛盾,一方面可以借助现有数据库提供的功能(例如视图等,见1.1.5)解决,另一方面我们可以设计专门的数据结构解决(例如上面树型结构记录的问题)。

1.5 数据库该是什么样?

既然在1.1.1中给出的数据库定义存在很大的问题,那么一个真正的数据库应当是什么样的呢?我们需要数据库为我们提供什么样的服务?这些服务又是通过什么形式表现出来呢?

要说清楚这一点,还是让我们从"在校学生"这个例子谈起。上面分析到为了消除各种异常,我们通过拆分的方式将原有设计一分为二,两表间通过系别代号相互关联。尽管异常没有了,但也带来了一系列麻烦。

1.5.1 视图

首先,数据表述上的认知矛盾使得校长在得到他的报表前不得不对数据进行一下处理,重新将两表"缝合"起来。如果教务处想了解每个系的学生人数时,就又需要另外一种数据"缝合"方式。为了让众口不再难调,数据库中引入了"视图"的概念,允许用户从不同的角度观察数据,得到自己想要的结果。"横看成岭侧成峰",山(数据库的物理设计方案)永远不会改变,通过不同的视角(视图),我们可以看到不同的数据表现形式。这就是视图的一个非常重要的作用。当然视图提供的功能远不止这些,作为初始了解就先说到这种程度。

《数据库原理》里面提到的三级模式、两级映象其实说的就是这层关系。我们抛开三级模式中的内模式(物理实现),单看外模式与模式。模式只有一个,那就是数据库设计者设计出来的表,而外模式可以有多个,每个外模式可以理解成一个"视图",想怎么看就怎么看(如图 1-2)。这么做的同时也实现的数据的"独立性",数据库的设计者可以专心的设计数据库逻辑结构,并将设计方案从不同视角的视图中独立出来。

图 1-2 通过视图解决认知矛盾

1.5.2 完整性约束

然而事情并不是象预期般进展顺利,数据库设计者在消除了各种异常的以及数据认知矛盾的困扰后,往往又陷入"数据不一致"的问题陷阱中。数据库设计者会发现数据插入、删除、更新操作不象想象中那样随心所欲,必须时刻小心的避开数据不一致的暗礁。

例如,一个不负责任的数据录入人员很可能将下面两条记录输入到数据库中:系别表(系号:3,系别:艺术系);学生表(学号:4,姓名:和二,年龄25,系号:9)。

在这里,新插入的艺术系与自动化系出现了相同的系号,而学生表与系别表靠此系号字段进行关联,于是问题就出来了,我们无法正常检索艺术系有多少人,也无法判断某系号为3的学生究竟是哪个系的。因此必须确保系别表中的系号能够唯一标识某一行记录。我们管这样的字段叫做"主键"(很不严格、不准确的定义,但我们可以暂时如此理解,详细的定义可以参考《数据库原理》)。主键的存在是为了确保实现"实体完整性" ,其取值有两点要求:(1)不允许为空;(2)不允许重复。因此,数据库需要提供某种限制性策略防止违反"实体完整性"的事情发生。不同数据库实现的手段各不相同,Visual FoxPro中我们可以在该字段上创建一个主索引或候选索引,在SQL Server中,我们可以为索引添加唯一性约束条件等。

再来看看插入的学生记录,我们给该学生的系号字段输入了数值9,而在系别表中根本没有系号为9的系别,于是该学生便"无家可归"了。为了防止类似事情发生,要求数据库还要提供某些机制,确保学生表中的系号和系别表中的系号存在某种对应关系,防止不一致现象出现。这种机制是靠实现"参照完整性" 实现的。学生表(从表)中的系号(外键)需要参照系别表(主表)中的系号(主键)。

参照完整性中所指的主表与从表不一定非是两个不同的表,也可以是同一张表。例如表 1-6:

表 1-6一张表内的参照完整性

学号 姓名 班长学号
1 张三 2
2 李四 2
3 王五 2
4 赵六 2

班长学号与学号间就构成了外键和主键的关系。班长学号的取值只能有两种情况,(1)为空,表示该班还没有选出班长。(2)为学号字段中的某个值,表示该班班长取自本班学生。

另外,在1.1.4数据表述与认知矛盾一节中,我们介绍了如何用二维表来表述一树形结构,仔细观察表 1-5,其中的ID字段与ParentID字段间也构成了主键与外键的关系,ParentID的取值必须来自ID列。

在实际应用过程中,参照完整性往往可以抽象归纳成几条原则,这里给出Visual FoxPro中的参照完整性约束供参考(以学生、系别表为例):

  • 删除规则:

级联删除:如果删除系别表中经管系,则自动将学生表中系别为经管系的学生删除。

限制删除:如果发现学生表中有学生是经管系的,则禁止删除系别表中的经管系。

  • 更新规则

级联更新:若更改系别表中的经管系系号,则学生表中对应经管系学生的系号也一并更改。

限制更新:如果学生表中有学生是经管系的,则禁止更改系别表中经管系的系号。

  • 插入规则

限制插入:禁止在学生表中插入一条记录,该记录的系号在系别表中没有。

除了了解参照完整性约束条件外,我们还应当注意应用参照完整性后数据处理的先后顺序。仍然以学生表和系别表为例子,假设用户为两表间建立了"限制删除、限制更新、限制插入"的参照完整性规则,那么当删除经管系及所有学生时,要先删学生表,再删系别表,更新也是相同,当插入艺术系及其学生时,要先插入系别表再插入学生表。此时两表操作的先后顺序是不同的。请大家完成【实验 1-1 Visual FoxPro中参照完整性的设置及数据操作顺序】步骤1、2、3、4以加深理解。

实验 1-1 Visual FoxPro中参照完整性的设置及数据操作顺序

1.5.3 触发器与存储过程

在实验 1-1中,我们实现了在Visual FoxPro中设置参照完整性,到底是什么神奇的力量使得级联删除得以实现的呢?在Visual FoxPro中是靠触发器与存储过程实现的(不同数据库使用的技术不尽相同)。触发器通常分为插入触发器、删除触发器和更新触发器,通过对这些触发器的设置可以确保在数据库表执行插入、删除、更新时自动执行某些代码。Visual FoxPro中,这些代码存贮在数据库中,我们管它们叫做"存储过程"。我们暂时可以这样理解存储过程:它是一段存储在数据库中、经过预先编译的,可被外部直接调用的程序代码。随着我们内容的逐步深入,对存储过程的认识还会进一步加深。请大家完成【实验 1-1 Visual FoxPro中参照完整性的设置及数据操作顺序】步骤5。

1.5.4 约束条件

上面我们学习了完整性约束中的实体完整性约束与参照完整性约束,还有一项叫做用户定义完整性约束,顾名思义,就是用户自行定义的完整性约束条件。在数据库中通常提供了两类用户定义完整性约束,(1)字段级完整性约束,(2)记录级完整性约束。

在我们进行库表的设计过程中,我们可以定义字段类型、字段长度与小数位数,但这对某些应用而言是不够的。例如某字段"年龄"。通常我们使用整形作为该字段的数据类型,然而"-5"、"1000"都是整数,可显然不是年龄,如何确保在字段级别上设置完整性呢?这就靠字段级完整性约束实现了。通过字段完整性约束,我们可以设置年龄字段中的数据必须是0到150之间的整数,以确保年龄数据的正确性。请大家完成【实验 1-2 在Visual FoxPro中实现字段级完整性约束】以加深对字段完整性的认识。

实验 1-2 在Visual FoxPro中实现字段级完整性约束

字段完整性仅仅对某个字段的数据进行完整性校验,如果多个字段中存在相互关联,字段级约束就显得力不从心了。例如某表中包含着"年龄"和"工龄"两个字段,年龄的字段约束为0~150间的整数,工龄的约束条件是0~60间的整数。我们完全可以插入一条记录,年龄为10而工龄为30。尽管这些数据并不违反单独某个字段上的约束条件,但一个10岁的小孩怎么会有30年工龄呢?为了保证字段间数据完整一致,就得靠记录级完整性约束实现了。通过设定约束条件"工龄<=年龄-18"就可以确保这两个字段间数据的一致性。请大家完成【实验 1-3 在Visual FoxPro中实现记录级完整性约束】以加深对字段完整性的认识。

实验 1-3 在Visual FoxPro中实现记录级完整性约束

1.5.5 数据库事务处理

上面说了很多关于数据库应该具备的功能,也许有人早就新存疑惑了:"在参照完整性中有个概念叫级联更新,也就是如果把系别代号改了,学生表中对应的系别代号也自动改,问题是如果改到一半时停电了,那岂不是数据出现不一致问题,更新异常又来了吗?"。

确实如此,如果没有一套有效的机制防止类似事情发生,数据库仍然面临很大的威胁。现有的数据库基本都支持"事务",那么什么是事务呢?简单的说,就是确保"同时成功则成功,任何一个失败则失败"的一种机制。一个事务往往包括三种动作行为:开始事务(Begin Transaction),提交事务(Commit)和回滚(Rollback)。从开始事务到提交事务过程中所发生的一切数据库修改要么同时成功(被Commit,固化在数据库中),要么一个失败,大家同时回复原有状态(Rollback,数据库回复到事务开始时的状态)。一个典型的事务程序可能如下:

tx = BeginTransaction();
try
{
    
//修改系别表
    //修改学生表
   tx.Commit();
}

catch
{
   tx.Rollback();
}

当执行BeginTransaction时,我们可以认为是给数据库照了张快照,记录当前状态。然后开始更新系别表与学生表,如果都能正确执行,则提交修改,快照也就没有什么用处了。但如果其中任何一个表出现更新异常,程序将落入catch段中,我们在这里对数据库进行回滚,还原到快照时的状态。

关于事务以及数据更新的更详细的内容将在【第2章 并发操作的一致性问题】中有更详细的介绍。

1.5.6 索引与主键

索引是数据库中一个非常重要的概念,它的作用就如同新华字典前的检字表一样,可以提高我们的检索效率。而主键的作用是用来唯一表示表中的某一行,知道了某主键就能够根据它唯一定位一条记录,就如同一张表的身份证号一样。(待完善)

posted on 2005-07-31 22:01 吕震宇 阅读(12034) 评论(38)  编辑 收藏 网摘 所属分类: 数据库应用基础

评论

#1楼  2005-08-01 20:54 东方蜘蛛      
我就把您这当成我的第二大学好了,呵呵
在学校学习不到,就在这学习了:)

  回复  引用  查看    

#2楼  2005-08-02 10:37 bugSharp [未注册用户]
吕老师,讲的真不错,深入浅出,期待你的下文啊!!
  回复  引用    

#3楼  2005-08-03 15:54 yanwc [未注册用户]
吕老师,有几个问题请教:
1.在vb.net中,如果我在datagrid中显示的内容是“学生名单视图”的内容,如何增加、修改、删除、保存记录?
2.数据库设计之“有时不得不违背的第三范式”
http://tintown.cnblogs.com/archive/2005/05/08/150784.aspx
这个是否与你的 1.1.3的内容有点冲突?

希望得到你的帮助,谢谢!!

  回复  引用    

#4楼 [楼主] 2005-08-03 16:53 吕震宇      
@yanwc

1、由于你用了视图,所以在VS .NET(vb.net我没有用过)中的SqlDataAdapter可能不会自动生成Select、Insert、Update、Delete命令(我没有试过,是从寒枫天伤的O/R随想一文中看到的),因此该视图是无法提交的,需要手工添加DataAdapter中的各命令以实现更新功能。

2、我很赞成“有时不得不违背的第三范式”的说法,而且在实际开发中确实是这样。范式可以指导我们对基于OLTP的数据库进行优化,但不要做得太过。而基于OLAP的数据仓库设计基本上就谈不上什么范式不范式的了。究竟优化到第几范式需要根据实际情况而定,作为初学者,我的建议是优化到第三范式。

  回复  引用  查看    

#5楼  2005-08-03 22:21 yanwc [未注册用户]
吕老师:谢谢你的答复!!
用视图是不能自动生成Select、Insert、Update、Delete命令,能不能拿你上面的表做示例,来讲一下如何手工添加DataAdapter中的各命令,谢谢!!
我查了CSDN上相关内容,也只是提到手工设置这几个命令,但没有查到如何的相关内容。

  回复  引用    

#6楼  2005-08-03 22:23 yanwc [未注册用户]
我查了CSDN上相关内容,也只是提到手工设置这几个命令,但没有查到如何设置这几个命令的相关内容。

  回复  引用    

#7楼  2005-08-20 03:01 周奔驰      
索引与主键讲的不清不楚
  回复  引用  查看    

#8楼  2005-09-01 10:13 坏蛋 [未注册用户]
表 1-5 使用二维表格表述树形结构
如何一次性提取出某个节点的所以下属节点(子,孙。。。。)呢?

  回复  引用    

#9楼  2005-11-10 00:34 zhaoxijun      
吕老师,讲的真不错
  回复  引用  查看    

#10楼  2005-11-22 18:09 peterfeng [未注册用户]
建议搂主使用SQLServer做为举例数据库。

讲的东西视角比较特别,适合有一定数据库基础的人听。
估计你的学生听起来会有难度。

  回复  引用    

#11楼  2005-11-23 11:56 xiao_p [未注册用户]
同意楼上的,我也感觉学的时候不是明白很多,但是用的时候就忽然醍醐灌顶了…………
  回复  引用    

#12楼  2005-12-02 15:11 Mark_Lee [未注册用户]
吕老师的表1-5好像有问题啊!
第一条记录的ParentID=1好像不妥,是不是应为ParentID=0才更清楚!

ID ParentID FoderName
1 0 Program Files

  回复  引用    

老师:
请问如何通过编写触发器实现如下功能:
当删除某条记录后自动将该记录彻底删除。或者在表关闭时将所有逻辑删除的记录删除掉
请老师将解决办法发到我的邮箱:wang_jian_bo037@126.com
谢谢老师

  回复  引用    

#14楼 [楼主] 2005-12-07 21:01 吕震宇      
@周日黄昏

我想你是指VFP数据库。理论上说,你的想法不是很可行。因为数据库程序设计的目的就是“共享”数据,也就是说你的程序很可能同时有多个人正在使用,当你关闭表时,也可能别人正在使用这张表,所以这个时候就无法执行物理删除。

不过如果你确认只有你一个人使用数据库,或者你引入了某种机制检测是否有人正在使用你的数据库,那么在推出你的系统时自动删除逻辑数据是有可能的。

下面的代码是我在我以前的程序中使用的,针对的都是数据库表,关键思路是找到数据库,以独占方式打开,然后使用ADBOBJECTS函数获取该数据库下的所有表信息,然后逐一Pack清除逻辑删除的数据。

LOCAL lnTotal, lcOldValue, lcNewValue
LOCAL lcOldError, lnErrorNo, lcFile
LOCAL laTables[1], i

lnErrorNo = 0
lcOldError = ON("error")
ON ERROR DO PackErrHandle WITH lnErrorNo

THISFORM.CmdOk.Enabled = .F.
THISFORM.CmdCancel.Enabled = .F.
CLOSE DATABASES ALL
SET EXCLUSIVE ON
*-------------------------------------
lnHandle = FOPEN("Data\DataLocation.txt")
lcStr = ALLT(FGET(lnHandle))
FCLOSE(lnHandle)

OPEN DATABASE "&lcStr"
CLOSE TABLES
THISFORM.lblStep.Caption = "正在清理各数据库数据 ......"
FOR i = 1 to ADBOBJECTS(laTables, "Table")
lnErrorNo = 0
IF !EMPTY(laTables[i])
IF !USED(laTables[i])
USE (laTables[i]) IN 0 EXCL
SELECT (laTables[i])
WAIT WINDOW NOWAIT "正在清理数据库" + UPPER(ALLTRIM(laTables[i])) + ".DBF"
*-- 当出现错误后,系统运行 PackErrHandle ,
*-- 并修改 lnErrorNo 的值
PACK
DO CASE
CASE lnErrorNo = 1705
=MESSAGEBOX("数据库"+lcFile+"正被其他用户使用,无法清理",48,"无法清理当前数据库")
CASE lnErrorNo = 1569
=MESSAGEBOX("对具有写保护的数据库容器 (.DBC) 文件进行写操作。",48,"无法清理当前数据库")
CASE lnErrorNo = 0
PACK
OTHERWISE
=MESSAGEBOX("未知错误,错误代号:"+STR(lnErrorNo))
ENDCASE
ENDIF
ENDIF
ENDFOR
CLOSE TABLES
WAIT WINDOW NOWAIT "清理完毕"

*-------------------------------------
CLOSE DATABASES ALL
SET EXCLUSIVE OFF

*-- 恢复错误处理过程
IF EMPTY(lcOldError)
ON ERROR
ELSE
ON ERROR &lcOldError
ENDIF

THISFORM.CmdOk.Enabled = .T.
THISFORM.CmdCancel.Enabled = .T.
=MESSAGEBOX("数据清理及整理工作完毕",0+64,"清理完毕")
THISFORM.RELEASE()

#################

Data\DataLocation.txt是一个纯文本文件,记录了数据库文件的物理位置,内容可以类似:

C:\AAA\ABC.DBC

  回复  引用  查看    

#15楼 [楼主] 2005-12-07 21:03 吕震宇      
@Mark_Lee

I Agree! 有时间我改过来,最近访问博客园的速度有些慢。

  回复  引用  查看    

为什么不选择用SqlServer数据库来讲,而用已经没多少人用的FoxPro呢?
  回复  引用    

索引和主键,以及约束是很重要的概念,不过作者却讲得太少。看来文章是偏重于实践,而不是理论
  回复  引用    

#18楼  2006-02-07 11:53 jiaojiao [未注册用户]
吕老师,你好!有个问题请教于你:
在数据库中三级模式、二级映射的概念我搞不懂,您能举例讲解一下吗?

  回复  引用    

#19楼  2006-04-02 07:43 蔡中和 [未注册用户]
讲的真好!!!!
  回复  引用    

#20楼  2006-04-04 19:20 梁广永      
老师讲得是实践多,理论少,
可能是考虑到理论难于理解的原因

  回复  引用  查看    

#21楼  2006-04-14 21:54 小炯炯 [未注册用户]
吕老师:
我现在遇到一个问题,在VFP里进行编辑关系里的参照完整性时,老是会出现说是数据表没有被发现,这是怎么回事?回复

  回复  引用    

#22楼  2006-07-17 10:38 请教 [未注册用户]
在 VB操作VFP数据库时,我开始在数据库中用DELETE 删除一条记录,但想用PACK做彻底删除时 提示 文件 IS IN USE ,搞得郁闷,不知道应该怎么处理
  回复  引用    

这样找回数据库删除的数据,是ACCES
  回复  引用    

找回数据库删除的数据,是ACCES
  回复  引用    

怎样找回数据库删除的数据,是ACCES
  回复  引用    

#26楼  2006-09-22 10:55 李燕平      
讲的很好,如果使用sqlserver就更好了
  回复  引用  查看    

#27楼  2007-03-06 10:07 dd [未注册用户]
在考生文件夹下有“XX”数据库
在“窗体1”窗体中添加标签和名称相同的文本框“请输入学号”和“学生姓名”,添加“显示学生姓名”按钮,编写程序实现输入学号后单击“显示学生姓名”按钮后显示学生姓名,要求用Dlookup函数实现。窗体的设计,如图
解答本题按下列步骤:
(1)打开“窗体1”设计视图,从工具箱中选择文本框控件添加到窗体中,在“文本框向导”中指定文本框的名称和标签为“请输入学号”。
(2)同样,添加“学生姓名”文本框。
(3)从工具箱中选择按钮添加到窗体中,取消“命令按钮向导”。
(4)将按钮命名为“显示学生姓名”。
(5)选中按钮,右键单击选择“事件生成器”对话框中选“代码生成器”,单击“确定”。
(6)在“private sub”和“end sub”之间添加如下代码:
forms![窗体1][学生姓名]=dlookup("学生姓名","学生","学生编号='"&forms!![窗体1][请输入学号]&"'"
虾米 17:47:00
(7)关闭代码生成器窗口,关闭并保存对窗体所做修改
forms![窗体1][学生姓名]=dlookup("学生姓名","学生","学生编号='"&forms!![窗体1][请输入学号]&"'"
代码这一句怎么老说错误?

  回复  引用    

#28楼  2007-07-18 15:27 weiwei~      
最近一直在选寻找数据库方面通俗易懂的教材,对于我们这种刚入门的新手来说市面上那些"用a理论阐述b理论"的深奥的数据库教材只能让人失望,今天看到您写的blog真是兴奋极了,终于找到了.
之前看了若干的计算机教材,唯一让我印象深刻并受益匪浅的是张孝祥的书,他就是完全抛开晦涩的理论运用生动的例子来阐述一些难懂的术语,您的风格跟他一样,十分欣赏.
加油!期待您更多更好的文章!

  回复  引用  查看    

#29楼  2007-09-29 16:03 spc920 [未注册用户]
真好,以后就上这儿了.
  回复  引用    

请问是原创吗?
  回复  引用    

#31楼 [楼主] 2007-10-11 21:58 吕震宇      
@独闯天涯
是的。

  回复  引用  查看    

#32楼  2007-11-04 17:36 蓝绿 [未注册用户]
过瘾
  回复  引用    

#33楼  2007-12-23 05:16 李华星      
学习中...
  回复  引用  查看    

#34楼  2008-02-03 00:49 未注册 [未注册用户]
看了一段,不得不佩服,实在是太强了
  回复  引用    

#35楼  2008-05-06 17:54 John Rambo      
辛普森。。。
  回复  引用  查看    

#36楼  2008-05-27 17:14 sijiayou [未注册用户]
多谢,看了之后受益匪浅
  回复  引用    

#37楼  2008-06-16 13:59 专研.NET      
学习了
  回复  引用  查看    


发表评论



姓名 [登录] [注册] 
主页
Email (仅博主可见) 
验证码 *  验证码看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论   新用户注册   返回页首      

导航: 网站首页 社区 新闻 博问 闪存 网摘 招聘 .NET频道 知识库 找找看 Google站内搜索



China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
China-Pub 计算机绝版图书按需印刷服务

相关文章:

相关链接:

历史上的今天:
2004-07-31 dudu: RSS似乎有问题
2004-07-31 博客园RSS变了?!