/** * 领主赏记录表迁移脚本 * 从 MySQL goods_king_rank 表迁移到 SQL Server goods_king_ranks 表 */ 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 } }; // 批量大小 const BATCH_SIZE = 1000; async function createTable(pool) { console.log('创建 goods_king_ranks 表...'); const createTableSql = ` IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='goods_king_ranks' AND xtype='U') BEGIN CREATE TABLE goods_king_ranks ( id INT IDENTITY(1,1) PRIMARY KEY, user_id INT NOT NULL, goods_id INT NOT NULL, count INT NOT NULL DEFAULT 0, z_nums INT NOT NULL DEFAULT 0, money DECIMAL(10,2) NOT NULL DEFAULT 0, order_list_id INT NOT NULL DEFAULT 0, addtime INT NOT NULL DEFAULT 0, end_time INT NOT NULL DEFAULT 0, CONSTRAINT pk_goods_king_ranks PRIMARY KEY CLUSTERED (id) ); CREATE INDEX ix_goods_king_ranks_user_id ON goods_king_ranks(user_id); CREATE INDEX ix_goods_king_ranks_goods_id ON goods_king_ranks(goods_id); CREATE INDEX ix_goods_king_ranks_user_goods ON goods_king_ranks(user_id, goods_id); EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'领主赏记录表,记录领主占领和挑战信息', @level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'goods_king_ranks'; END `; await pool.request().query(createTableSql); console.log('表创建完成'); } async function getSourceCount(mysqlConn) { const [rows] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_king_rank'); return rows[0].count; } async function getTargetCount(pool) { const result = await pool.request().query('SELECT COUNT(*) as count FROM goods_king_ranks'); return result.recordset[0].count; } async function migrateData(mysqlConn, sqlPool) { const sourceCount = await getSourceCount(mysqlConn); console.log(`源表记录数: ${sourceCount}`); if (sourceCount === 0) { console.log('源表无数据,跳过迁移'); return; } // 清空目标表 console.log('清空目标表...'); await sqlPool.request().query('TRUNCATE TABLE goods_king_ranks'); // 开启 IDENTITY_INSERT await sqlPool.request().query('SET IDENTITY_INSERT goods_king_ranks ON'); let offset = 0; let migratedCount = 0; while (offset < sourceCount) { console.log(`迁移进度: ${offset}/${sourceCount}`); // 从 MySQL 读取数据 const [rows] = await mysqlConn.execute( `SELECT id, user_id, goods_id, count, z_nums, money, order_list_id, addtime, end_time FROM goods_king_rank ORDER BY id LIMIT ? OFFSET ?`, [BATCH_SIZE, offset] ); if (rows.length === 0) break; // 批量插入到 SQL Server const table = new sql.Table('goods_king_ranks'); table.create = false; table.columns.add('id', sql.Int, { nullable: false }); table.columns.add('user_id', sql.Int, { nullable: false }); table.columns.add('goods_id', sql.Int, { nullable: false }); table.columns.add('count', sql.Int, { nullable: false }); table.columns.add('z_nums', sql.Int, { nullable: false }); table.columns.add('money', sql.Decimal(10, 2), { nullable: false }); table.columns.add('order_list_id', sql.Int, { nullable: false }); table.columns.add('addtime', sql.Int, { nullable: false }); table.columns.add('end_time', sql.Int, { nullable: false }); for (const row of rows) { table.rows.add( row.id, row.user_id || 0, row.goods_id || 0, row.count || 0, row.z_nums || 0, row.money || 0, row.order_list_id || 0, row.addtime || 0, row.end_time || 0 ); } const request = sqlPool.request(); await request.bulk(table); migratedCount += rows.length; offset += BATCH_SIZE; } // 关闭 IDENTITY_INSERT await sqlPool.request().query('SET IDENTITY_INSERT goods_king_ranks OFF'); // 重置自增序列 const maxIdResult = await sqlPool.request().query('SELECT MAX(id) as maxId FROM goods_king_ranks'); const maxId = maxIdResult.recordset[0].maxId || 0; await sqlPool.request().query(`DBCC CHECKIDENT ('goods_king_ranks', RESEED, ${maxId})`); console.log(`迁移完成,共迁移 ${migratedCount} 条记录`); } async function validate(mysqlConn, sqlPool) { console.log('\n验证迁移结果...'); const sourceCount = await getSourceCount(mysqlConn); const targetCount = await getTargetCount(sqlPool); console.log(`源表记录数: ${sourceCount}`); console.log(`目标表记录数: ${targetCount}`); if (sourceCount === targetCount) { console.log('✓ 记录数一致'); } else { console.log('✗ 记录数不一致!'); } } async function main() { let mysqlConn = null; let sqlPool = null; try { console.log('连接 MySQL...'); mysqlConn = await mysql.createConnection(mysqlConfig); console.log('MySQL 连接成功'); console.log('连接 SQL Server...'); sqlPool = await sql.connect(sqlServerConfig); console.log('SQL Server 连接成功'); await createTable(sqlPool); await migrateData(mysqlConn, sqlPool); await validate(mysqlConn, sqlPool); console.log('\n迁移任务完成!'); } catch (error) { console.error('迁移失败:', error); process.exit(1); } finally { if (mysqlConn) await mysqlConn.end(); if (sqlPool) await sqlPool.close(); } } main();