import sqlite3 db_path = 'security_monitor.db' conn = sqlite3.connect(db_path) cursor = conn.cursor() def add_column(table_name, col_name, col_type, default_value=None): try: if default_value: cursor.execute(f'ALTER TABLE {table_name} ADD COLUMN {col_name} {col_type} DEFAULT {default_value}') else: cursor.execute(f'ALTER TABLE {table_name} ADD COLUMN {col_name} {col_type}') print(f'添加列 {table_name}.{col_name} 成功') return True except sqlite3.OperationalError as e: if 'duplicate column name' in str(e): print(f'列 {table_name}.{col_name} 已存在') return True else: print(f'添加列 {table_name}.{col_name} 失败: {e}') return False print('=== 数据库迁移脚本 ===') print() # cameras 表 print('更新 cameras 表:') add_column('cameras', 'cloud_id', 'INTEGER') add_column('cameras', 'pending_sync', 'BOOLEAN', '0') add_column('cameras', 'sync_failed_at', 'TIMESTAMP') add_column('cameras', 'sync_retry_count', 'INTEGER', '0') print() # rois 表 print('更新 rois 表:') add_column('rois', 'cloud_id', 'INTEGER') add_column('rois', 'pending_sync', 'BOOLEAN', '0') add_column('rois', 'sync_failed_at', 'TIMESTAMP') add_column('rois', 'sync_retry_count', 'INTEGER', '0') add_column('rois', 'sync_version', 'INTEGER', '0') print() # alarms 表 print('更新 alarms 表:') add_column('alarms', 'cloud_id', 'INTEGER') add_column('alarms', 'upload_status', "TEXT", "'pending_upload'") add_column('alarms', 'upload_retry_count', 'INTEGER', '0') add_column('alarms', 'error_message', 'TEXT') add_column('alarms', 'region_data', 'TEXT') add_column('alarms', 'llm_checked', 'BOOLEAN', '0') add_column('alarms', 'llm_result', 'TEXT') add_column('alarms', 'processed', 'BOOLEAN', '0') print() # camera_status 表 print('更新 camera_status 表:') add_column('camera_status', 'last_frame_time', 'TIMESTAMP') print() conn.commit() # 验证表结构 print('=== 验证表结构 ===') for table in ['cameras', 'rois', 'alarms', 'camera_status']: cursor.execute(f'PRAGMA table_info({table})') cols = [col[1] for col in cursor.fetchall()] print(f'{table}: {len(cols)} 列') conn.close() print() print('数据库迁移完成!')