Misaka_Company 5de1d4ee51 优化 Access 全量写入:executemany 改为 CSV+Text 驱动单语句批量导入
- 根因:ACE/Jet 的 executemany 在网络盘(E:)上逐行落地,每行一次往返,35043 行约 10 分钟
- UNION ALL 参数化受 Jet 查询复杂度上限封死(查询过于复杂 -3071),不可用
- 改用官方 Text 导入路径:写入临时 Tab 分隔 CSV(GBK/cp936) + 动态 schema.ini,单条 INSERT...SELECT FROM [Text;...] 整批写入,往返从 35043 次压成 1 次
- 保留正确性保障:列约束值清洗(截断/夹日期) + 写入后 COUNT(*) 核对 + 不足时逐行回退并精确记录失败行
- 本地集成测试(真实 sync_access,35043 行)通过:行数+校验和完全一致
2026-07-15 16:03:12 +08:00

ProcurementVisibilityHub_DataSync

采购执行情况即时数据同步服务。将 169 共享盘上的 Excel采购执行情况即时数据.xlsx)同步写入两个目标库:

  • SQL Server114 / CompanyDBschema procurementVisibilityHub,表 请购执行
  • Access 生产库ProcurementVisibilityHub.accdb,表 procurementVisibilityHub_请购执行

采用全量覆盖策略SQL Server 端 TRUNCATE + INSERTAccess 端 DELETE + INSERT,并写入统一的「导入时间」。


目录结构

路径 说明
config/config.yaml 运行配置(含 DB 凭据,已被 .gitignore 忽略
src/config_loader.py 读取 YAML 配置、构造 ODBC 连接串
src/source_watcher.py 源文件变化检测mtime/size+ 下载到 data/
src/excel_parser.py 解析 xlsx → 行字典,含字段映射与类型转换
src/sync_writer.py 全量写入 SQL Server + Access
src/runner.py 主入口:服务循环 / 单次 / 本地联调 / dry-run
data/ 源文件历史副本(运行时生成,已忽略)
logs/sync.log 运行日志(运行时生成,已忽略)

环境要求

  • Python 3.10+
  • 目标主机需安装 ODBC 驱动:
    • ODBC Driver 17 for SQL Server(连 114 SQL Server
    • Microsoft Access Driver (*.mdb, *.accdb)(连 Access 生产库)
  • 依赖见 requirements.txtPyYAMLopenpyxlpyodbc

安装

# 1. 创建并激活虚拟环境(项目内)
python -m venv .venv
.\.venv\Scripts\activate        # Windows
# source .venv/bin/activate     # Linux/macOS

# 2. 安装依赖
pip install -r requirements.txt

# 3. 准备配置(从模板复制后填入真实凭据)
cp config/config.yaml.example config/config.yaml   # 若无模板,直接新建 config/config.yaml

⚠️ config/config.yaml 含数据库账号密码,不纳入版本管理。如需团队共享,请提交一份 config/config.yaml.example(占位凭据),真实配置留本地。


配置说明config/config.yaml 关键字段)

字段 说明
source.unc_path 源 Excel 的 UNC 路径169 共享盘)
source.local_cache_dir 本地历史副本目录(默认 data
scan.interval_seconds 服务循环扫描间隔(秒)
sql_server.* SQL Server 连接信息server/port/database/user/password…
access.* Access 库路径与表名DBQ/table
field_map Excel 列名 → 数据库字段名(仅列名不同者)
auto_fields 数据库自动生成字段:id_field(自增不写)、import_time_field=同步时刻)
sync.strategy 同步策略,当前固定 full
sync.batch_size 批量插入大小(默认 1000
logging 日志级别与目录

使用方式

# 服务循环模式(默认,配合 NSSM 部署为 Windows 服务)
python -m src.runner

# 单次运行后退出
python -m src.runner --once

# 用本地文件作源(跳过 169 下载,便于联调)
python -m src.runner --local X.xlsx

# 仅解析并打印,不写库
python -m src.runner --local X.xlsx --dry-run

# 指定配置文件
python -m src.runner --config config/config.yaml

运行逻辑:检测源 Excel 是否变化mtime/size无变化则跳过有变化则下载副本 → 解析 → 全量写入两个目标库。


运行流程

169 共享 Excel
      │  source_watcher 检测变化 + 下载到 data/
      ▼
excel_parser 解析(字段映射 + 类型转换float/datetime/int/text
      ▼
sync_writer 全量写入
   ├─ SQL ServerTRUNCATE + 分批 INSERTfast_executemany事务提交
   └─ Access     DELETE  + 分批 INSERTautocommit
      ▼
logs/sync.log 记录全过程

部署NSSM 服务)

以 Windows 服务常驻运行(主机 114由 NSSM 拉起 python -m src.runner 进入循环模式。日志统一写入 logs/sync.log


常见问题

  • 连不上 SQL Server:确认 ODBC Driver 17 已装、114:1433 可达、账号密码正确(Encrypt/TrustServerCertificate 与服务器端匹配)。
  • Access 写入失败:确认目标主机装了 Microsoft Access Driveraccess.dbq 路径存在、有写权限。
  • 源无变化不执行:属正常行为(基于 mtime/size 的增量跳过);想强制全量可用 --local 指定当前文件或删除 data/.source_meta.json 基准。
Description
169 Excel -> 114 SQL Server + Access
Readme 78 KiB
Languages
Python 100%