fix_duplicate_records.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #!/usr/bin/env python3
  2. """
  3. 修复 duplicate_business_cards 表中 main_card_id 为 null 的损坏记录
  4. 使用方法:
  5. python fix_duplicate_records.py
  6. 描述:
  7. 此脚本用于修复在处理重复记录时出现的数据完整性问题。
  8. 当 main_card_id 字段为 null 时,会违反数据库的非空约束。
  9. 注意:
  10. - 此操作会永久删除损坏的记录
  11. - 建议在执行前备份数据库
  12. - 仅在确认数据损坏时使用
  13. """
  14. import sys
  15. import os
  16. # 添加项目根目录到 Python 路径
  17. project_root = os.path.dirname(os.path.abspath(__file__))
  18. sys.path.insert(0, project_root)
  19. try:
  20. from app import create_app, db
  21. from app.core.data_parse.parse import DuplicateBusinessCard
  22. import logging
  23. from datetime import datetime
  24. # 设置日志
  25. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  26. logger = logging.getLogger(__name__)
  27. def fix_broken_records():
  28. """修复损坏的重复记录"""
  29. try:
  30. logger.info("开始修复损坏的重复记录...")
  31. # 查找所有 main_card_id 为 null 的记录
  32. broken_records = DuplicateBusinessCard.query.filter(
  33. DuplicateBusinessCard.main_card_id.is_(None)
  34. ).all()
  35. if not broken_records:
  36. logger.info("没有发现需要修复的损坏记录")
  37. return True
  38. logger.info(f"发现 {len(broken_records)} 条损坏记录")
  39. # 记录要删除的记录信息
  40. for i, record in enumerate(broken_records, 1):
  41. logger.info(f"损坏记录 {i}:")
  42. logger.info(f" - ID: {record.id}")
  43. logger.info(f" - 重复原因: {record.duplicate_reason}")
  44. logger.info(f" - 处理状态: {record.processing_status}")
  45. logger.info(f" - 创建时间: {record.created_at}")
  46. logger.info(f" - 处理时间: {record.processed_at}")
  47. # 询问用户确认
  48. print(f"\n发现 {len(broken_records)} 条损坏的重复记录")
  49. print("这些记录的 main_card_id 字段为 null,违反了数据库约束")
  50. print("是否要删除这些损坏的记录? (y/N): ", end="")
  51. confirm = input().strip().lower()
  52. if confirm not in ['y', 'yes']:
  53. logger.info("用户取消操作")
  54. return False
  55. # 删除损坏的记录
  56. for record in broken_records:
  57. db.session.delete(record)
  58. # 提交事务
  59. db.session.commit()
  60. logger.info(f"成功删除了 {len(broken_records)} 条损坏的重复记录")
  61. return True
  62. except Exception as e:
  63. logger.error(f"修复操作失败: {str(e)}")
  64. db.session.rollback()
  65. return False
  66. def main():
  67. """主函数"""
  68. print("=== 重复记录修复工具 ===")
  69. print("此工具用于修复 duplicate_business_cards 表中的损坏记录")
  70. print("=" * 50)
  71. # 创建应用上下文
  72. app = create_app()
  73. with app.app_context():
  74. success = fix_broken_records()
  75. if success:
  76. print("\n✅ 修复操作完成")
  77. else:
  78. print("\n❌ 修复操作失败或被取消")
  79. sys.exit(1)
  80. if __name__ == "__main__":
  81. main()
  82. except ImportError as e:
  83. print(f"导入错误: {e}")
  84. print("请确保从项目根目录运行此脚本")
  85. sys.exit(1)
  86. except Exception as e:
  87. print(f"执行错误: {e}")
  88. sys.exit(1)