HaniBlindBox/server/scripts/migrate_goods_king_rank.js
2026-01-25 15:44:07 +08:00

198 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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.

/**
* 领主赏记录表迁移脚本
* 从 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();