From fd047e21438f926d8baedcceba2d85de91954cf7 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Fri, 24 Jul 2026 16:14:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20Attachment=20=E8=A1=A8=E5=85=B3?= =?UTF-8?q?=E8=81=94=E5=AD=97=E6=AE=B5=20NS=20=E6=9B=B4=E5=90=8D=E4=B8=BA?= =?UTF-8?q?=20SN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 数据库侧已将 Common.Attachment 的 NS 列重命名为 SN,同步更新代码: - db.py: upsert_attachments 的 DELETE/INSERT 改用 [SN],distinct_sn 变量与 相关注释、日志文案统一更新 - write_attachments.py: 模块 docstring 与 convert_results_to_rows 的行列说明 由 (NS, ...) 改为 (SN, ...);写入目标描述 Common.Attachment.SN - README.md: 落库约定与字段表中 NS 全部改为 SN 已用 --sn 26B10 实测写入并用 SELECT [SN] 验证数据正确落库。 Co-Authored-By: WorkBuddy --- README.md | 10 +++++----- db.py | 22 +++++++++++----------- write_attachments.py | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d322e64..7875e6f 100644 --- a/README.md +++ b/README.md @@ -270,16 +270,16 @@ python write_attachments.py --mode fine --enable-other 落库约定(与 `db.py` 常量、`write_attachments.py` 的转换逻辑保持一致): - **有附件**(`has_attachment=true`,`status=ok`):每个 `type` 写一行。 - - `fine` 模式:`type` 形如 `大类:细分`,按首个冒号拆分为 `(NS, 大类, 细分)`。 - - `coarse` 模式:`type` 是大类,小类统一填占位值 `无` → `(NS, 大类, '无')`。 + - `fine` 模式:`type` 形如 `大类:细分`,按首个冒号拆分为 `(SN, 大类, 细分)`。 + - `coarse` 模式:`type` 是大类,小类统一填占位值 `无` → `(SN, 大类, '无')`。 - **无附件**(`has_attachment=false`,含 `empty_param` 与模型判无附件):写哨兵行 - `(NS, '无附件', '无')`,下游用 `WHERE MajorCategory <> '无附件'` 取真实附件。 + `(SN, '无附件', '无')`,下游用 `WHERE MajorCategory <> '无附件'` 取真实附件。 - **无法确定/失败**(`has_attachment=null`,含 `not_found` / `llm_*_error` / `db_error`):一律不写,既不当作无附件,也不留脏数据。 -- **幂等**:写入时对同一总排号先删除旧行再插入本次结果(依赖 `NS, MajorCategory, +- **幂等**:写入时对同一总排号先删除旧行再插入本次结果(依赖 `SN, MajorCategory, MinorCategory` 唯一索引),重跑安全。 -目标表 `Common.Attachment` 字段:`NS`(nvarchar(30),总排号/关联键)、 +目标表 `Common.Attachment` 字段:`SN`(nvarchar(30),总排号/关联键)、 `MajorCategory`(nvarchar(40),附件大类)、`MinorCategory`(nvarchar(40),附件小类), 三者均 `NOT NULL`。 diff --git a/db.py b/db.py index 3210fee..432bce0 100644 --- a/db.py +++ b/db.py @@ -133,7 +133,7 @@ def fetch_param_by_id( # 附件分类落库(目标表 Common.Attachment,与源表 productionContractData 分属不同 schema) # --------------------------------------------------------------------------- # 落库约定(与项目记忆 MEMORY.md 中写入约定一致,请勿在此处用字面量以外的值): -# - 无附件(has_attachment=false):写哨兵行 (NS, '无附件', '无') +# - 无附件(has_attachment=false):写哨兵行 (SN, '无附件', '无') # - 无小类的行(coarse 真实附件 / 哨兵行):MinorCategory 统一填 '无' ATTACHMENT_SCHEMA = "Common" ATTACHMENT_TABLE = "Attachment" @@ -175,9 +175,9 @@ def upsert_attachments( ) -> tuple[int, int]: """幂等写入 Common.Attachment。 - rows: 本次要写入的 (NS, MajorCategory, MinorCategory) 列表。 - 对出现的每个 NS 先 DELETE 其旧行,再批量 INSERT——保证重跑总是反映 - 最新分类结果,不会因唯一索引 (NS, 大类, 小类) 冲突而失败。 + rows: 本次要写入的 (SN, MajorCategory, MinorCategory) 列表。 + 对出现的每个 SN 先 DELETE 其旧行,再批量 INSERT——保证重跑总是反映 + 最新分类结果,不会因唯一索引 (SN, 大类, 小类) 冲突而失败。 返回 (deleted_rows, inserted_rows) 计数。 """ @@ -185,30 +185,30 @@ def upsert_attachments( return (0, 0) qualified = f"[{ATTACHMENT_SCHEMA}].[{ATTACHMENT_TABLE}]" - distinct_ns = sorted({r[0] for r in rows}) + distinct_sn = sorted({r[0] for r in rows}) conn_str = _build_conn_str(db_cfg) try: with pyodbc.connect(conn_str, timeout=db_cfg["connect_timeout"]) as conn: conn.timeout = db_cfg["query_timeout"] cursor = conn.cursor() - # 1) 删除本批所有 NS 的旧行 - del_ph = ",".join("?" for _ in distinct_ns) + # 1) 删除本批所有 SN 的旧行 + del_ph = ",".join("?" for _ in distinct_sn) cursor.execute( - f"DELETE FROM {qualified} WHERE [NS] IN ({del_ph})", distinct_ns + f"DELETE FROM {qualified} WHERE [SN] IN ({del_ph})", distinct_sn ) deleted = cursor.rowcount # 2) 插入新行 cursor.executemany( - f"INSERT INTO {qualified} ([NS], [MajorCategory], [MinorCategory]) " + f"INSERT INTO {qualified} ([SN], [MajorCategory], [MinorCategory]) " f"VALUES (?, ?, ?)", rows, ) inserted = len(rows) conn.commit() logger.info( - "upsert_attachments: 删除 %d 行, 插入 %d 行, 涉及 %d 个 NS", - deleted, inserted, len(distinct_ns), + "upsert_attachments: 删除 %d 行, 插入 %d 行, 涉及 %d 个 SN", + deleted, inserted, len(distinct_sn), ) return (deleted, inserted) except pyodbc.Error as e: diff --git a/write_attachments.py b/write_attachments.py index a27d63b..27e7992 100644 --- a/write_attachments.py +++ b/write_attachments.py @@ -6,7 +6,7 @@ - has_attachment=true (status=ok): 每个 type 一行。fine 模式 type 形如 "大类:细分",按首个冒号拆成 (大类, 小类); coarse 模式 type 是大类,小类统一填 '无'。 - - has_attachment=false (无附件): 写哨兵行 (NS, '无附件', '无')。 + - has_attachment=false (无附件): 写哨兵行 (SN, '无附件', '无')。 - has_attachment=null (not_found / llm_error / db_error): 不写(属"无法确定/失败")。 用法: @@ -25,7 +25,7 @@ --id 数据库真实 ID 列(id_field),如 802 --sn 总排号列(id_column),如 26B742(即原先 --id 的语义) --ids-file 每行一个总排号(键类型 sn) -无论用哪种方式,结果均按回查到的总排号写入 Common.Attachment.NS。 +无论用哪种方式,结果均按回查到的总排号写入 Common.Attachment.SN。 """ from __future__ import annotations @@ -54,7 +54,7 @@ def convert_results_to_rows(results: list[dict], mode: str) -> tuple[list[tuple[ """将 classify_batch 的结果列表转成可写入 Common.Attachment 的行。 返回 (rows, skipped): - rows - list[(NS, MajorCategory, MinorCategory)] + rows - list[(SN, MajorCategory, MinorCategory)] skipped- list[总排号],has_attachment 为 None(not_found/失败)未写入的 """ rows: list[tuple[str, str, str]] = []