199 lines
7.7 KiB
JavaScript
199 lines
7.7 KiB
JavaScript
/**
|
||
* 商品扩展配置数据迁移脚本 - 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();
|