Access数据库实例:从建表到录入数据的完整操作

站长资讯2小时前发布 jdkjadmin
0 00
Access数据库实例:从建表到录入数据的完整操作

Access数据库实例:从建表到录入数据的完整操作

Access 适合制作小型、以桌面办公为中心的数据应用:例如部门维护客户与订单、个人管理设备清单、团队通过表单录入内部台账。它把数据表、查询、窗体和报表放在一个数据库文件中,入门门槛低,也可以用 VBA 自动化操作。

但 Access 不是大型网站的数据库服务器,也不能仅靠给表设置密码就实现精细的用户权限管理。本文从创建数据库开始,逐步建立客户表和订单表,演示如何录入数据,并说明哪些场景适用、哪些边界需要提前考虑。示例以 Windows 桌面版 Access 的 .accdb 文件为例,代码使用 DAO(Data Access Objects)。

一、先判断 Access 是否适合

Access 通常适用于数据量和并发规模有限、使用者主要在局域网或办公环境中、需要快速构建录入界面的场景。它尤其适合原型、部门级工具和个人数据库:可以直接用设计视图建表,再利用窗体降低录入错误,用查询和报表整理结果。

如果系统要面向互联网开放、需要稳定支持大量并发写入、需要细致的角色与行级权限,或者必须承受高可用和灾备要求,应评估 SQL Server、PostgreSQL 等服务器数据库。Access 数据库文件通常不应直接暴露给互联网用户,也不适合多个远程用户通过不稳定网络同时读写。

Access 数据库文件的大小上限为 2 GB(系统对象也计入),这是文件格式层面的上限,不代表接近上限时仍有良好体验。实际可用规模还取决于记录宽度、索引、附件、查询方式和并发情况。Access 的理论并发用户上限也不等于推荐的实际并发规模;文件共享环境中的网络质量、锁冲突和写入频率都会影响稳定性。

二、创建数据库文件

  1. 打开 Microsoft Access,选择“空白数据库”。
  2. 输入文件名,例如 OfficeDemo.accdb,选择保存位置。
  3. 单击“创建”。如果 Access 自动新建了一个空表,可以关闭该表;出现保存提示时选择不保存。

开发时建议把文件放在本机可写目录。多用户使用时,常见做法是拆分数据库:后端文件只放表,置于受控的局域网共享目录;每位用户各自持有一份前端文件,前端包含查询、窗体、报表和 VBA,并链接后端表。拆分可减少前端文件被多人同时修改的风险,但不会把 Access 变成服务器数据库,也不能替代备份和权限管理。

三、设计数据表:先想清楚字段和关系

本例管理客户和订单。一个客户可以有多张订单,因此建立两张表:

  • Customers:存客户的基本信息。
  • Orders:存订单,并通过 CustomerID 指向客户。

每张表都使用自动编号字段作为主键。订单表保存客户编号,而不是把客户姓名复制到每张订单中。这样客户改名时只需更新一处,也能避免同一客户被写成多个近似名称。

字段类型应按数据含义选择。电话号码看起来像数字,但通常不参与加减计算,且可能包含前导零、加号或分机,因此使用短文本比使用数字类型更合适。金额使用货币类型,日期时间使用日期/时间类型。自动编号由 Access 生成,录入时不要自行指定。

四、用 SQL 建表

在 Access 中,选择“创建”→“查询设计”,关闭“显示表”窗口,然后切换到“SQL 视图”。把下面两段 SQL 分别粘贴执行。每次只执行一个 CREATE TABLE 语句;Access 查询设计器一般不适合一次执行多条 DDL 语句。

CREATE TABLE Customers (
    CustomerID COUNTER CONSTRAINT PK_Customers PRIMARY KEY,
    CustomerName TEXT(100) NOT NULL,
    Phone TEXT(30),
    CreatedAt DATETIME
);
CREATE TABLE Orders (
    OrderID COUNTER CONSTRAINT PK_Orders PRIMARY KEY,
    CustomerID LONG NOT NULL,
    OrderDate DATETIME,
    Amount CURRENCY,
    CONSTRAINT FK_Orders_Customers
        FOREIGN KEY (CustomerID)
        REFERENCES Customers (CustomerID)
);

COUNTER 是 Access SQL 中的自动编号类型;LONG 与自动编号主键的数值类型兼容,可用于保存外键。TEXT(n) 表示长度受限的短文本,Access 短文本字段最多可存 255 个字符。NOT NULL 表示该字段必须有值;没有写 NOT NULL 的字段允许为空。

如果第二条语句因外键语法、已有同名对象或 Access 版本差异而失败,可以先只创建订单表,不在 DDL 中声明外键,再通过“数据库工具”→“关系”建立关系:添加两张表,将 Customers.CustomerID 拖到 Orders.CustomerID,勾选“实施参照完整性”,保存关系。不能实施参照完整性时,先检查订单表是否已有指向不存在客户的编号,以及两列的数据类型是否兼容。

Access 的 SQL 方言与 SQL Server、MySQL 并不完全相同。不要未经测试就照搬其他数据库的建表语法、数据类型或约束。尤其是复杂的校验规则,优先使用表设计中的验证规则、窗体验证或明确的业务逻辑,不要假设所有标准 SQL 约束都能按其他数据库的方式工作。

五、也可以用设计视图建表

如果希望通过界面操作,在“创建”选项卡中选择“表设计”,逐行添加字段:

表字段数据类型设置
CustomersCustomerID自动编号设为主键
CustomersCustomerName短文本字段大小 100;必填设为“是”
CustomersPhone短文本字段大小 30
CustomersCreatedAt日期/时间可为空
OrdersOrderID自动编号设为主键
OrdersCustomerID数字字段大小选“长整型”;必填设为“是”
OrdersOrderDate日期/时间可为空
OrdersAmount货币可为空

保存表时分别命名为 Customers 和 Orders。设置外键时,关键是订单中的 CustomerID 要设为“数字”,并将“字段大小”设为“长整型”;若设成整数或自动编号,可能与客户表主键不匹配。也可以在关系窗口中勾选“级联更新相关字段”和“级联删除相关记录”,但应先明确业务后果。级联删除可能一并删除关联订单,不要为了消除错误提示而随意开启。

六、通过界面录入一条数据

  1. 打开 Customers 表,在新记录行中输入客户名称和电话号码。CustomerID 会由 Access 自动生成。
  2. 保存并记下生成的客户编号。自动编号可能跳号,不应把“编号连续”作为业务要求。
  3. 打开 Orders 表,新建记录,在 CustomerID 中输入刚才的客户编号。
  4. 填写日期和金额后离开该行,Access 会提交记录。

如果已实施参照完整性,订单中填写不存在的 CustomerID 会被拒绝。这是预期保护,不要通过关闭关系约束来掩盖数据录入错误。正式应用通常不会让用户直接输入编号,而是使用下拉框显示客户名称、实际保存客户编号。

七、用 VBA 和 DAO 安全录入

如果需要自动化录入,可以在 Access 中按 Alt+F11 打开 VBA 编辑器,选择“插入”→“模块”。以下示例使用 DAO 对象和参数查询,完成“新增客户,再为该客户新增订单”的操作。

代码假设两张表已按前文建立。在 VBA 编辑器中,打开“工具”→“引用”,确认勾选当前 Office/Access 版本的 Microsoft Office Access database engine Object Library(名称可能随版本略有差异),然后把代码放入标准模块。运行 AddSampleCustomerAndOrder。如果相应 DAO 类型无法识别,通常是引用未启用。

Option Compare Database
Option Explicit

Public Sub AddSampleCustomerAndOrder()
    Dim db As DAO.Database
    Dim ws As DAO.Workspace
    Dim rs As DAO.Recordset
    Dim qd As DAO.QueryDef
    Dim customerId As Long

    Set db = CurrentDb
    Set ws = DBEngine.Workspaces(0)

    On Error GoTo ErrHandler
    ws.BeginTrans

    '新增客户,让 Access 生成自动编号主键。
    Set rs = db.OpenRecordset("Customers", dbOpenDynaset)
    rs.AddNew
    rs!CustomerName = "示例客户"
    rs!Phone = "021-12345678"
    rs!CreatedAt = Now()
    rs.Update

    'Update 后读取刚刚新增记录的自动编号。
    rs.Bookmark = rs.LastModified
    customerId = rs!CustomerID
    rs.Close
    Set rs = Nothing

    '参数用于传递值,避免把文本、日期和数值拼进 SQL。
    Set qd = db.CreateQueryDef("", _
        "PARAMETERS [pCustomerID] Long, " & _
        "[pOrderDate] DateTime, [pAmount] Currency; " & _
        "INSERT INTO Orders (CustomerID, OrderDate, Amount) " & _
        "VALUES ([pCustomerID], [pOrderDate], [pAmount]);")

    qd.Parameters("pCustomerID").Value = customerId
    qd.Parameters("pOrderDate").Value = Date
    qd.Parameters("pAmount").Value = CCur(128.5)

    'dbFailOnError 让写入失败时产生错误,而不是静默忽略。
    db.Execute qd.SQL, dbFailOnError

    ws.CommitTrans
    MsgBox "客户和订单已保存,客户编号为 " & customerId, vbInformation

CleanExit:
    On Error Resume Next
    If Not rs Is Nothing Then rs.Close
    Set rs = Nothing
    Set qd = Nothing
    Set db = Nothing
    Set ws = Nothing
    Exit Sub

ErrHandler:
    On Error Resume Next
    ws.Rollback
    MsgBox "录入失败:" & Err.Description, vbExclamation
    Resume CleanExit
End Sub

事务让两次写入作为一个整体提交:客户和订单都成功才提交;中间发生错误则回滚,避免留下只有客户、没有订单的半成品。示例使用当前 Access 数据库的工作区事务,适用于本地 DAO 操作。事务开始后应尽快完成工作,不要在事务中等待用户输入或执行耗时操作。

代码里的参数声明类型要与实际字段相符:pCustomerID 为长整型,日期参数为日期/时间,金额参数为货币。参数名应与 SQL 中的名称一致。使用 db.CreateQueryDef("", sql) 创建的是临时 QueryDef,不会在导航窗格中保存查询。

八、参数化查询能做什么,不能做什么

参数化查询适合把数据值传给 SQL,例如文本、日期、金额和编号。它能避免常见的字符串拼接错误:姓名中含单引号时,不必手动替换引号;日期也不需要依赖地区格式拼接成 SQL 字面量。参数化还可以降低把用户输入误当 SQL 语法执行的风险。

参数并不能代替权限检查、输入校验或业务规则。即使使用参数,也应确认客户编号存在、金额范围合理、当前用户是否有权新增记录。DAO 参数的类型要匹配目标字段;需要写入空值时,应明确使用 Null,而不是空字符串或数字零。字段是否允许空值仍由表结构决定。

参数用于值,不能用来替换表名、字段名、排序方向或 SQL 关键字。例如不能期待把 ORDER BY [pField] 的参数设置为字段名后,就完成动态排序。需要动态选择列时,应从代码中预先定义的白名单中选取合法字段,再组装标识符部分;不要直接拼接用户任意输入。DAO、ADO、ODBC 或不同 Access 版本在参数声明和调用方式上可能不同,示例是 DAO 的 Access 用法,不应直接当作其他驱动的语法。

九、常见错误与排查

1. 提示数据类型不匹配

检查字段定义和输入类型。外键应是与自动编号主键兼容的长整型;金额字段使用货币而不是短文本;日期字段不要把任意格式的字符串直接当作日期。DAO 参数声明也要与字段类型一致。

2. 外键值不存在

先确认客户记录已提交,并使用实际生成的 CustomerID。不要假设自动编号从 1 开始或连续增长。若从外部导入数据,先清理没有对应客户的订单记录,再实施参照完整性。

3. SQL 提示语法错误

Access 使用自己的 SQL 方言。确认表名和字段名拼写一致;与关键字冲突或含空格的名称应使用方括号,例如 [Order]。建表语句逐条执行,并检查当前运行的是 Access 查询设计器,而不是把 Access SQL 发给其他数据库执行。

4. 文本过长或字符异常

短文本字段受字段大小限制,写入超过限制的内容可能被截断或报错。保存长篇内容应考虑“长文本”字段,但不要把大段文件内容随意塞进字段。使用 Unicode 文本时,Access 字段可存储常见多语言字符;从外部文件导入时仍要核对源文件编码和导入选项。

5. 记录看似没保存

表格视图中编辑当前行后,通常需要离开该行或显式保存记录。代码写入时,检查是否调用了 Update,DAO 的 Execute 是否使用 dbFailOnError,以及错误处理是否把失败信息展示出来。事务未提交时,其他操作也可能看不到预期结果。

6. 自动编号有空缺

自动编号是用于唯一标识记录的技术键,不是发票号或需要连续的业务序号。记录删除、事务回滚等情况都可能造成编号空缺。若业务确实要求连续编号,需要单独设计受控的编号分配逻辑,并考虑并发、删除和审计规则。

十、录入方式的选择与安全维护

直接在表格视图录入适合少量测试数据;正式使用时,建议建立窗体,使用组合框选择客户,并在窗体中校验必填项、日期和金额范围。表单能改善操作体验,但真正的数据完整性仍应尽可能由表结构和关系约束兜底,因为数据也可能通过查询、导入或 VBA 写入。

Access 的文件密码或数据库加密适合降低数据库文件被未授权人员直接打开的风险,但它不等于服务器端的细粒度授权。传统 Access 工作组级用户安全机制不适用于现代 .accdb 数据库。文件共享权限、用户电脑权限、备份访问权限都需要单独管理;不要把数据库文件放在任何人都能读取的公共目录。

在共享文件环境中,应为每位用户提供本地前端,后端放在稳定且受控的文件共享位置,避免通过互联网或不可靠 VPN 直接打开同一个数据库文件。定期备份后端,并实际测试恢复流程。结构调整和批量导入前先备份;如果文件变大或出现性能、锁定问题,也可以评估拆分数据、归档旧记录,或迁移到服务器数据库。

总结

从一个可用的 Access 数据库开始,关键不是先写复杂代码,而是把表和关系设计正确:用主键识别记录,用外键表达关联,按实际含义选择字段类型,再选择表格视图、窗体或 DAO 程序录入。本文的客户—订单示例提供了建表 SQL、关系设置方法和可运行的参数化 VBA 写入代码。

当数据规模、并发量或安全要求超出 Access 文件共享模式的舒适范围时,应尽早迁移或把 Access 仅作为前端。这样既能发挥它在办公自动化和快速建模上的优势,也能避免把单机数据库误用为需要服务器级能力的系统。

© 版权声明

相关文章