news 2026/9/10 23:13:13

数据库专题07:评论与删除策略——外键、软删除和权限必须一起设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据库专题07:评论与删除策略——外键、软删除和权限必须一起设计

数据库专题07:评论与删除策略——外键、软删除和权限必须一起设计

删除评论不是简单的delete from comments。用户需要看到“该评论已删除”,审计需要知道谁删除,文章删除时又要决定评论是否一起清理。本篇为评论增加软删除字段,用 SQL 同时完成所有权判断和状态改变,并讨论文章级联删除、匿名化和数据保留的取舍。

上一篇练习讲解

标签练习的关键是中间表复合主键和规范化标签名。删除一篇文章只应级联删除它的article_tags,仍被其他文章引用的标签必须保留。标签文章列表按(created_at,id)游标分页,不能把所有关联一次加载进内存。

1. 评论表:事实和显示状态分开

createtablecomments(id bigserialprimarykey,article_idbigintnotnullreferencesarticles(id)ondeletecascade,user_idbigintnotnullreferencesusers(id),contenttextnotnull,created_at timestamptznotnulldefaultnow(),deleted_at timestamptz,deleted_bybigintreferencesusers(id),delete_reasonvarchar(200),constraintcomment_delete_statecheck((deleted_atisnullanddeleted_byisnull)or(deleted_atisnotnullanddeleted_byisnotnull)));createindexidx_comments_article_createdoncomments(article_id,created_atdesc)wheredeleted_atisnull;

正文保留用于审计,但公开 API 在deleted_at非空时只返回“该评论已删除”,不能继续暴露原文。如果隐私政策要求彻底删除,后台任务可在保留期后匿名化content,审计事件只记录 id 和原因。

2. 发布评论

fromsqlalchemyimporttextdefadd_comment(conn,article_id:int,user_id:int,content:str)->int:"""只允许对已发布文章评论,避免草稿被猜 id 后写入。"""content=content.strip()ifnotcontentorlen(content)>2000:raiseValueError("评论需为 1~2000 个字符")row=conn.execute(text(""" insert into comments(article_id,user_id,content) select id,:user_id,:content from articles where id=:article_id and status='published' returning id """),{"article_id":article_id,"user_id":user_id,"content":content}).first()ifrowisNone:raiseLookupError("文章不存在或未发布")returnrow.id

insert ... select把文章状态校验和插入放进一条语句,减少并发窗口。外键仍负责用户和文章存在性。

3. 作者删除与管理员删除

defdelete_comment(conn,comment_id:int,current_user:dict,reason:str)->None:"""评论作者可删除自己评论;管理员可删除任意评论。重复删除返回幂等成功。"""ifcurrent_user["role"]=="admin":condition="id=:id and deleted_at is null"else:condition="id=:id and user_id=:user_id and deleted_at is null"result=conn.execute(text(f""" update comments set deleted_at=now(), deleted_by=:user_id, delete_reason=:reason where{condition}"""),{"id":comment_id,"user_id":current_user["id"],"reason":reason[:200]})ifresult.rowcount==0:existing=conn.execute(text("select deleted_at from comments where id=:id"),{"id":comment_id}).first()ifexistingandexisting.deleted_at:returnraisePermissionError("评论不存在或无权删除")

这里的 f-string 只拼接程序内部固定条件,不含用户输入。角色来自登录会话,不允许请求体传role=admin

4. 评论列表和计数

selectc.id,c.created_at,u.email,casewhenc.deleted_atisnullthenc.contentelse'该评论已删除'endascontentfromcomments cjoinusers uonu.id=c.user_idwherec.article_id=:article_idorderbyc.created_atasc,c.idasclimit:size;selectarticle_id,count(*)fromcommentswheredeleted_atisnullgroupbyarticle_id;

详情时间线保留删除占位,报表计数排除软删除。两种查询访问模式不同,索引需要结合EXPLAIN验证。

验收与故障排查

草稿文章评论 -> LookupError 发布文章评论 -> comment_id=1 其他用户删除 -> PermissionError 本人删除两次 -> 第二次幂等成功,deleted_at 不变化 公开列表 -> 只显示“该评论已删除”

如果删除后计数仍增加,检查所有聚合是否都包含deleted_at is null;如果外键阻止删除用户,需要在产品层决定禁止删用户、匿名化用户还是on delete set null,不要临时禁用外键。

课后练习

实现评论游标分页和管理员删除审计事件;增加“30 天后把已删正文替换为[removed]”的批处理,并保证重复运行安全。下一篇用唯一约束实现幂等点赞。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 23:13:01

AI Agent Skills生态的安全风险与防护实践

1. AI Agent Skills生态的崛起与潜在风险AI Agent Skills生态正在经历爆发式增长。根据最新行业报告显示,2023年全球AI Agent Skills市场同比增长超过300%,预计到2026年将形成千亿级规模的市场。这种快速增长背后是开发者对AI能力扩展的强烈需求——通过…

作者头像 李华
网站建设 2026/9/10 23:10:54

嵌入式C++轻量级测试框架设计与实践

1. 嵌入式C测试框架概述 在嵌入式系统开发中,C因其高效性和面向对象特性成为主流开发语言之一。但嵌入式环境的特殊性(资源受限、实时性要求高、硬件依赖强)使得传统测试框架往往难以直接适用。我曾在多个嵌入式项目中尝试过不同测试方案&…

作者头像 李华
网站建设 2026/9/10 23:10:34

CANN/GE获取物理流数量API

GetPhysicalStreamNum 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Tens…

作者头像 李华
网站建设 2026/9/10 23:08:30

配电网韧性提升:移动储能预布局与动态调度策略及Matlab实现

这两年做配电网韧性课题的人越来越多,打开任何一本电力系统方向的期刊,十篇里至少有两三篇在谈极端事件下的供电恢复。但真正动手把论文里的方法变成可运行的代码,你会发现里面全是坑。你准备复现的这个课题——面向配电网韧性提升的移动储能…

作者头像 李华
网站建设 2026/9/10 23:06:32

2026年7月深圳市光明区二手房价格深度分析报告

一、报告摘要本报告基于2026年7月深圳市光明区实际成交案例,对区域二手房价格进行深度分析。报告涵盖成交概况、价格走势、热门板块对比、典型楼盘案例分析以及未来趋势研判,为购房者和投资者提供数据参考。二、光明区二手房市场整体概况2026年7月&#…

作者头像 李华