Files
akmon/POSTGRESQL_CONSTRAINT_FIX.md
2026-01-20 08:04:15 +08:00

3.3 KiB

PostgreSQL 约束修复说明

问题描述

在原始的 video_system_database.sql 中,使用了 PostgreSQL 不支持的 CHECK 约束语法:

CONSTRAINT chk_play_media_type CHECK (
    EXISTS (
        SELECT 1 FROM ak_contents 
        WHERE id = content_id 
        AND content_type IN ('video', 'audio')
    )
)

PostgreSQL 不允许在 CHECK 约束中使用子查询,这会导致部署时报错。

修复方案

1. 移除了有问题的 CHECK 约束

移除了以下表中的 CHECK 约束:

  • ak_video_play_records.chk_play_media_type
  • ak_image_tags.chk_image_tag_type
  • ak_image_view_records.chk_image_view_type

2. 应用层校验替代方案

创建了带内容类型校验的 RPC 函数:

弹幕插入函数

SELECT insert_danmu_with_validation(
    content_id, 
    '弹幕内容', 
    time_position,
    color,
    font_size,
    position_type
);

图片标签插入函数

SELECT insert_image_tag_with_validation(
    content_id,
    '标签名称',
    'user', -- 标签类型
    confidence -- 置信度(可选)
);

播放记录函数

SELECT record_play_progress_with_validation(
    content_id,
    play_position,
    play_duration,
    device_type,
    resolution,
    quality
);

数据完整性保证

1. 外键约束

所有相关表都有适当的外键约束,确保引用完整性。

2. 应用层校验

通过 RPC 函数在应用层进行内容类型校验:

  • 弹幕:仅限 videoaudio 内容
  • 播放记录:仅限 videoaudio 内容
  • 图片标签:仅限 image 内容
  • 图片浏览记录:仅限 image 内容

3. 触发器机制

统计更新触发器仍然有效,自动维护内容统计数据。

使用建议

前端调用示例

// 弹幕插入
const { data: danmuId } = await supabase.rpc('insert_danmu_with_validation', {
  p_content_id: contentId,
  p_content: danmuText,
  p_time_position: currentTime,
  p_color: '#FFFFFF',
  p_font_size: 16
});

// 图片标签添加
const { data: tagId } = await supabase.rpc('insert_image_tag_with_validation', {
  p_content_id: imageId,
  p_tag_name: tagName,
  p_tag_type: 'user'
});

// 播放进度记录
const { data: recordId } = await supabase.rpc('record_play_progress_with_validation', {
  p_content_id: videoId,
  p_play_position: currentTime,
  p_play_duration: totalDuration,
  p_device_type: 'mobile'
});

错误处理

RPC 函数会抛出明确的错误信息:

  • 内容不存在
  • 只有视频和音频内容支持弹幕功能
  • 只有图片内容支持标签功能
  • 只有视频和音频内容支持播放记录

直接插入的风险

如果绕过 RPC 函数直接插入数据,可能会导致数据不一致:

  • 图片内容可能被插入弹幕记录
  • 视频内容可能被插入图片标签

建议始终使用提供的 RPC 函数进行数据操作。

部署验证

修复后的数据库可以正常部署到 Supabase 或任何 PostgreSQL 实例,不会出现约束相关的错误。

下一步

  1. 部署更新后的数据库结构
  2. 在前端代码中使用 RPC 函数替代直接的表插入
  3. 测试各种内容类型的操作,确保校验正常工作
  4. 可选:添加更多业务逻辑校验(如敏感词过滤、权限检查等)