HaniBlindBox/server/scripts/migrate_goods_extensions.js
2026-01-02 05:18:05 +08:00

199 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 商品扩展配置数据迁移脚本 - Node.js
* Feature: database-migration, Property 2: 数据记录数一致性
* Validates: Requirements 2.6
*
* 源表: MySQL goods_extend (34 条记录)
* 目标表: SQL Server goods_extensions
*
* 字段映射 (直接映射,无需转换):
* - id -> id
* - goods_id -> goods_id
* - pay_wechat -> pay_wechat
* - pay_balance -> pay_balance
* - pay_currency -> pay_currency
* - pay_currency2 -> pay_currency2
* - pay_coupon -> pay_coupon
* - is_deduction -> is_deduction
*/
const mysql = require('mysql2/promise');
const sql = require('mssql');
// MySQL 配置
const mysqlConfig = {
host: '192.168.195.16',
port: 1887,
user: 'root',
password: 'Dbt@com@123',
database: 'youdas',
charset: 'utf8mb4'
};
// SQL Server 配置
const sqlServerConfig = {
server: '192.168.195.15',
port: 1433,
user: 'sa',
password: 'Dbt@com@123',
database: 'honey_box',
options: {
encrypt: false,
trustServerCertificate: true
}
};
// 获取已迁移的商品扩展ID列表
async function getMigratedIds(pool) {
const result = await pool.request().query('SELECT id FROM goods_extensions');
return new Set(result.recordset.map(r => r.id));
}
// 批量插入商品扩展数据
async function insertGoodsExtensionsBatch(pool, extensions) {
if (extensions.length === 0) return 0;
let insertedCount = 0;
for (const ext of extensions) {
try {
const insertSql = `
SET IDENTITY_INSERT goods_extensions ON;
INSERT INTO goods_extensions (
id, goods_id, pay_wechat, pay_balance, pay_currency, pay_currency2, pay_coupon, is_deduction
) VALUES (
${ext.id},
${ext.goods_id || 0},
${ext.pay_wechat || 0},
${ext.pay_balance || 0},
${ext.pay_currency || 0},
${ext.pay_currency2 || 0},
${ext.pay_coupon || 0},
${ext.is_deduction || 0}
);
SET IDENTITY_INSERT goods_extensions OFF;`;
await pool.request().batch(insertSql);
insertedCount++;
} catch (err) {
console.error(`插入商品扩展 ${ext.id} (goods_id: ${ext.goods_id}) 失败:`, err.message);
}
}
return insertedCount;
}
async function main() {
console.log('========================================');
console.log('商品扩展配置数据迁移脚本 - Node.js');
console.log('========================================\n');
let mysqlConn = null;
let sqlPool = null;
try {
// 连接 MySQL
console.log('正在连接 MySQL...');
mysqlConn = await mysql.createConnection(mysqlConfig);
console.log('MySQL 连接成功\n');
// 连接 SQL Server
console.log('正在连接 SQL Server...');
sqlPool = await sql.connect(sqlServerConfig);
console.log('SQL Server 连接成功\n');
// 获取已迁移的ID
console.log('正在获取已迁移的商品扩展ID...');
const migratedIds = await getMigratedIds(sqlPool);
console.log(`已迁移商品扩展数: ${migratedIds.size}\n`);
// 从 MySQL 获取所有商品扩展数据
console.log('正在从 MySQL 读取商品扩展数据...');
const [rows] = await mysqlConn.execute(`
SELECT id, goods_id, pay_wechat, pay_balance, pay_currency, pay_currency2, pay_coupon, is_deduction
FROM goods_extend
ORDER BY id
`);
console.log(`MySQL 商品扩展总数: ${rows.length}\n`);
// 过滤出未迁移的商品扩展
const extensionsToMigrate = rows.filter(ext => !migratedIds.has(ext.id));
console.log(`待迁移商品扩展数: ${extensionsToMigrate.length}\n`);
if (extensionsToMigrate.length === 0) {
console.log('所有商品扩展数据已迁移完成!');
} else {
// 批量迁移每批20条
const batchSize = 20;
let totalInserted = 0;
for (let i = 0; i < extensionsToMigrate.length; i += batchSize) {
const batch = extensionsToMigrate.slice(i, i + batchSize);
const inserted = await insertGoodsExtensionsBatch(sqlPool, batch);
totalInserted += inserted;
console.log(`进度: ${Math.min(i + batchSize, extensionsToMigrate.length)}/${extensionsToMigrate.length} (本批插入: ${inserted})`);
}
console.log(`\n迁移完成!共插入 ${totalInserted} 条记录`);
}
// 验证迁移结果
console.log('\n========================================');
console.log('迁移结果验证');
console.log('========================================');
const [mysqlCount] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_extend');
const sqlResult = await sqlPool.request().query('SELECT COUNT(*) as count FROM goods_extensions');
console.log(`MySQL goods_extend 表记录数: ${mysqlCount[0].count}`);
console.log(`SQL Server goods_extensions 表记录数: ${sqlResult.recordset[0].count}`);
if (mysqlCount[0].count === sqlResult.recordset[0].count) {
console.log('\n✅ 数据迁移完成,记录数一致!');
} else {
console.log(`\n⚠️ 记录数不一致,差异: ${mysqlCount[0].count - sqlResult.recordset[0].count}`);
}
// 验证支付方式配置分布
console.log('\n========================================');
console.log('支付方式配置验证');
console.log('========================================');
const [mysqlPayWechat] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_extend WHERE pay_wechat = 1');
const sqlPayWechatResult = await sqlPool.request().query('SELECT COUNT(*) as count FROM goods_extensions WHERE pay_wechat = 1');
console.log(`MySQL 支持微信支付的商品扩展数: ${mysqlPayWechat[0].count}`);
console.log(`SQL Server 支持微信支付的商品扩展数: ${sqlPayWechatResult.recordset[0].count}`);
const [mysqlPayBalance] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_extend WHERE pay_balance = 1');
const sqlPayBalanceResult = await sqlPool.request().query('SELECT COUNT(*) as count FROM goods_extensions WHERE pay_balance = 1');
console.log(`MySQL 支持余额支付的商品扩展数: ${mysqlPayBalance[0].count}`);
console.log(`SQL Server 支持余额支付的商品扩展数: ${sqlPayBalanceResult.recordset[0].count}`);
const [mysqlPayCoupon] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_extend WHERE pay_coupon = 1');
const sqlPayCouponResult = await sqlPool.request().query('SELECT COUNT(*) as count FROM goods_extensions WHERE pay_coupon = 1');
console.log(`MySQL 支持优惠券支付的商品扩展数: ${mysqlPayCoupon[0].count}`);
console.log(`SQL Server 支持优惠券支付的商品扩展数: ${sqlPayCouponResult.recordset[0].count}`);
if (mysqlPayWechat[0].count === sqlPayWechatResult.recordset[0].count &&
mysqlPayBalance[0].count === sqlPayBalanceResult.recordset[0].count &&
mysqlPayCoupon[0].count === sqlPayCouponResult.recordset[0].count) {
console.log('\n✅ 支付方式配置迁移正确!');
} else {
console.log('\n⚠ 支付方式配置数量不一致!');
}
} catch (err) {
console.error('迁移过程中发生错误:', err);
process.exit(1);
} finally {
// 关闭连接
if (mysqlConn) await mysqlConn.end();
if (sqlPool) await sqlPool.close();
}
}
main();