| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- """
- 数据库迁移脚本:为图像翻译表添加软删除字段
- 执行方式:
- python scripts/migrate_add_soft_delete.py
- 功能:
- 1. 添加 is_deleted 字段(Boolean,默认 False)
- 2. 添加 deleted_at 字段(DateTime,可为空)
- 3. 创建 is_deleted 索引
- """
- import sys
- import os
- # 添加项目根目录到 Python 路径
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- from sqlalchemy import text
- from app.database import engine, SessionLocal
- def run_migration():
- """执行数据库迁移"""
- print("=" * 60)
- print("开始执行迁移:为图像翻译表添加软删除字段")
- print("=" * 60)
-
- db = SessionLocal()
-
- try:
- # 1. 添加 is_deleted 字段
- print("\n[1/4] 添加 is_deleted 字段...")
- try:
- db.execute(text("""
- ALTER TABLE aigcspace.image_translation
- ADD COLUMN IF NOT EXISTS is_deleted BOOLEAN NOT NULL DEFAULT FALSE
- """))
- db.commit()
- print("✓ is_deleted 字段添加成功")
- except Exception as e:
- print(f"⚠ is_deleted 字段可能已存在: {e}")
- db.rollback()
-
- # 2. 添加 deleted_at 字段
- print("\n[2/4] 添加 deleted_at 字段...")
- try:
- db.execute(text("""
- ALTER TABLE aigcspace.image_translation
- ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP
- """))
- db.commit()
- print("✓ deleted_at 字段添加成功")
- except Exception as e:
- print(f"⚠ deleted_at 字段可能已存在: {e}")
- db.rollback()
-
- # 3. 创建索引
- print("\n[3/4] 创建 is_deleted 索引...")
- try:
- db.execute(text("""
- CREATE INDEX IF NOT EXISTS idx_image_translation_is_deleted
- ON aigcspace.image_translation(is_deleted)
- """))
- db.commit()
- print("✓ 索引创建成功")
- except Exception as e:
- print(f"⚠ 索引可能已存在: {e}")
- db.rollback()
-
- # 4. 添加字段注释
- print("\n[4/4] 添加字段注释...")
- try:
- db.execute(text("""
- COMMENT ON COLUMN aigcspace.image_translation.is_deleted IS '是否已删除'
- """))
- db.execute(text("""
- COMMENT ON COLUMN aigcspace.image_translation.deleted_at IS '删除时间'
- """))
- db.commit()
- print("✓ 字段注释添加成功")
- except Exception as e:
- print(f"⚠ 添加注释失败: {e}")
- db.rollback()
-
- # 验证迁移结果
- print("\n" + "=" * 60)
- print("验证迁移结果...")
- print("=" * 60)
-
- result = db.execute(text("""
- SELECT
- column_name,
- data_type,
- is_nullable,
- column_default
- FROM information_schema.columns
- WHERE table_schema = 'aigcspace'
- AND table_name = 'image_translation'
- AND column_name IN ('is_deleted', 'deleted_at')
- ORDER BY column_name
- """))
-
- columns = result.fetchall()
- if columns:
- print("\n新增字段信息:")
- for col in columns:
- print(f" - {col[0]}: {col[1]} (nullable: {col[2]}, default: {col[3]})")
- else:
- print("⚠ 警告:未找到新增字段,请检查迁移是否成功")
-
- # 检查索引
- result = db.execute(text("""
- SELECT indexname
- FROM pg_indexes
- WHERE schemaname = 'aigcspace'
- AND tablename = 'image_translation'
- AND indexname = 'idx_image_translation_is_deleted'
- """))
-
- index = result.fetchone()
- if index:
- print(f"\n索引信息:")
- print(f" - {index[0]}")
- else:
- print("\n⚠ 警告:未找到索引,请检查创建是否成功")
-
- # 统计现有记录
- result = db.execute(text("""
- SELECT COUNT(*) as total
- FROM aigcspace.image_translation
- """))
- total = result.fetchone()[0]
-
- print(f"\n当前表中记录总数: {total}")
- print(f"所有现有记录的 is_deleted 默认值为: FALSE")
-
- print("\n" + "=" * 60)
- print("✓ 迁移执行成功!")
- print("=" * 60)
-
- return True
-
- except Exception as e:
- print(f"\n✗ 迁移执行失败: {e}")
- import traceback
- traceback.print_exc()
- db.rollback()
- return False
-
- finally:
- db.close()
- def rollback_migration():
- """回滚迁移(仅用于测试环境)"""
- print("\n" + "=" * 60)
- print("警告:准备回滚迁移")
- print("=" * 60)
-
- confirm = input("\n确定要回滚迁移吗?这将删除 is_deleted 和 deleted_at 字段!(yes/no): ")
- if confirm.lower() != 'yes':
- print("已取消回滚")
- return
-
- db = SessionLocal()
-
- try:
- # 删除索引
- print("\n[1/3] 删除索引...")
- db.execute(text("""
- DROP INDEX IF EXISTS aigcspace.idx_image_translation_is_deleted
- """))
- db.commit()
- print("✓ 索引删除成功")
-
- # 删除字段
- print("\n[2/3] 删除 is_deleted 字段...")
- db.execute(text("""
- ALTER TABLE aigcspace.image_translation
- DROP COLUMN IF EXISTS is_deleted
- """))
- db.commit()
- print("✓ is_deleted 字段删除成功")
-
- print("\n[3/3] 删除 deleted_at 字段...")
- db.execute(text("""
- ALTER TABLE aigcspace.image_translation
- DROP COLUMN IF EXISTS deleted_at
- """))
- db.commit()
- print("✓ deleted_at 字段删除成功")
-
- print("\n✓ 回滚完成")
-
- except Exception as e:
- print(f"\n✗ 回滚失败: {e}")
- import traceback
- traceback.print_exc()
- db.rollback()
-
- finally:
- db.close()
- if __name__ == "__main__":
- import argparse
-
- parser = argparse.ArgumentParser(description='图像翻译表软删除字段迁移脚本')
- parser.add_argument(
- '--rollback',
- action='store_true',
- help='回滚迁移(仅用于测试环境)'
- )
-
- args = parser.parse_args()
-
- if args.rollback:
- rollback_migration()
- else:
- success = run_migration()
- sys.exit(0 if success else 1)
|