首页 / 资讯中心 / 文章详情

易语言操作ACCESS数据库:从建表到增删改查的完整实战指南

易语言操作ACCESS数据库:从建表到增删改查的完整实战指南 ★ FEATURED ARTICLE
简介这份教程面向易语言初学者聚焦如何用易语言操作ACCESS数据库解决从建库建表到读写记录的入门难题。内容先对比易语言支持的多种数据库类型指出ACCESS与MSSQL操作思路一致再依次讲解ACCESS安装准备、使用设计器创建数据表与主键设置、数据库连接与记录集两类控件的分工以及连接打开、读操作、读操作问题解决、高级打开、写操作、记录简单与高级修改、数据库与高级表格交互等模块并提醒尽量使用英文字段名以规避兼容性问题。资源包为1个doc文档约776KB适合按章节顺序边看边练。目前已有1047人学习可作为课堂外自学的补充材料帮助读者建立数据库操作的整体框架掌握连接、读取、写入与修改记录的完整流程并理解指针位置判断等常见排错思路。1. 易语言操作 ACCESS 数据库从建表到增删改查一套能跑通的完整路径很多用易语言做桌面工具的朋友第一次碰到数据持久化都会卡在同一个地方程序一关内存里的数据全没了。想存成文本文件吧查询、排序、去重全靠自己写逻辑数据量一上来就崩。这时候 ACCESS 数据库往往是最顺手的选择——单文件、免安装服务、Windows 自带驱动就能连配合易语言的数据库组件几十行代码就能把增删改查跑起来。但真动手时又会发现一堆问题连接字符串怎么写、记录集和表格组件到底用哪个、中文乱码怎么处理、并发写入报错怎么办。这篇就把易语言操作 ACCESS 的完整链路拆开讲从建库、连库、建表到参数化查询、事务批量写入、再到打包分发时的驱动坑每一步都给可复制的代码和参数说明。适合已经会易语言基本语法、想给工具加上本地数据存储的开发者也适合被文本文件折磨过、准备换方案的熟手。2. 连接 ACCESS 的三种方式与选型别一上来就用错组件易语言操作 ACCESS本质上是通过 ADOActiveX 数据对象或 ODBC 去调用系统里的数据库驱动。易语言自带的「数据库」组件和「外部数据库」组件底层封装的就是这两条路。选错了组件后面写多少代码都是白费。2.1 三种连接方式的真实差别第一种是易语言自带的「数据库」组件它走的是 ODBC 的老接口配置简单但功能弱不支持参数化查询遇到特殊字符容易出问题。第二种是「外部数据库」组件它封装了 ADO支持记录集、事务、参数化是现在的主流选择。第三种是直接调用系统里的 ADO 对象通过「对象」类型去创建 Connection 和 Recordset灵活度最高但代码量也最大。我一般会推荐「外部数据库」组件理由是它在易语言里封装得比较完整又保留了 ADO 的核心能力。下面这张表把三种方式的差异列清楚对比项数据库组件外部数据库组件直接调用 ADO 对象底层接口ODBCADOADO参数化查询不支持支持支持事务控制弱支持完整支持代码复杂度低中高推荐场景极简读写常规项目复杂业务逻辑选型的原则很简单如果只是存个配置、读个列表数据库组件够用只要涉及用户输入拼接 SQL、批量写入、多表关联直接上外部数据库组件别犹豫。2.2 连接字符串的写法与参数含义ACCESS 的连接字符串有两种常见写法对应不同的驱动版本。老版本用 Jet 引擎新版本用 ACE 引擎。ACE 引擎对 .accdb 格式支持更好但需要系统安装对应的驱动包。# Jet 引擎适用于 .mdb 格式32 位程序 ProviderMicrosoft.Jet.OLEDB.4.0;Data SourceD:\data\demo.mdb; # ACE 引擎适用于 .accdb 和 .mdb需装驱动 ProviderMicrosoft.ACE.OLEDB.12.0;Data SourceD:\data\demo.accdb;在易语言里这段字符串要赋给外部数据库组件的「连接文本」属性。注意几个参数Data Source后面必须是数据库文件的绝对路径相对路径在某些系统上会解析失败如果数据库有密码要加上Jet OLEDB:Database Password你的密码如果程序要跨 32 位和 64 位运行驱动版本必须和程序位数一致这是最常见的翻车点。2.3 用代码建立连接并验证下面这段代码演示了如何用外部数据库组件连接一个 ACCESS 文件并做一次连通性验证。.版本 2 .支持库 eDB .程序集变量 数据库, 外部数据库 .子程序 _启动子程序, 整数型 .局部变量 连接结果, 逻辑型 .局部变量 错误信息, 文本型 设置连接字符串指向同目录下的 data.accdb 注意取运行目录() 返回的是程序所在目录末尾不带反斜杠 数据库.连接文本 ProviderMicrosoft.ACE.OLEDB.12.0;Data Source 取运行目录 () \data.accdb; 尝试打开连接 连接结果 数据库.打开 () .如果真 (连接结果 假) 错误信息 数据库.取错误信息 () 信息框 (连接失败 错误信息, 0, 错误) 返回 (0) .如果真结束 连接成功后执行一次简单查询确认能读到数据 .如果真 (数据库.执行 (SELECT COUNT(*) FROM 用户表, ) 假) 信息框 (查询失败请检查表是否存在, 0, 提示) .如果真结束 用完关闭释放句柄 数据库.关闭 () 返回 (0)这段代码的关键点有三个第一连接文本里的路径拼接用了取运行目录()这样程序换目录也能找到数据库第二打开()返回假时一定要取错误信息否则你只知道失败不知道原因第三查询用执行()方法它适合不需要返回记录集的语句比如 COUNT、INSERT、UPDATE。如果是要读多行数据得用记录集。参数说明连接文本是外部数据库组件的核心属性格式必须严格按 Provider 规范写多一个空格都可能报错。打开()方法没有参数返回逻辑型。取错误信息()返回最近一次操作的错误描述调试阶段建议每次都打印出来。3. 建表与字段设计把数据类型和索引一次定对连接通了只是第一步表结构设计不合理后面查询慢、写入报错、数据对不上全是坑。ACCESS 的字段类型和 SQL Server、MySQL 有差异不能照搬。3.1 ACCESS 字段类型与易语言变量的对应关系ACCESS 支持的类型不少但常用的就那几个。下面这张表把 ACCESS 字段类型、SQL 建表时的写法、以及易语言里对应的变量类型列清楚ACCESS 类型建表 SQL 写法易语言变量类型说明文本TEXT(50)文本型长度 1-255超长用 MEMO长文本MEMO文本型存大段内容不能建索引整数INTEGER整数型范围 ±2 万左右长整数LONG长整数型范围更大常用作主键双精度DOUBLE双精度小数型存金额、比例日期时间DATETIME日期时间型格式敏感见后文是否YESNO逻辑型存真假值自动编号COUNTER整数型自增主键只读设计表时有个血泪经验能用整数就别用文本做主键。文本主键在关联查询时性能差而且容易因为空格、大小写导致匹配不上。自动编号字段是最省心的选择。3.2 用 SQL 建表的完整代码下面这段代码在已连接的数据库里创建一张用户表包含自动编号主键、文本字段、整数字段和日期字段。.版本 2 .支持库 eDB .子程序 创建用户表 .局部变量 建表SQL, 文本型 .局部变量 执行结果, 逻辑型 拼接建表语句字段名用中文ACCESS 支持 注意COUNTER 类型会自动递增不需要手动赋值 建表SQL CREATE TABLE 用户表 ( 建表SQL 建表SQL 编号 COUNTER PRIMARY KEY, 建表SQL 建表SQL 姓名 TEXT(50) NOT NULL, 建表SQL 建表SQL 年龄 INTEGER, 建表SQL 建表SQL 注册时间 DATETIME, 建表SQL 建表SQL 备注 MEMO 建表SQL 建表SQL ) 执行结果 数据库.执行 (建表SQL, ) .如果真 (执行结果 假) 信息框 (建表失败 数据库.取错误信息 (), 0, 错误) .如果真结束逻辑说明CREATE TABLE语句里COUNTER是 ACCESS 特有的自增类型等价于其他数据库的 AUTO_INCREMENT。PRIMARY KEY直接跟在字段后面也可以单独写成PRIMARY KEY (编号)。NOT NULL约束建议加上能避免很多空值判断的麻烦。参数说明TEXT(50)里的 50 是字符数上限不是字节数中文也算一个字符。MEMO类型不能参与排序和索引如果某个字段需要经常 WHERE 查询别用 MEMO。DATETIME字段在写入时日期格式要用#2024-01-01#这种带井号的形式后面会细讲。3.3 索引的建立与查询性能的关系数据量超过几千行以后没有索引的查询会明显变慢。ACCESS 支持在单个字段或多个字段上建索引语法和标准 SQL 略有不同。.版本 2 .支持库 eDB .子程序 创建索引 在姓名字段上建普通索引加速按姓名查询 数据库.执行 (CREATE INDEX idx_姓名 ON 用户表 (姓名), ) 在年龄和注册时间上建复合索引加速组合条件查询 数据库.执行 (CREATE INDEX idx_年龄时间 ON 用户表 (年龄, 注册时间), )索引不是越多越好。每建一个索引插入和更新时都要额外维护写入性能会下降。一般原则是经常出现在 WHERE 条件里的字段建索引经常排序的字段建索引重复值特别多的字段比如性别只有两个值不建索引。复合索引的字段顺序有讲究把区分度高的字段放前面。4. 增删改查的完整实现参数化查询与事务批量写入表建好了接下来就是日常操作。这一章把增删改查四个动作拆开每个都给可复制的代码重点讲参数化查询和事务这两个是避免 SQL 注入和数据不一致的关键。4.1 插入数据参数化查询的正确写法直接拼接 SQL 字符串是新手最容易犯的错。用户输入里带个单引号SQL 就断了轻则报错重则数据被篡改。参数化查询把数据和 SQL 语句分开传从根上解决这个问题。.版本 2 .支持库 eDB .子程序 插入用户_参数化 .参数 姓名, 文本型 .参数 年龄, 整数型 .局部变量 插入SQL, 文本型 .局部变量 执行结果, 逻辑型 用问号占位参数按顺序传入 插入SQL INSERT INTO 用户表 (姓名, 年龄, 注册时间) VALUES (?, ?, ?) 外部数据库组件的执行方法支持参数数组 注意日期要用 #日期# 格式这里用取现行时间() 转换 执行结果 数据库.执行 (插入SQL, 姓名, 年龄, 取现行时间 ()) .如果真 (执行结果 假) 信息框 (插入失败 数据库.取错误信息 (), 0, 错误) .如果真结束逻辑说明SQL 语句里的?是参数占位符执行时按顺序把后面的参数填进去。这样即使用户输入张三; DROP TABLE 用户表; --整个字符串也会被当作普通文本处理不会变成 SQL 指令。参数说明执行()方法的第一个参数是 SQL 语句后面可以跟多个参数值数量要和?的个数一致。日期时间型参数直接传易语言的日期时间变量即可组件会自动转换。如果字段是文本型但传了整数ACCESS 会尝试隐式转换但建议类型严格对应避免意外。4.2 查询数据记录集与表格组件的配合查询是用的最多的操作。外部数据库组件通过取记录集()方法返回一个记录集对象可以逐行读取也可以直接绑定到易语言的表格组件上显示。.版本 2 .支持库 eDB .子程序 查询用户_按年龄 .参数 最小年龄, 整数型 .局部变量 查询SQL, 文本型 .局部变量 记录集, 外部数据库记录集 .局部变量 姓名, 文本型 .局部变量 年龄, 整数型 查询SQL SELECT 编号, 姓名, 年龄 FROM 用户表 WHERE 年龄 ? ORDER BY 年龄 DESC 取记录集第二个参数为真表示返回记录集对象 记录集 数据库.取记录集 (查询SQL, 最小年龄) .如果真 (记录集.取记录数量 () 0) 信息框 (没有符合条件的记录, 0, 提示) 返回 () .如果真结束 逐行读取直到记录集末尾 .判断循环首 (记录集.尾记录后 () 假) 姓名 记录集.读文本 (姓名) 年龄 记录集.读整数 (年龄) 这里可以把数据加到表格组件或列表框里 调试输出 (姓名, 年龄) 记录集.到下一条 () .判断循环尾 () 用完关闭记录集释放资源 记录集.关闭 ()逻辑说明取记录集()返回的记录集对象初始位置在第一条记录之前所以要先判断尾记录后()再读。读文本()和读整数()的参数是字段名不是索引这样字段顺序变了也不影响代码。参数说明取记录集()的第二个参数开始是 SQL 里的参数值用法和执行()一致。取记录数量()返回结果行数可以用来判断是否为空。记录集用完必须关闭()否则连接池会被占满后续操作报「连接忙」。4.3 更新与删除条件一定要带对更新和删除的语法和插入类似但风险更高——WHERE 条件写错整张表的数据都可能被改掉或删掉。.版本 2 .支持库 eDB .子程序 更新用户年龄 .参数 用户编号, 整数型 .参数 新年龄, 整数型 .局部变量 更新SQL, 文本型 WHERE 条件用主键确保只影响一行 更新SQL UPDATE 用户表 SET 年龄 ? WHERE 编号 ? .如果真 (数据库.执行 (更新SQL, 新年龄, 用户编号) 假) 信息框 (更新失败 数据库.取错误信息 (), 0, 错误) .如果真结束 .子程序 删除用户 .参数 用户编号, 整数型 .局部变量 删除SQL, 文本型 删除前建议先查询确认避免误删 删除SQL DELETE FROM 用户表 WHERE 编号 ? .如果真 (数据库.执行 (删除SQL, 用户编号) 假) 信息框 (删除失败 数据库.取错误信息 (), 0, 错误) .如果真结束逻辑说明UPDATE 和 DELETE 的 WHERE 条件尽量用主键或唯一索引字段这样能精确锁定目标行。如果业务需要批量更新也要先用 SELECT 确认影响范围再执行。参数说明执行()方法对 UPDATE 和 DELETE 同样返回逻辑型成功为真。注意 ACCESS 的 UPDATE 不支持 FROM 子句的多表关联写法多表更新要拆成多条语句或用子查询。4.4 事务批量写入几千条数据一次提交逐条插入几千条数据每条都触发一次磁盘写入速度慢得让人想砸键盘。用事务把多条插入包起来一次性提交速度能提升一个数量级。.版本 2 .支持库 eDB .子程序 批量插入用户 .参数 用户列表, 文本型, 数组 .局部变量 i, 整数型 .局部变量 插入SQL, 文本型 插入SQL INSERT INTO 用户表 (姓名, 年龄) VALUES (?, ?) 开启事务 数据库.开始事务 () .计次循环首 (取数组成员数 (用户列表), i) 假设数组里每项是 姓名,年龄 格式 .如果真 (数据库.执行 (插入SQL, 取文本左边 (用户列表[i], 寻找文本 (用户列表[i], ,, , 假) 1), 到整数 (取文本右边 (用户列表[i], 取文本长度 (用户列表[i]) 寻找文本 (用户列表[i], ,, , 假)))) 假) 任何一条失败就回滚保证数据一致性 数据库.回滚事务 () 信息框 (第 到文本 (i) 条插入失败已回滚, 0, 错误) 返回 () .如果真结束 .计次循环尾 () 全部成功提交事务 数据库.提交事务 () 信息框 (批量插入完成共 到文本 (取数组成员数 (用户列表)) 条, 0, 提示)逻辑说明开始事务()之后的所有操作都在一个事务里要么全部成功要么全部回滚。这样即使中途某条数据有问题也不会出现「插了一半」的脏数据状态。参数说明事务的粒度要控制好太大比如几万条会占用大量日志空间太小又起不到批量优化的效果。一般几千条提交一次比较合适。注意 ACCESS 的事务对并发支持有限多个程序同时写同一个文件时事务可能锁表导致其他程序报错。5. 避坑与排查中文乱码、驱动缺失、并发锁定的真实处理这一章全是踩过的坑每条按「现象 → 原因 → 解决」写遇到问题可以直接对照排查。5.1 中文写入变成问号或乱码现象插入的中文姓名在 ACCESS 里打开显示成???或者乱码字符。原因连接字符串里没有指定字符集或者易语言字符串编码和 ACCESS 期望的编码不一致。ACCESS 的 ACE 引擎默认用 Unicode但某些驱动版本在 32 位环境下会按 ANSI 处理。解决在连接字符串里加上Jet OLEDB:Global Partial Bulk Ops2;不一定有用更可靠的做法是确保数据库文件本身是用 Unicode 编码创建的。如果已经出现乱码用SELECT读出来在易语言里显示正常但 ACCESS 里不正常说明是写入时的编码问题。换用 ACE 引擎驱动并在连接文本末尾加上;Character SetUTF-8;试试。如果还不行把字段类型从 TEXT 改成 MEMOMEMO 对 Unicode 支持更稳定。5.2 提示「未找到提供程序可能未正确安装」现象程序在自己电脑上跑得好好的拷到别人电脑上就报这个错。原因目标电脑没装 ACCESS 数据库引擎驱动。Windows 系统自带的是 Jet 引擎只支持 .mdb 格式不支持 .accdb。ACE 引擎需要单独安装驱动包。解决两个方案。一是把数据库存成 .mdb 格式用 Jet 引擎连接兼容性最好但字段类型和容量有限制。二是随程序打包 ACE 驱动安装包但要注意 32 位和 64 位版本不能混装。我一般推荐第一个方案除非必须用 .accdb 的新特性。5.3 多程序同时写入报「数据库被锁定」现象两个程序实例同时往同一个 ACCESS 文件写数据其中一个报错「无法更新数据库或对象为只读」或「数据库已被锁定」。原因ACCESS 是文件型数据库写入时会锁文件。多个进程同时写或者一个进程持有记录集没关闭都会导致锁冲突。解决第一确保每次用完记录集都关闭()连接不用时也关闭()。第二写入操作尽量短平快不要开着事务去等用户输入。第三如果确实需要多程序并发考虑换成 SQLite 或者把写入操作集中到一个程序里其他程序通过它来写。ACCESS 不适合高并发场景这是它的定位决定的。5.4 日期格式写入报「标准表达式中数据类型不匹配」现象插入日期时间时SQL 执行失败错误信息提示数据类型不匹配。原因ACCESS 的日期字面量必须用#包裹比如#2024-01-01#。如果直接传字符串2024-01-01ACCESS 会当成文本处理和 DATETIME 字段类型冲突。解决用参数化查询时直接传易语言的日期时间型变量组件会自动转换。如果非要拼 SQL日期部分写成#2024-01-01 12:00:00#。另外注意系统区域设置某些区域用日/月/年格式会导致#01/02/2024#被解析成 1 月 2 日还是 2 月 1 日不确定建议统一用年-月-日格式。5.5 查询结果顺序和预期不一致现象SELECT出来的数据没有ORDER BY时顺序每次都不一样。原因关系型数据库不保证无ORDER BY时的返回顺序ACCESS 也不例外。它可能按主键顺序返回也可能按插入顺序取决于执行计划。解决需要固定顺序时必须显式加ORDER BY。如果业务上依赖插入顺序加一个自增的编号字段按编号排序。别依赖「默认顺序」这种玄学换个驱动版本可能就变了。6. 进阶技巧把 ACCESS 操作封装成可复用的类模块前面几章的代码都是散落在各个子程序里的项目一大就难维护。这一章讲怎么把数据库操作封装成一个类模块以及一个验证数据是否真正写入的小技巧。6.1 封装类模块的基本结构在易语言里新建一个类模块把外部数据库组件放进去对外只暴露方法不暴露组件本身。这样调用方不需要关心连接字符串、错误处理这些细节。.版本 2 .支持库 eDB .类 数据库助手 .程序集变量 内部数据库, 外部数据库 .程序集变量 最后错误, 文本型 .子程序 初始化, 逻辑型 .参数 数据库路径, 文本型 内部数据库.连接文本 ProviderMicrosoft.ACE.OLEDB.12.0;Data Source 数据库路径 ; .如果真 (内部数据库.打开 () 假) 最后错误 内部数据库.取错误信息 () 返回 (假) .如果真结束 返回 (真) .子程序 执行SQL, 逻辑型 .参数 SQL语句, 文本型 .参数 参数1, 通用型, 可空 .参数 参数2, 通用型, 可空 .参数 参数3, 通用型, 可空 .局部变量 结果, 逻辑型 根据参数个数决定传几个这里简化处理 结果 内部数据库.执行 (SQL语句, 参数1, 参数2, 参数3) .如果真 (结果 假) 最后错误 内部数据库.取错误信息 () .如果真结束 返回 (结果) .子程序 取错误, 文本型 返回 (最后错误) .子程序 销毁 内部数据库.关闭 ()逻辑说明类模块把连接、执行、错误信息都包在里面调用方只需要初始化()一次然后反复调执行SQL()。错误信息通过取错误()方法获取不用每次都弹信息框。参数说明通用型参数可以接收任意类型适合做参数化查询的占位。但易语言的通用型参数有数量限制如果需要传更多参数可以改成传一个数组在方法内部展开。6.2 验证数据是否真正写入的方法写完插入代码怎么确认数据真的进库了最直接的方法是在 ACCESS 里打开表看但调试阶段来回切换很麻烦。可以在代码里加一个验证步骤插入后立刻用SELECT COUNT(*)查一下总数和插入前对比。.版本 2 .支持库 eDB .子程序 验证插入 .局部变量 插入前数量, 整数型 .局部变量 插入后数量, 整数型 .局部变量 记录集, 外部数据库记录集 查插入前总数 记录集 数据库.取记录集 (SELECT COUNT(*) AS 总数 FROM 用户表, ) 记录集.到下一条 () 插入前数量 记录集.读整数 (总数) 记录集.关闭 () 执行插入 数据库.执行 (INSERT INTO 用户表 (姓名) VALUES (?), 测试用户) 查插入后总数 记录集 数据库.取记录集 (SELECT COUNT(*) AS 总数 FROM 用户表, ) 记录集.到下一条 () 插入后数量 记录集.读整数 (总数) 记录集.关闭 () .如果 (插入后数量 插入前数量 1) 调试输出 (插入成功当前总数 到文本 (插入后数量)) .否则 调试输出 (插入异常前后数量 到文本 (插入前数量) - 到文本 (插入后数量)) .如果结束这个技巧在批量操作时特别有用能快速定位是哪一批数据出了问题。注意COUNT(*)返回的字段名用AS 总数起了别名读的时候用别名不然 ACCESS 可能返回Expr1000这种自动名称。6.3 一个我常用的习惯每次改完数据库相关的代码我不会直接跑主流程而是先单独跑一个「连接测试」子程序确认能连上、能建表、能插入一条再删掉。这个习惯帮我省了很多后悔药——有几次是驱动版本不对有几次是路径里有空格没处理如果直接跑主流程报错信息会被业务逻辑淹没排查起来费时费力。另外数据库文件一定要定期备份ACCESS 文件损坏的概率虽然不高但一旦损坏恢复工具也不一定能救回来。我一般会在程序启动时自动复制一份带日期的备份到 backup 目录保留最近七天的。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站