Files
medical-mall/docs/sql/00_meta/12_soft_delete_standard.md

3.0 KiB
Raw Blame History

数据库软删除 (Soft Delete) 统一标准规范

1. 核心目标

  • 数据保留:防止误操作导致的数据永久丢失,支持操作审计。
  • 级联安全:通过逻辑链路同步软删关联数据,避免孤儿数据。
  • 透明过滤:利用 RLS行级安全策略或统一过滤口径使业务层查询默认排除已标记删除的记录。

2. 字段规范

所有需要支持软删除的业务表必须统一包含以下字段:

字段名 类型 说明 索引建议
deleted_at TIMESTAMPTZ 删除时间戳。非 NULL 表示已删除。 必须建立索引
deleted_by UUID 执行删除操作的用户 ID (ak_users.id)。 建议索引
restored_at TIMESTAMPTZ (可选) 最近一次恢复的时间戳。 -
restored_by UUID (可选) 最近一次恢复的操作人。 -

3. RLS 自动过滤口径

为了确保查询透明性,必须在 20_rls/ 策略中统一加入过滤条件:

-- 示例策略:仅允许查询未删除的记录
CREATE POLICY select_active_records ON public.your_table
  FOR SELECT
  TO authenticated
  USING (deleted_at IS NULL);

4. RPC 重构准则

删除接口必须从 DELETE FROM ... 改为 UPDATE ... SET deleted_at = now()

4.1 基础删除模板

CREATE OR REPLACE FUNCTION public.rpc_admin_soft_delete_item(p_id UUID)
RETURNS BOOLEAN SECURITY DEFINER SET search_path = public AS $$
BEGIN
    -- 1. 鉴权 (示例)
    IF NOT EXISTS (
        SELECT 1 FROM public.ak_users 
        WHERE auth_id = auth.uid() AND role = 'admin'
    ) THEN
        RAISE EXCEPTION 'Permission denied';
    END IF;
    
    -- 2. 执行软删
    UPDATE public.your_table
    SET deleted_at = now(), deleted_by = auth.uid()
    WHERE id = p_id AND deleted_at IS NULL;
    
    RETURN FOUND;
END;
$$ LANGUAGE plpgsql;

4.2 级联软删除规范

若存在级联依赖(如:软删“商品分类”时需同步软删其下的“商品”),必须在 RPC 内部通过事务或同步 UPDATE 处理:

-- 级联链路示例
UPDATE public.ml_products
SET deleted_at = now(), deleted_by = auth.uid()
WHERE category_id = p_category_id AND deleted_at IS NULL;

5. UI 交互适配

  • 默认视图:列表页面默认仅展示 deleted_at IS NULL 的数据。
  • 回收站 (可选):若业务需要,可提供“回收站”视图(过滤 deleted_at IS NOT NULL)及“恢复”功能。
  • 二次确认:点击“删除”按钮时,必须弹出提示明确告知数据将进入逻辑删除状态。

6. 改造优先级

  1. 第一梯队:基础资产(商品、分类、文章、分销商)。
  2. 第二梯队配置类运费模板、通知模板、DIY 页面)。
  3. 第三梯队:日志/交互类(评论、收藏、地址)。