用好 Open SQL 的 FETCH:用数据库游标把海量结果集按包读出来,TaoToken 统一 Key 通道
1. 海量取数为什么总在 FETCH 上翻车做 ABAP 报表或接口取数绕不开一个经典矛盾业务要的结果集很大但应用服务器内存有限网络往返也不想抖得太厉害。把所有数据一次性SELECT ... INTO TABLE拉到内表里轻则响应慢重则直接把 work process 顶到短转储。我见过太多夜间批处理作业白天测试跑得好好的一上生产数据量翻十倍就崩。FETCH NEXT CURSOR的价值就在于把数据库端的结果集变成一个可持续消费的数据流。你可以把读取粒度控制在PACKAGE SIZE上既能稳定内存又能更顺滑地做分批处理、分批写入、分批输出。它属于 ABAP Open SQL用来从数据库游标对应的结果集中按当前游标位置提取数据并用INTO或APPENDING把数据赋值到目标数据对象里。每一次 FETCH 执行完游标位置都会向后移动提取的行数为下一次读取做好准备。从工程角度看可以把它理解为数据库端保存了一个可前进的读取指针ABAP 端通过 FETCH 像读文件一样一段段消费数据而不是一次性把整个文件读进内存。这篇内容面向报表与接口取数场景交付可复制的OPEN CURSOR / FETCH ... INTO TABLE ... PACKAGE SIZE代码骨架、包大小取值建议以及用SY-SUBRC与包计数验证分批完整性的动作。同时说明如何通过 TaoToken 统一 Key 通道管理调用凭据让取数脚本和外部 AI 服务调用共用一套凭据治理方式。适合谁看正在写 ABAP 报表、接口取数、夜间批处理或者被短转储和内存溢出折磨过的开发者。如果你只会SELECT INTO TABLE一把梭这篇能帮你把资源曲线拉平。2. TaoToken 统一 Key 通道取数脚本调用外部服务的凭据前置在报表和接口取数场景里ABAP 程序本身负责从数据库分批读数据但很多项目还需要把取到的数据推给外部服务做进一步处理比如调用大模型做文本分类、摘要、字段补全或者调用 AI 接口做数据清洗。这时候就会遇到一个现实问题调用凭据怎么管。传统做法是把 API Key 硬编码在 ABAP 代码里或者放在自定义表里。硬编码的问题很明显代码一提交Key 就跟着进版本库了放自定义表里又得自己处理加密、轮换、权限。更麻烦的是一个项目里可能同时用多个模型服务每个服务一套 Key管理成本直线上升。TaoToken 的思路是提供一个统一的 Key 通道。你只需要在 TaoToken 官网注册后拿到一个 Key就可以通过统一的 API 入口调用不同的模型服务。对于 ABAP 取数场景来说这意味着你可以在SM30维护表里只存一个 TaoToken Key或者通过SSF加密后存在自定义表里程序里通过CL_HTTP_CLIENT调用时统一带上这个 Key。具体操作上你可以先访问 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号然后在控制台创建 API Key。拿到 Key 之后在 ABAP 里调用外部服务时把 Key 放在 HTTP 请求头里即可。TaoToken 的 API 入口是 https://taotoken.net/api不带 UTM 参数适合在代码里直接引用。这里要强调一点TaoToken 是统一的 Key 管理通道不是让你在 ABAP 里直接连数据库。你的数据读取还是走 Open SQL 的 FETCH 游标TaoToken 只负责管理你调用外部 AI 服务时的凭据。两者是配合关系不是替代关系。对于需要长期跑批处理、调用外部服务的场景可以考虑 TaoToken 的 Coding Plan它适合需要稳定调用额度的项目。如果你只是想先验证模型效果可以用模型对话功能快速测试。接入文档在 TaoToken 的 doc 页面有详细说明API Keys 管理在 console 里操作。在 ABAP 侧建议把 TaoToken Key 的读取封装成一个独立的函数模块比如Z_GET_TAOTOKEN_KEY内部从加密表或SSF读取返回给调用方。这样取数程序和外部服务调用程序可以共用同一套凭据读取逻辑轮换 Key 时只需要改一处。3. 可复制的 OPEN CURSOR / FETCH 配置骨架这一节给出可以直接复制到 ABAP 程序里的代码骨架。先看最基本的游标声明和打开。DATA: dbcur TYPE cursor, lt_data TYPE TABLE OF bseg, lv_package_size TYPE i VALUE 5000, lv_total TYPE i VALUE 0, lv_package_count TYPE i VALUE 0. OPEN CURSOR dbcur FOR SELECT * FROM bseg WHERE bukrs p_bukrs AND gjahr p_gjahr ORDER BY belnr, buzei.这里有几个关键点。dbcur必须声明为cursor类型这是硬约束。主机变量要用转义符前缀书写这是现代 ABAP SQL 的规范严格语法检查模式下不加会报错。OPEN CURSOR的 SELECT 语句里不能用INTO因为游标只是打开结果集不立即取数。接下来是循环取包的核心骨架。DO. FETCH NEXT CURSOR dbcur INTO TABLE lt_data PACKAGE SIZE lv_package_size. IF sy-subrc 0. EXIT. ENDIF. lv_package_count lv_package_count 1. lv_total lv_total lines( lt_data ). 在这里处理本包数据写入外部系统、调用 AI 服务、输出文件等 PERFORM process_package USING lt_data. CLEAR lt_data. ENDDO. CLOSE CURSOR dbcur.这段代码的语义很清晰每次 FETCH 取lv_package_size行到lt_datasy-subrc为 0 表示取到了数据为 4 表示结果集读完。注意sy-subrc 4时目标对象保持不变也就是lt_data不会被清空或覆盖所以你需要在循环体末尾手动CLEAR lt_data避免下一包数据追加到旧数据后面。PACKAGE SIZE的取值建议对于行宽较窄的表比如只有几个字段的日志表可以设到 10000 甚至 20000对于行宽较宽的表比如包含多个金额、文本字段的凭证行项目表建议 2000 到 5000。判断标准是单包内表占用的内存不要超过 work process 可用内存的十分之一。你可以先用ST05或者SAT跑一次看单包处理时间和内存峰值再调整。如果你需要在循环体里做COMMIT WORK比如每包提交一次外部接口调用那就要注意游标保持问题。OPEN CURSOR支持WITH HOLD选项用来影响数据库提交时游标是否保持。具体是否需要WITH HOLD取决于你在循环体里做了什么提交以及数据库行为。建议把它当成明确控制游标生命周期的工程化按钮而不是玄学开关。对于需要动态包大小的场景比如按单据号分组每组行数不同可以用双游标方案。第一个游标统计每组的行数第二个游标按该行数作为动态PACKAGE SIZE读取明细。DATA: BEGIN OF ls_count, carrid TYPE spfli-carrid, count TYPE i, END OF ls_count, lt_spfli TYPE TABLE OF spfli, dbcur1 TYPE cursor, dbcur2 TYPE cursor. OPEN CURSOR dbcur1 FOR SELECT carrid, count(*) AS count FROM spfli GROUP BY carrid ORDER BY carrid. OPEN CURSOR dbcur2 FOR SELECT * FROM spfli ORDER BY carrid. DO. FETCH NEXT CURSOR dbcur1 INTO ls_count. IF sy-subrc 0. EXIT. ENDIF. FETCH NEXT CURSOR dbcur2 INTO TABLE lt_spfli PACKAGE SIZE ls_count-count. 处理本组数据 CLEAR lt_spfli. ENDDO. CLOSE CURSOR: dbcur1, dbcur2.这段代码的动机是在单条 SELECT 语句里无法对PACKAGE SIZE做按组变化的动态控制于是用两个并行游标把包大小策略从数据库结果中计算出来。如果把carrid换成销售订单号把spfli换成行项目表这就是很多企业里按单据分包的通用思路。4. 验证请求与成功结果用 SY-SUBRC 和包计数确认分批完整性写完代码只是第一步怎么确认分批读取是完整的、没有漏行、没有重复才是工程化的关键。这一节给出几个验证动作。第一个动作用sy-dbcnt做累计行数日志。FETCH每次行提取后会把sy-dbcnt设置为截至当前为止从该结果集提取的累计行数。注意它是累计值不是本次包大小。你可以在每包处理完后写一条应用日志。DATA: lv_cumulative TYPE i. FETCH NEXT CURSOR dbcur INTO TABLE lt_data PACKAGE SIZE lv_package_size. IF sy-subrc 0. lv_cumulative sy-dbcnt. 写日志当前累计读取 lv_cumulative 行 MESSAGE i001(zlog) WITH 累计读取行数: lv_cumulative. ENDIF.当累计行数超过 2,147,483,647 发生溢出时sy-dbcnt会变为 -1。对于绝大多数报表场景这个上限够用但如果你做的是超大规模数据迁移就要注意这个边界。第二个动作用包计数和总行数做交叉验证。在循环开始前先用一条SELECT COUNT(*)拿到总行数循环结束后对比累计读取行数。DATA: lv_expected TYPE i, lv_actual TYPE i. SELECT COUNT(*) FROM bseg INTO lv_expected WHERE bukrs p_bukrs AND gjahr p_gjahr. ... 循环 FETCH 并累加 lv_actual ... IF lv_actual lv_expected. 记录差异触发告警 MESSAGE e002(zlog) WITH 行数不一致 预期: lv_expected 实际: lv_actual. ENDIF.这个动作能帮你发现游标提前关闭、异常分支跳过、PACKAGE SIZE设置不当导致的问题。实测下来很多分批读取的 bug 都是通过这个对比暴露出来的。第三个动作检查sy-subrc的退出条件。FETCH的sy-subrc含义很固定0 表示至少提取到一行4 表示没有提取到任何行。读完之后继续读会稳定返回 4。所以循环退出条件用IF sy-subrc 0. EXIT. ENDIF.是安全的。但要注意一个陷阱如果结果集本来就是空的第一次 FETCH 就返回 4循环直接退出lt_data保持初始状态。这时候你的包计数是 0累计行数也是 0和COUNT(*)的 0 一致验证通过。第四个动作验证游标是否被正确关闭。你可以在CLOSE CURSOR之后加一个检查确认没有游标泄漏。在同一个 ABAP 程序上下文中可同时打开的数据库游标数量是有限的超出会出现类似Too many open cursors的问题。真实项目里这类问题往往不是因为你故意开了很多游标而是因为异常分支或提前EXIT时忘了CLOSE导致游标泄漏到对话进程生命周期结束才释放。建议把游标处理写成固定模板打开、循环取包、退出、关闭并且用TRY ... CATCH cx_sy_open_sql_db包住关键节点至少能把短转储变成可诊断的应用日志。TRY. OPEN CURSOR dbcur FOR SELECT * FROM bseg WHERE bukrs p_bukrs. DO. FETCH NEXT CURSOR dbcur INTO TABLE lt_data PACKAGE SIZE lv_package_size. IF sy-subrc 0. EXIT. ENDIF. 处理数据 CLEAR lt_data. ENDDO. CLOSE CURSOR dbcur. CATCH cx_sy_open_sql_db INTO DATA(lx_sql). 记录异常确保游标关闭 IF dbcur IS NOT INITIAL. CLOSE CURSOR dbcur. ENDIF. MESSAGE lx_sql-get_text( ) TYPE E. ENDTRY.5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节对照真实报错给出排查路径。这些报错不一定都来自 ABAP 侧很多是调用外部服务时遇到的但排查思路是相通的。401 Unauthorized如果你在 ABAP 里调用 TaoToken 的 API 时遇到 401首先检查 Key 是否正确放在请求头里。TaoToken 的 API 入口是 https://taotoken.net/apiKey 放在Authorization: Bearer your_key头里。常见错误是 Key 前后多了空格或者用了错误的头字段名。在 ABAP 里可以用CL_HTTP_CLIENT的SET_REQUEST_HEADER_FIELD方法设置。local proxy failed这个报错通常出现在本地开发环境调用外部服务时。如果你在 ABAP 系统里配置了 HTTP 代理但代理地址或端口不对就会报这个。检查SM59里的 HTTP 目标配置确认代理设置和实际网络环境一致。注意这里说的是企业内网正常的 HTTP 代理配置不是让你去搞什么特殊网络工具。reading choices 相关报错如果你在调用模型服务时遇到返回体解析失败报错里出现reading choices字样通常是因为返回的 JSON 结构和你的解析代码不匹配。比如你期望的是choices[0].message.content但实际返回的是错误信息结构。建议在 ABAP 里先用CL_HTTP_CLIENT拿到原始返回字符串用WRITE输出到屏幕或写日志确认结构后再写解析逻辑。OAuth 相关报错如果你用的是需要 OAuth 认证的服务报错里出现invalid_token或token_expired说明访问令牌过期或无效。TaoToken 的 Key 通道本身是 API Key 模式不涉及 OAuth 流程但如果你在 ABAP 里同时调用了其他需要 OAuth 的服务就要单独处理令牌刷新。建议把不同服务的认证逻辑分开封装不要混在一个函数里。CX_SY_OPEN_SQL_DB 异常这是 ABAP 侧最常见的游标相关异常。触发条件包括dbcur没有声明为cursor类型、游标没有打开就 FETCH、游标已经关闭后继续 FETCH、在同一个dbcur上重复OPEN CURSOR。排查时先检查游标声明和打开顺序再检查是否有异常分支跳过了CLOSE CURSOR。Too many open cursors这个报错说明同时打开的游标数量超限。检查代码里是否有游标在异常路径下没有被关闭。建议用TRY ... CATCH包住游标操作在CATCH块里确保关闭游标。sy-subrc 判断错误有些开发者习惯用IF sy-subrc 0判断成功但在 FETCH 场景下sy-subrc 4表示结果集读完也是正常退出条件。如果你只判断 0可能会在结果集读完时进入死循环。正确的退出条件是IF sy-subrc 0. EXIT. ENDIF.。PACKAGE SIZE 设置过大导致短转储如果你把PACKAGE SIZE设得太大比如 100000单包内表可能直接撑爆内存。建议从 5000 开始试根据行宽和可用内存调整。可以用SAT跑一次性能分析看单包处理的内存峰值。CDS replacement object 导致语义变化在 S/4HANA 时代如果在OPEN CURSOR的 SELECT 数据源中某个数据库表或数据库视图被定义了 CDS 作为 replacement object那么后续 FETCH 实际访问的是 CDS而不是原始表或视图。这会导致字段计算、客户端处理、授权检查、甚至隐藏过滤介入性能画像和结果都可能改变。排查时用ST05看实际执行的 SQL确认数据源是否符合预期。6. 把 FETCH 放进现代 ABAP 的工程实践很多人把游标理解成行级处理等于慢这句话在不加限定时确实容易误导。如果你用FETCH INTO wa每次只取一行还在 ABAP 里做大量计算那当然慢。真正工程化的 FETCH 用法是用PACKAGE SIZE把数据库端结果集切片用批量方式搬运配合分包处理把系统资源拉平。在 S/4HANA、CDS、Gateway、RAP、BTP ABAP environment 这些现代场景里做稳定性优先的批处理或服务端分页时FETCH 依然是一把非常顺手的刀。关键不在于会不会写语法而在于你是否能把它当作资源控制器控制内存、控制节奏、控制生命周期并且在 clean core 与 released API 的边界里安全落地。如果你在项目里还需要调用外部 AI 服务做数据增强建议把 TaoToken 的 Key 管理封装成独立模块和取数逻辑解耦。取数程序只负责分批读数据外部服务调用程序只负责带 Key 发请求两者通过内表或队列传递数据。这样 Key 轮换时不影响取数逻辑取数逻辑调整时也不影响服务调用。TaoToken 的 API Keys 管理在 console 页面操作接入文档在 doc 页面有详细说明。如果你需要长期跑批处理并调用外部服务Coding Plan 适合需要稳定额度的场景。验证模型效果可以用模型对话功能快速测试。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endAPI 入口是 https://taotoken.net/api。最后给一个实用技巧在 ABAP 里调用外部服务时把 TaoToken Key 的读取和 HTTP 客户端调用封装成一个函数模块入参是请求体出参是响应体。这样你的取数程序里只需要调用这个函数模块不需要关心 Key 从哪里来、放在哪个请求头里。Key 轮换时只改函数模块内部实现调用方无感知。这个封装思路和游标处理的模板化思路是一致的把易变的部分隔离把稳定的部分复用。

相关新闻

从补习班到名校:韩国精英教育如何“制造”阶层?

从补习班到名校:韩国精英教育如何“制造”阶层?

1. 这个标题到底在说什么:从“译文”二字看韩国精英教育朋友把“Elite South Korean of an Elite Education”发给我的时候,她自己都笑了——这英文本身读着有点别扭,更像是先用中文想好了“精英教育下的韩国精英”再翻译回去的。但正是这种“…

2026/10/18 4:34:32 阅读更多 →
文生图实战:如何用AI稳定生成“半草绘”风格?LoRA与提示词调优全攻略

文生图实战:如何用AI稳定生成“半草绘”风格?LoRA与提示词调优全攻略

“半草绘”这三个字,我第一次看到的时候愣了一下。它是“半成品草图”还是“半手绘半数码”?后来看多了这类作品才明白,真正吸引人的是那种“未完成感”:画面里保留着松散的草稿线条、大块留白、几笔看似随意但精准的笔触&#xf…

2026/10/18 4:34:32 阅读更多 →
告别AI敷衍回复:用免费的提示词优化器Prompt Optimizer 3分钟跑通第一次优化

告别AI敷衍回复:用免费的提示词优化器Prompt Optimizer 3分钟跑通第一次优化

告别AI敷衍回复:用免费的提示词优化器Prompt Optimizer 3分钟跑通第一次优化 【免费下载链接】prompt-optimizer An AI prompt optimizer for writing better prompts and getting better AI results. 项目地址: https://gitcode.com/GitHub_Trending/pro/prompt-…

2026/10/18 4:33:31 阅读更多 →

最新新闻

Matlab实现ILFS无限潜在特征选择:分类特征降维实战

Matlab实现ILFS无限潜在特征选择:分类特征降维实战

1. 项目概述1.1 核心需求解析特征选择这件事,做数据分析的同学迟早都得面对。尤其在处理分类特征变量的时候,数据集动不动就是几十上百个维度,里面真正有用的可能就一小部分,剩下的全是干扰项。如果一股脑全丢进模型里&#xff0c…

2026/10/18 5:25:40 阅读更多 →
setTimeout 执行时机与参数传递详解:从事件循环到实战避坑

setTimeout 执行时机与参数传递详解:从事件循环到实战避坑

1. 从一次定时器“失灵”说起:setTimeout到底在什么时候执行很多人第一次用setTimeout都踩过同一个坑:明明写了setTimeout(fn, 0),结果代码并没有立刻执行,反而排在了后面。更让人困惑的是,当需要往回调函数里传参数时…

2026/10/18 5:25:40 阅读更多 →
YOLOv5改进之GAM全局注意力机制:涨点明显但计算量增加多少?

YOLOv5改进之GAM全局注意力机制:涨点明显但计算量增加多少?

在YOLOv5的各类改进方案中,注意力机制几乎是“人手一个”的标配。从SE、CBAM到ECA、CA,再到近两年被频繁引用的GAM(Global Attention Mechanism),各类注意力模块的论文和开源实现层出不穷。但一个被反复回避的问题是:GAM到底能涨多少点?代价又是什么? 本文基于近期的学…

2026/10/18 5:25:40 阅读更多 →
H5无插件播放链路实战:从RTSP到HTTP-FLV/HLS的工程选型

H5无插件播放链路实战:从RTSP到HTTP-FLV/HLS的工程选型

上个月我们单位那一套视频底座平台又要接新的大屏展示需求,前端同事跑过来问我:浏览器里能不能不装插件、直接用 H5 页面播放一路编号为 1078 的取流 URL?我说这不是能不能的问题,是协议对不对、链路通不通、播放器怎么选的问题。…

2026/10/18 5:25:40 阅读更多 →
初次为产线选工业涂料供应商,采购方应优先核查哪些能力

初次为产线选工业涂料供应商,采购方应优先核查哪些能力

先说结论 第一顺位不是报价,而是"这家能不能合规地供货"。营业执照经营范围与生产许可、检测报告的出具机构资质、报告引用的标准是否为现行版本,这三项属于一票否决项。 能力核查分三层:入场资质(能不能进你的合格供应…

2026/10/18 5:25:40 阅读更多 →
全数字全国产恒流板替代进口方案:工控设备厂降本15%案例拆解,国产化适配的3个关键决策

全数字全国产恒流板替代进口方案:工控设备厂降本15%案例拆解,国产化适配的3个关键决策

恒流板国产化替代的真实成本账:从38.6元到32.8元背后的三项关键验证不少工控设备厂的技术负责人都在问同一个问题:进口恒流板交期从4周拖到11周,打样被拒、认证卡壳、批次不良率在3%上下浮动,国产替代到底该怎么推?本文…

2026/10/18 5:24:40 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →