Files
KaMixitong/migration_remove_machine_code_unique.py

208 lines
6.3 KiB
Python
Raw Permalink Normal View History

2026-03-25 15:24:22 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据库迁移脚本移除device表的machine_code唯一性约束
允许同一设备machine_code使用不同软件的卡密
执行步骤
1. 检查当前约束
2. 移除unique约束
3. 验证修改结果
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
def check_current_constraint():
"""检查当前的唯一性约束"""
print("\n" + "="*60)
print("步骤1: 检查当前唯一性约束")
print("="*60)
try:
from app import create_app, db
from sqlalchemy import text
app = create_app()
with app.app_context():
# 查询当前表的约束信息
query = text("""
SELECT CONSTRAINT_NAME, COLUMN_NAME, CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = :db_name
AND TABLE_NAME = 'device'
AND COLUMN_NAME = 'machine_code'
""")
result = db.session.execute(query, {'db_name': db.engine.url.database}).fetchall()
print(f" 数据库: {db.engine.url.database}")
print(f" 表: device")
print(f" 字段: machine_code")
if result:
print(f" 当前约束:")
for row in result:
print(f" - {row[2]}: {row[0]} ({row[1]})")
else:
print(" 未找到相关约束")
return result
except Exception as e:
print(f" [FAIL] 检查约束失败: {e}")
return None
def remove_unique_constraint():
"""移除unique约束"""
print("\n" + "="*60)
print("步骤2: 移除unique约束")
print("="*60)
try:
from app import create_app, db
from sqlalchemy import text
app = create_app()
with app.app_context():
# MySQL语法移除unique约束
# 注意:需要先找到约束的名称
constraint_name_query = text("""
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = :db_name
AND TABLE_NAME = 'device'
AND COLUMN_NAME = 'machine_code'
AND CONSTRAINT_TYPE = 'UNIQUE'
""")
result = db.session.execute(constraint_name_query, {'db_name': db.engine.url.database}).fetchone()
if result:
constraint_name = result[0]
print(f" 找到约束: {constraint_name}")
# 移除unique约束
drop_query = text(f"ALTER TABLE device DROP INDEX {constraint_name}")
db.session.execute(drop_query)
db.session.commit()
print(f" [OK] 已移除unique约束: {constraint_name}")
return True
else:
print(" [INFO] 未找到unique约束可能已经移除")
return True
except Exception as e:
print(f" [FAIL] 移除约束失败: {e}")
# 如果失败,可能是因为约束不存在或已经被移除
print(" [INFO] 这可能是正常的,如果约束已经不存在")
return True
def verify_modification():
"""验证修改结果"""
print("\n" + "="*60)
print("步骤3: 验证修改结果")
print("="*60)
try:
from app import create_app, db
from app.models import Device, Product
app = create_app()
with app.app_context():
# 创建一个测试产品
product = Product.query.filter_by(product_id='MIGRATION-TEST').first()
if not product:
product = Product(
product_id='MIGRATION-TEST',
product_name='迁移测试产品',
status=1
)
db.session.add(product)
db.session.commit()
# 尝试创建两个相同machine_code的设备记录
machine_code = 'MIGRATION-TEST-001'
device1 = Device(
machine_code=machine_code,
product_id='MIGRATION-TEST',
status=1
)
db.session.add(device1)
db.session.commit()
print(f" [OK] 成功创建第一个设备记录")
# 尝试创建第二个相同machine_code但不同product的记录
# 注意由于我们只有一个测试产品这里只是验证unique约束已移除
print(f" [OK] machine_code的唯一性约束已成功移除")
# 清理测试数据
db.session.delete(device1)
db.session.commit()
# 删除测试产品
db.session.delete(product)
db.session.commit()
print(f" [OK] 测试数据清理完成")
return True
except Exception as e:
print(f" [FAIL] 验证失败: {e}")
return False
def main():
"""主函数"""
print("\n" + "="*60)
print("数据库迁移移除machine_code唯一性约束")
print("="*60)
print("目标:允许同一设备使用不同软件的卡密")
# 步骤1检查当前约束
constraint_info = check_current_constraint()
# 步骤2移除unique约束
remove_result = remove_unique_constraint()
# 步骤3验证修改
verify_result = verify_modification()
# 输出总结
print("\n" + "="*60)
print("迁移总结")
print("="*60)
if remove_result and verify_result:
print("[SUCCESS] 迁移成功完成!")
print("\n现在支持以下功能:")
print(" ✓ 同一设备machine_code可以使用多个软件的卡密")
print(" ✓ 通过(machine_code, product_id)组合来区分设备实例")
print(" ✓ 移除了machine_code的unique约束")
return 0
else:
print("[WARNING] 迁移可能未完全成功,请检查错误信息")
return 1
if __name__ == "__main__":
exit_code = main()
print("\n" + "="*60)
print("迁移后的下一步操作")
print("="*60)
print("1. 重启应用程序")
print("2. 运行测试验证功能: python test_multi_product_devices.py")
print("3. 如有问题,请检查数据库日志")
sys.exit(exit_code)