Files
wvp-platform/数据库/aiot/执行指南-为现有摄像头生成camera_code.md
16337 b2c2159967 docs(aiot): 添加为现有摄像头生成camera_code的执行指南
- 详细的SQL执行步骤和验证方法
- 常见问题解答和回滚方案
- 确保旧摄像头数据兼容性
2026-02-13 13:30:58 +08:00

6.8 KiB
Raw Blame History

为现有摄像头生成 camera_code - 执行指南

目的: 为数据库中已存在的摄像头生成唯一的 camera_code 标识符

执行时间: 2026-02-13

重要性: ⚠️ 必须执行!否则旧摄像头的 camera_code 为空,前端将无法正常使用


🚀 快速执行(推荐)

方法一MySQL 命令行执行

# 1. 进入 MySQL
mysql -u root -p wvp_aiot

# 2. 执行迁移脚本
source C:/workspace/wvp-platform/数据库/aiot/迁移-添加camera_code字段.sql

# 3. 查看执行结果
# 脚本会自动显示验证结果和样本数据

方法二直接复制SQL执行

如果 source 命令不可用请复制以下SQL直接在MySQL客户端执行

-- 1. 新增 camera_code 列(如果不存在)
ALTER TABLE wvp_stream_proxy
  ADD COLUMN IF NOT EXISTS camera_code VARCHAR(64) NULL COMMENT '摄像头全局唯一编码格式cam_xxxxxxxxxxxx';

-- 2. 为现有数据生成 camera_code基于 ID 生成12位哈希
UPDATE wvp_stream_proxy
  SET camera_code = CONCAT('cam_', SUBSTRING(MD5(CAST(id AS CHAR)), 1, 12))
  WHERE camera_code IS NULL OR camera_code = '';

-- 3. 将 camera_code 设为 NOT NULL 并添加唯一索引(如果不存在)
ALTER TABLE wvp_stream_proxy
  MODIFY COLUMN camera_code VARCHAR(64) NOT NULL;

-- 添加唯一索引(如果不存在,忽略错误)
ALTER TABLE wvp_stream_proxy
  ADD UNIQUE KEY uk_camera_code (camera_code);

-- 4. 验证数据完整性 - 检查重复
SELECT '检查重复的 camera_code' AS check_name, COUNT(*) AS issue_count
FROM (
  SELECT camera_code, COUNT(*) AS cnt
  FROM wvp_stream_proxy
  GROUP BY camera_code
  HAVING cnt > 1
) AS duplicates;

-- 5. 验证格式
SELECT '检查格式错误的 camera_code' AS check_name, COUNT(*) AS issue_count
FROM wvp_stream_proxy
WHERE camera_code NOT REGEXP '^cam_[a-f0-9]{12}$';

-- 6. 更新 ROI 表中的 camera_id从 app/stream 格式改为 camera_code
UPDATE wvp_ai_roi r
  INNER JOIN wvp_stream_proxy sp ON r.camera_id = CONCAT(sp.app, '/', sp.stream)
  SET r.camera_id = sp.camera_code;

-- 7. 验证 ROI 更新结果
SELECT '检查未匹配的 ROI' AS check_name, COUNT(*) AS issue_count
FROM wvp_ai_roi r
LEFT JOIN wvp_stream_proxy sp ON r.camera_id = sp.camera_code
WHERE sp.camera_code IS NULL;

-- 8. 显示迁移后的样本数据
SELECT id, camera_code, app, stream, name
FROM wvp_stream_proxy
LIMIT 5;

SELECT roi_id, camera_id, name
FROM wvp_ai_roi
LIMIT 5;

验证执行结果

执行完成后,应该看到以下输出:

1. 重复检查

check_name                  | issue_count
-------------------------------------------
检查重复的 camera_code        | 0

issue_count = 0 表示无重复

2. 格式检查

check_name                       | issue_count
------------------------------------------------
检查格式错误的 camera_code         | 0

issue_count = 0 表示格式正确

3. ROI 匹配检查

check_name              | issue_count
---------------------------------------
检查未匹配的 ROI          | 0

issue_count = 0 表示 ROI 关联正确

4. 样本数据示例

-- wvp_stream_proxy 样本
+----+------------------+------+----------+--------+
| id | camera_code      | app  | stream   | name   |
+----+------------------+------+----------+--------+
| 1  | cam_c4ca4238a0b9 | live | camera01 | 大堂   |
| 2  | cam_c81e728d9d4c | live | camera02 | 停车场 |
+----+------------------+------+----------+--------+

-- wvp_ai_roi 样本
+--------+------------------+----------+
| roi_id | camera_id        | name     |
+--------+------------------+----------+
| 1      | cam_c4ca4238a0b9 | ROI区域1 |
| 2      | cam_c81e728d9d4c | ROI区域2 |
+--------+------------------+----------+

camera_code 格式为 cam_xxxxxxxxxxxx12位十六进制


🔍 手动验证(可选)

如果需要手动检查执行以下SQL

-- 1. 检查所有摄像头是否都有 camera_code
SELECT COUNT(*) AS total_cameras,
       COUNT(camera_code) AS with_code,
       COUNT(*) - COUNT(camera_code) AS missing_code
FROM wvp_stream_proxy;

期望结果: missing_code = 0

-- 2. 检查 camera_code 唯一性
SELECT COUNT(DISTINCT camera_code) AS unique_codes,
       COUNT(*) AS total_rows
FROM wvp_stream_proxy;

期望结果: unique_codes = total_rows

-- 3. 检查 ROI 表是否正确关联
SELECT COUNT(*) AS total_rois,
       COUNT(sp.camera_code) AS matched_rois,
       COUNT(*) - COUNT(sp.camera_code) AS unmatched_rois
FROM wvp_ai_roi r
LEFT JOIN wvp_stream_proxy sp ON r.camera_id = sp.camera_code;

期望结果: unmatched_rois = 0


⚠️ 常见问题

Q1: 执行时报错 "Duplicate key name 'uk_camera_code'"

原因: 索引已存在(可能之前执行过)

解决: 忽略此错误,继续执行后续步骤

Q2: ROI 更新显示 0 rows affected

原因:

  • 情况1: 没有 ROI 数据(正常)
  • 情况2: camera_id 格式已经是 camera_code已迁移过

验证: 执行验证SQL检查 unmatched_rois 是否为 0

Q3: 某些摄像头的 camera_code 仍然为空

原因: UPDATE 语句条件过滤了这些记录

解决: 手动为这些记录生成 camera_code

UPDATE wvp_stream_proxy
SET camera_code = CONCAT('cam_', SUBSTRING(MD5(CONCAT('manual_', id, '_', NOW())), 1, 12))
WHERE camera_code IS NULL OR camera_code = '';

📊 迁移前后对比

迁移前

wvp_stream_proxy:
  - app: "live"
  - stream: "camera01"
  - camera_code: NULL ❌

wvp_ai_roi:
  - camera_id: "live/camera01" ❌ (拼接格式,不稳定)

迁移后

wvp_stream_proxy:
  - app: "live"
  - stream: "camera01"
  - camera_code: "cam_c4ca4238a0b9" ✅

wvp_ai_roi:
  - camera_id: "cam_c4ca4238a0b9" ✅ (唯一标识符,稳定)

🔄 回滚(如果需要)

如果迁移出现问题,可以执行回滚:

-- 1. 恢复 ROI 表的 camera_id需要在迁移前备份原始值
-- 注意:此步骤需要提前备份!
UPDATE wvp_ai_roi r
INNER JOIN wvp_stream_proxy sp ON r.camera_id = sp.camera_code
SET r.camera_id = CONCAT(sp.app, '/', sp.stream);

-- 2. 删除 camera_code 列
ALTER TABLE wvp_stream_proxy DROP COLUMN camera_code;

⚠️ 重要: 建议在执行迁移前先备份数据库!

# 备份数据库
mysqldump -u root -p wvp_aiot > wvp_aiot_backup_20260213.sql

执行完成标志

当您看到以下结果时,表示迁移成功:

  • 所有验证查询的 issue_count 都为 0
  • 样本数据中的 camera_code 格式为 cam_xxxxxxxxxxxx
  • wvp_ai_roi 表的 camera_id 已更新为 camera_code
  • 前端摄像头管理页面能正常显示"应用名"列
  • 新增摄像头时自动生成 camera_code

执行人: _______________ 执行时间: _______________ 验证结果: ☐ 通过 ☐ 失败 备注: _______________