/** * 单页内容数据迁移脚本 - Node.js * * 源表: MySQL danye * 目标表: SQL Server danye * * 字段映射: * - id -> id * - title -> title * - content -> content * - update_time -> update_time * - status -> status * - is_image_optimizer -> is_image_optimizer */ 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 } }; // 转义SQL字符串 function escapeString(str) { if (str === null || str === undefined) return 'NULL'; return "N'" + String(str).replace(/'/g, "''") + "'"; } // 获取已迁移的ID列表 async function getMigratedIds(pool) { const result = await pool.request().query('SELECT id FROM danye'); return new Set(result.recordset.map(r => r.id)); } // 逐条插入数据(因为 content 字段可能很大) async function insertDanyeOne(pool, danye) { const sqlStatement = ` SET IDENTITY_INSERT danye ON; INSERT INTO danye (id, title, content, update_time, status, is_image_optimizer) VALUES (${danye.id}, ${escapeString(danye.title)}, ${escapeString(danye.content)}, ${danye.update_time}, ${danye.status}, ${danye.is_image_optimizer}); SET IDENTITY_INSERT danye OFF;`; await pool.request().batch(sqlStatement); } 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, title, content, update_time, status, is_image_optimizer FROM danye ORDER BY id `); console.log(`MySQL 单页总数: ${rows.length}\n`); // 显示单页列表 console.log('单页列表:'); for (const row of rows) { const status = migratedIds.has(row.id) ? '已迁移' : '待迁移'; console.log(` ${row.id}. ${row.title} [${status}]`); } console.log(''); // 过滤出未迁移的单页 const danyesToMigrate = rows.filter(danye => !migratedIds.has(danye.id)); console.log(`待迁移单页数: ${danyesToMigrate.length}\n`); if (danyesToMigrate.length === 0) { console.log('所有单页数据已迁移完成!'); } else { // 逐条迁移(因为 content 字段可能很大) console.log('开始迁移单页数据...'); let insertedCount = 0; for (const danye of danyesToMigrate) { try { await insertDanyeOne(sqlPool, danye); insertedCount++; console.log(` ✓ 插入单页 ${danye.id}: ${danye.title}`); } catch (err) { console.error(` ✗ 插入单页 ${danye.id} (${danye.title}) 失败:`, err.message); } } console.log(`\n迁移完成!共插入 ${insertedCount} 条记录`); } // 验证迁移结果 console.log('\n========================================'); console.log('迁移结果验证'); console.log('========================================'); const [mysqlCount] = await mysqlConn.execute('SELECT COUNT(*) as count FROM danye'); const sqlResult = await sqlPool.request().query('SELECT COUNT(*) as count FROM danye'); console.log(`MySQL danye 表记录数: ${mysqlCount[0].count}`); console.log(`SQL Server danye 表记录数: ${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迁移后的单页列表:'); const migratedDanyes = await sqlPool.request().query('SELECT id, title FROM danye ORDER BY id'); for (const danye of migratedDanyes.recordset) { console.log(` ${danye.id}. ${danye.title}`); } } catch (err) { console.error('迁移过程中发生错误:', err); process.exit(1); } finally { // 关闭连接 if (mysqlConn) await mysqlConn.end(); if (sqlPool) await sqlPool.close(); } } main();