SQL字符串精准定位与条件填充实战:POSITION+SUBSTRING+CASE WHEN
1. 这不是“查数据”而是“精准定位智能填充”的组合拳SQL里最常被低估的其实是字段级的字符串操作能力。很多人一看到“从指定字段查找指定字符”第一反应是LIKE加%模糊匹配——这就像用消防水枪给盆栽浇水方向对了但精度和效率全丢了。真正高效的方案是把字符串当作可拆解、可索引、可编程的结构来处理。标题里这句“sql从‘指定字段’查找‘指定字符’外加条件判断函数返回指定条件填充”说白了就是三步闭环定位 → 判断 → 填充。它不依赖外部程序不触发全表扫描所有逻辑在单条SQL内完成执行一次就出结果。我去年帮某高校实验室优化一个学生选课日志分析系统时原脚本用Python读取百万行日志再逐行正则匹配耗时47分钟改写成纯SQL的CASE WHEN嵌套POSITIONSUBSTRING后整个查询压到8.3秒且数据库负载下降62%。这种能力特别适合做数据清洗、报表字段动态生成、日志关键词提取、用户行为路径标记等场景。如果你正在处理订单备注里的优惠券码识别、客服工单中的紧急等级标注、或IoT设备上报字符串里的状态位解析那这个标题背后的技术链就是你该立刻掌握的“字段手术刀”。2. 核心设计思路为什么必须用POSITION/SUBSTRING而非LIKE2.1 传统LIKE的致命缺陷它只回答“有没有”不告诉你“在哪里”LIKE %abc%这类写法看似简单实则暗藏三重陷阱第一索引失效。只要左侧带%B-Tree索引就彻底作废MySQL/PostgreSQL都会退化为全表扫描。我测试过一张1200万行的订单表对order_remark字段执行WHERE order_remark LIKE %优惠券%执行计划显示type: ALL实际耗时23.6秒而改用POSITION(优惠券 IN order_remark) 0后type: index耗时降至0.8秒——差距近30倍。第二无法定位位置。LIKE只能返回布尔值但业务常需要知道“优惠券码从第几个字符开始”。比如备注字段是已使用优惠券COUP2024-001减免15.5元你不仅要判断存在更要提取COUP2024-001这个子串。LIKE对此束手无策。第三无法支持多条件嵌套。当需求变成“如果含‘紧急’且不含‘已解决’则标为P0如果含‘延期’且创建时间3天则标为P1”LIKE的布尔逻辑根本撑不起这种复合判断。2.2 POSITIONSUBSTRING构成的“字符串坐标系”POSITION(needle IN haystack)函数PostgreSQL/SQL Server或INSTR(haystack, needle)MySQL是真正的破局点。它返回子串首次出现的起始位置从1开始计数把字符串变成了可定位的坐标空间。例如SELECT POSITION(优惠券 IN 已使用优惠券COUP2024-001) AS pos; -- 返回值6因为优是第6个字符有了位置坐标SUBSTRING(haystack FROM start FOR length)就能精准截取。继续上面的例子SELECT SUBSTRING(已使用优惠券COUP2024-001 FROM 10 FOR 12) AS coupon_code; -- 返回值COUP2024-001这里的关键洞察是位置计算必须可复用。不能硬编码FROM 10而要让起始位置由POSITION动态计算。实际写法是SUBSTRING(order_remark FROM POSITION(优惠券 IN order_remark) 5) -- 5是因为优惠券共5个字符跳过它才能取后面的码这种“位置驱动截取”的模式让SQL具备了类似编程语言中str.find()str.slice()的能力这才是标题中“指定字段查找指定字符”的技术内核。2.3 CASE WHEN把离散判断编译成数据库原生指令很多开发者试图用IF函数或存储过程实现条件填充这是典型的“用错工具”。CASE WHEN是SQL标准中最高效、最易优化的分支结构。它的优势在于编译期优化数据库查询优化器会将CASE分支预编译为跳转表比运行时解析IF快3-5倍短路执行一旦某个WHEN条件为真后续分支完全不执行避免冗余计算类型安全所有THEN分支必须返回同类型强制你在设计阶段就明确输出格式。举个真实案例某电商后台需根据订单备注自动标记物流状态。原始需求是备注含“已发货”且不含“待揽收” → 标为“已出库”备注含“待揽收”且创建时间2小时 → 标为“待揽收”其他情况 → 标为“处理中”用CASE WHEN实现SELECT order_id, CASE WHEN POSITION(已发货 IN remark) 0 AND POSITION(待揽收 IN remark) 0 THEN 已出库 WHEN POSITION(待揽收 IN remark) 0 AND NOW() - create_time INTERVAL 2 hours THEN 待揽收 ELSE 处理中 END AS logistics_status FROM orders;注意这里POSITION(待揽收 IN remark) 0的写法——当子串不存在时POSITION返回0这是比NOT LIKE更精确的否定判断。这种写法在千万级数据上实测性能稳定且逻辑清晰无歧义。3. 实操细节从字段解析到动态填充的完整链路3.1 字段预处理先解决编码与空格干扰真实业务数据永远比示例脏。我处理过的某医疗系统日志表patient_info字段里混着全角空格、不可见换行符、甚至BOM头。直接POSITION(姓名 IN patient_info)会失败因为实际字符串可能是 姓名张三\n开头是全角空格。必须前置清洗-- PostgreSQL示例移除首尾空白、替换全角空格、删除控制字符 SELECT TRIM( TRANSLATE( REGEXP_REPLACE(patient_info, E[\\u0000-\\u0008\\u000B-\\u000C\\u000E-\\u001F], , g), , ) ) AS cleaned_info FROM medical_logs;这段代码分三层REGEXP_REPLACE(..., E[\\u0000-\\u0008...], , g)用正则清除ASCII控制字符0x00-0x08, 0x0B-0x0C等TRANSLATE(..., , )把全角空格U3000替换成半角空格TRIM()去掉首尾所有空白字符包括制表符、换行符。提示MySQL 8.0支持REGEXP_REPLACE但语法略有不同若用旧版MySQL可用REPLACE(REPLACE(field, CHAR(160), ), \n, )逐层替换。关键原则是——清洗必须在POSITION之前完成否则位置计算全错。3.2 动态截取用位置偏移实现“所见即所得”提取假设要从log_content字段提取形如[ERROR] code1001, msgtimeout中的错误码。难点在于code后面不一定是4位数字可能是code500或code99999。硬编码SUBSTRING(log_content FROM X FOR 4)必然失败。正确解法是双位置锚定SELECT log_content, -- 第一步找到code的起始位置 POSITION(code IN log_content) AS code_start_pos, -- 第二步找到code之后第一个逗号的位置作为结束锚点 POSITION(, IN SUBSTRING(log_content FROM POSITION(code IN log_content) 5)) AS comma_after_code, -- 第三步计算实际截取长度逗号位置减1因为SUBSTRING从1开始计数 CASE WHEN POSITION(code IN log_content) 0 AND POSITION(, IN SUBSTRING(log_content FROM POSITION(code IN log_content) 5)) 0 THEN SUBSTRING( log_content FROM POSITION(code IN log_content) 5 FOR POSITION(, IN SUBSTRING(log_content FROM POSITION(code IN log_content) 5)) - 1 ) ELSE NULL END AS error_code FROM system_logs;这个写法的核心技巧是用SUBSTRING制造局部视图再在局部视图里找相对位置。SUBSTRING(log_content FROM X)相当于把原字符串从X位置开始切片后续的POSITION就在这个切片里找逗号得到的是相对于切片开头的偏移量完美避开全局位置计算的复杂性。3.3 条件填充CASE WHEN的嵌套艺术与性能边界当条件超过3层时CASE WHEN容易写成意大利面条式代码。我的经验是用“主干分支”结构主干用POSITION快速筛出高频场景分支对主干未覆盖的字段用更精细的SUBSTRINGPOSITION二次定位。例如用户标签系统需从user_profile字段提取城市但数据格式混乱大部分是城市北京|行业IT少量是location:shanghai,age:25极少数是【上海】用户欢迎优化写法SELECT user_id, CASE -- 主干优先匹配中文格式占比85% WHEN POSITION(城市 IN user_profile) 0 THEN SUBSTRING(user_profile FROM POSITION(城市 IN user_profile) 4 FOR 20) -- 分支1匹配英文格式 WHEN POSITION(location: IN user_profile) 0 THEN SPLIT_PART( SUBSTRING(user_profile FROM POSITION(location: IN user_profile) 9), ,, 1 ) -- 分支2匹配方括号格式 WHEN POSITION(【 IN user_profile) 0 AND POSITION(】 IN user_profile) POSITION(【 IN user_profile) THEN SUBSTRING( user_profile FROM POSITION(【 IN user_profile) 1 FOR POSITION(】 IN user_profile) - POSITION(【 IN user_profile) - 1 ) ELSE 未知 END AS city_tag FROM users;注意SPLIT_PART是PostgreSQL特有函数MySQL用SUBSTRING_INDEX这里体现的是按数据分布分层处理的思想。实测表明把高频场景放在CASE前面能减少60%以上的低效分支计算。4. 实操全流程以电商订单备注解析为例4.1 需求还原从模糊描述到可执行SQL客户原始需求“订单备注里可能有优惠券码、赠品信息、特殊要求要自动提取并分类”。我们拆解为具体字段coupon_code提取优惠券COUP2024-001中的COUP2024-001gift_item提取赠品蓝牙耳机黑色中的蓝牙耳机黑色special_req当备注含“加急”且不含“已处理”时填“优先配货”建表语句简化版CREATE TABLE orders ( id SERIAL PRIMARY KEY, remark TEXT NOT NULL, create_time TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); INSERT INTO orders (remark, create_time) VALUES (已使用优惠券COUP2024-001赠品蓝牙耳机黑色, 2024-05-20 10:30:00), (加急请今天发出, 2024-05-20 14:22:00), (赠品定制鼠标垫, 2024-05-19 09:15:00);4.2 完整SQL实现位置计算条件填充一体化SELECT id, remark, -- 提取优惠券码先找优惠券位置再找其后第一个逗号或结尾 CASE WHEN POSITION(优惠券 IN remark) 0 THEN -- 计算优惠券后的起始位置 SUBSTRING( remark FROM POSITION(优惠券 IN remark) 5 -- 截取长度取到下一个逗号或到字符串末尾 FOR COALESCE( NULLIF( POSITION(, IN SUBSTRING(remark FROM POSITION(优惠券 IN remark) 5)) - 1, -1 ), LENGTH(remark) - POSITION(优惠券 IN remark) - 4 ) ) ELSE NULL END AS coupon_code, -- 提取赠品逻辑同上但用赠品为锚点 CASE WHEN POSITION(赠品 IN remark) 0 THEN SUBSTRING( remark FROM POSITION(赠品 IN remark) 4 FOR COALESCE( NULLIF( POSITION(, IN SUBSTRING(remark FROM POSITION(赠品 IN remark) 4)) - 1, -1 ), LENGTH(remark) - POSITION(赠品 IN remark) - 3 ) ) ELSE NULL END AS gift_item, -- 特殊要求纯条件判断不涉及截取 CASE WHEN POSITION(加急 IN remark) 0 AND POSITION(已处理 IN remark) 0 THEN 优先配货 ELSE NULL END AS special_req, -- 综合状态用嵌套CASE生成最终标签 CASE WHEN POSITION(优惠券 IN remark) 0 AND POSITION(赠品 IN remark) 0 THEN 满赠优惠 WHEN POSITION(加急 IN remark) 0 THEN 加急订单 WHEN POSITION(赠品 IN remark) 0 THEN 赠品订单 ELSE 普通订单 END AS order_type FROM orders;4.3 执行结果与关键参数验证运行上述SQL得到结果idremarkcoupon_codegift_itemspecial_reqorder_type1已使用优惠券COUP2024-001赠品蓝牙耳机黑色COUP2024-001蓝牙耳机黑色NULL满赠优惠2加急请今天发出NULLNULL优先配货加急订单3赠品定制鼠标垫NULL定制鼠标垫NULL赠品订单重点验证coupon_code的截取逻辑对id1POSITION(优惠券 IN remark)8所以FROM 8513SUBSTRING(remark FROM 13)得到COUP2024-001赠品蓝牙耳机黑色POSITION(, IN ...)14逗号在第14位所以FOR 14-113SUBSTRING(... FROM 13 FOR 13)正好取到COUP2024-001。这个计算过程在数据库内部毫秒级完成无需任何应用层干预。5. 常见问题与避坑指南血泪总结的12个实战陷阱5.1 位置计算类问题问题现象根本原因解决方案实操心得POSITION始终返回0字段含不可见字符如零宽空格U200B用LENGTH(field)对比LENGTH(TRIM(field))差值0即存在隐藏字符用REGEXP_REPLACE(field, [^[:print:]], )清除我曾因U200B导致3个字段的POSITION全部失效排查耗时2天。现在新项目必加SELECT LENGTH(col), LENGTH(TRIM(col)) FROM table LIMIT 5做基线检查截取结果为空字符串SUBSTRING的FOR length参数为负数用GREATEST(0, calculated_length)包裹长度计算MySQL中SUBSTRING(str FROM x FOR -1)会返回空串PostgreSQL直接报错务必加防御性判断中文字符位置错乱数据库字符集非UTF8mb4导致一个汉字占3字节但POSITION按字节计数检查SHOW VARIABLES LIKE character_set%;确保character_set_client/connection/results均为utf8mb4某次迁移老系统时character_set_database是latin1POSITION(你好 IN abc你好)返回4按字节实际应为4按字符必须统一字符集5.2 条件判断类问题问题现象根本原因解决方案实操心得CASE WHEN返回NULL而非预期值某个WHEN分支的条件表达式本身为NULL如POSITION(NULL IN field)所有参与判断的字段先用COALESCE(field, )兜底在remark字段允许NULL的表中POSITION(abc IN NULL)返回NULL导致整个WHEN条件为UNKNOWN跳过执行。永远对可能为NULL的字段做COALESCE性能骤降从0.1秒到15秒CASE中嵌套了多次POSITION重复计算同一子串提前用CTE或子查询计算位置再在主查询引用改写前CASE WHEN POSITION(A IN f) 0 THEN SUBSTRING(f FROM POSITION(A IN f)) END计算2次改写后WITH pos AS (SELECT id, POSITION(A IN f) AS a_pos FROM t) SELECT CASE WHEN a_pos 0 THEN SUBSTRING(f FROM a_pos) END FROM t JOIN pos USING(id)计算1次多条件AND失效用AND连接多个POSITION 0但某个字段为NULL导致整个条件为NULL改用AND前加IS NOT NULL显式判断或用COALESCE(POSITION(...), 0) 0SQL中NULL AND TRUE结果是NULL而非FALSECASE会跳过该分支。必须把NULL转化为确定的布尔值5.3 跨数据库兼容性问题场景PostgreSQLMySQL 8.0SQL Server兼容写法建议查找子串位置POSITION(a IN str)INSTR(str, a)CHARINDEX(a, str)写视图时用CASE WHEN version() LIKE PostgreSQL% THEN ...动态选择或应用层适配截取子串SUBSTRING(str FROM start FOR len)SUBSTRING(str, start, len)SUBSTRING(str, start, len)MySQL和SQL Server的start参数从1开始与PG一致但MySQL的SUBSTR别名也支持替换字符串REPLACE(str, a, b)REPLACE(str, a, b)REPLACE(str, a, b)此函数三者完全一致可放心通用正则替换REGEXP_REPLACE(str, pattern, repl)REGEXP_REPLACE(str, pattern, repl)不支持需用PATINDEXSTUFF组合复杂清洗尽量在ETL层做SQL层只做确定性操作最后分享一个压箱底技巧当POSITION找不到目标时不要只返回0而是用COALESCE(NULLIF(POSITION(key IN field), 0), LENGTH(field)1)把0转为一个“超尾位置”。这样在SUBSTRING中FROM 超尾位置会自然返回空串避免额外的CASE判断代码更简洁。这个技巧在我优化的17个生产SQL中平均减少12%的执行时间。

相关新闻

Python+MySQL学生选课管理系统:从数据库设计到答辩避坑全指南

Python+MySQL学生选课管理系统:从数据库设计到答辩避坑全指南

简介:基于Python和MySQL实现的学生选课管理系统,是一份面向计算机相关专业期末大作业或毕业设计的完整项目包。项目由导师指导并通过高分评审,源码均经过本地编译调试,可稳定运行,适合需要快速构建课程设计或提升实战能…

2026/10/13 9:20:47 阅读更多 →
COMSOL激光熔覆与选区熔融仿真:从热源标定到残余应力评估

COMSOL激光熔覆与选区熔融仿真:从热源标定到残余应力评估

做激光熔覆和选区熔融仿真的这些年,我被问得最多的一句话是——“COMSOL到底能不能把这两个工艺算清楚?”我的回答通常是一半肯定、一半劝退:能,但前提是你得把热源标定、材料参数温度相关性、相变潜热、单元激活、熔池对流这几件…

2026/10/13 9:20:47 阅读更多 →
Python+MySQL实现学生选课系统:数据库设计与事务避坑指南

Python+MySQL实现学生选课系统:数据库设计与事务避坑指南

简介:基于Python和MySQL的学生选课管理系统源码包,专为计算机相关专业期末大作业及课程设计场景打造,项目经导师指导并审核,评审得分98分,难度适中,适合正在完成课设、毕设或需要项目实战练习的学习者。压缩…

2026/10/13 9:20:47 阅读更多 →

最新新闻

PowerContext挂接MiniMax Code:终结跨会话与跨Agent上下文断裂

PowerContext挂接MiniMax Code:终结跨会话与跨Agent上下文断裂

大约两个星期前,我把手头的项目从“上下文完全靠每次手动贴”的方式,切到了 PowerContext 挂接 MiniMax Code 的方式。困扰我很久的一个问题终于不再是问题:跨会话和跨 Agent 之间的项目上下文,不再断裂了。起因很简单。我开一个新…

2026/10/13 10:00:16 阅读更多 →
领域模型进化:GRPO 强化学习与 Post-training Engineering

领域模型进化:GRPO 强化学习与 Post-training Engineering

通用大模型(base model)是个通才。它在万亿 token 上做过 next-token prediction,把世界知识压缩进了权重,但你让它写一段符合你公司合规规范的代码、审一份你领域的合同、跑通你内部系统的 SQL,它大概率会给你一个&qu…

2026/10/13 10:00:16 阅读更多 →
t3code 深度拆解:编码工具核心原理与实操避坑指南

t3code 深度拆解:编码工具核心原理与实操避坑指南

1. 从“t3code”这个标题说起:它到底是什么,能解决什么问题第一次看到“t3code”这个标题,很多人会一头雾水。它不像“Python爬虫实战”那样直白,也不像“家庭咖啡烘焙指南”那样有明确场景。但恰恰是这种模糊性,给了我…

2026/10/13 10:00:16 阅读更多 →
Seldon Core Pipeline 就绪状态检查实战:从 tfsimples 示例到 ready 接口的源码解析

Seldon Core Pipeline 就绪状态检查实战:从 tfsimples 示例到 ready 接口的源码解析

人工智能大模型MLOpsLLMOps模型推理服务云原生后端 【免费下载链接】seldon-core An MLOps framework to package, deploy, monitor and manage thousands of production machine learning models 项目地址: https://gitcode.com/gh_mirrors/se/seldon-core 点击查看…

2026/10/13 10:00:16 阅读更多 →
Oracle到达梦迁移实战:数据类型、SQL语法与存储过程避坑指南

Oracle到达梦迁移实战:数据类型、SQL语法与存储过程避坑指南

1. 迁移之前,先把两边的“家底”摸清楚1.1 为什么Oracle到达梦的迁移总在“意料之外”翻车做过数据库迁移的人都有一个共识:迁移本身不难,难的是迁移之后业务跑不起来。Oracle到达梦的迁移尤其如此,因为这两套数据库虽然都支持SQL…

2026/10/13 10:00:16 阅读更多 →
Java垃圾分类系统:树形分类建模与时间窗调度实战

Java垃圾分类系统:树形分类建模与时间窗调度实战

简介:这是一套已高分通过的Java毕业设计项目源码,面向计算机专业本科生及Java初学者,聚焦城市垃圾分类回收管理场景,提供从用户注册登录、垃圾类型分类录入、回收点信息维护、预约回收申请到后台数据统计的完整业务闭环&#xff0…

2026/10/13 9:59:14 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →