Files
nxxmdata/backend/check-primary-keys.js
2025-08-25 15:00:46 +08:00

128 lines
4.0 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.

/**
* 检查数据库中所有表的主键ID分布情况
* @file check-primary-keys.js
* @description 分析各表的主键ID范围为重新排序做准备
*/
const { sequelize } = require('./config/database-simple');
const { QueryTypes } = require('sequelize');
async function checkPrimaryKeys() {
try {
console.log('=== 检查数据库表主键ID分布情况 ===\n');
// 获取所有表名
const tables = await sequelize.query(
"SELECT TABLE_NAME as table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'",
{ type: QueryTypes.SELECT }
);
console.log(`发现 ${tables.length} 个表:\n`);
const tableStats = [];
for (const table of tables) {
const tableName = table.table_name;
try {
// 检查表是否有id字段
const columns = await sequelize.query(
`SELECT COLUMN_NAME as column_name, DATA_TYPE as data_type, IS_NULLABLE as is_nullable, COLUMN_KEY as column_key
FROM information_schema.columns
WHERE table_schema = DATABASE() AND TABLE_NAME = '${tableName}' AND COLUMN_NAME = 'id'`,
{ type: QueryTypes.SELECT }
);
if (columns.length === 0) {
console.log(`${tableName}: 没有id字段`);
continue;
}
// 获取ID统计信息
const stats = await sequelize.query(
`SELECT
COUNT(*) as total_count,
MIN(id) as min_id,
MAX(id) as max_id,
COUNT(DISTINCT id) as unique_count
FROM ${tableName}`,
{ type: QueryTypes.SELECT }
);
const stat = stats[0];
// 检查ID连续性
const gapCheck = await sequelize.query(
`SELECT COUNT(*) as gap_count
FROM (
SELECT id + 1 as next_id
FROM ${tableName}
WHERE id + 1 NOT IN (SELECT id FROM ${tableName})
AND id < (SELECT MAX(id) FROM ${tableName})
) as gaps`,
{ type: QueryTypes.SELECT }
);
const hasGaps = gapCheck[0].gap_count > 0;
const tableInfo = {
tableName,
totalCount: parseInt(stat.total_count),
minId: stat.min_id,
maxId: stat.max_id,
uniqueCount: parseInt(stat.unique_count),
hasGaps,
needsReorder: stat.min_id !== 1 || hasGaps
};
tableStats.push(tableInfo);
console.log(`${tableName}:`);
console.log(` - 记录数: ${tableInfo.totalCount}`);
console.log(` - ID范围: ${tableInfo.minId} - ${tableInfo.maxId}`);
console.log(` - 唯一ID数: ${tableInfo.uniqueCount}`);
console.log(` - 有间隙: ${hasGaps ? '是' : '否'}`);
console.log(` - 需要重排: ${tableInfo.needsReorder ? '是' : '否'}`);
console.log('');
} catch (error) {
console.log(`${tableName}: 检查失败 - ${error.message}`);
}
}
// 汇总统计
console.log('\n=== 汇总统计 ===');
const needReorderTables = tableStats.filter(t => t.needsReorder);
console.log(`需要重新排序的表: ${needReorderTables.length}/${tableStats.length}`);
if (needReorderTables.length > 0) {
console.log('\n需要重新排序的表:');
needReorderTables.forEach(table => {
console.log(`- ${table.tableName} (${table.minId}-${table.maxId}, ${table.totalCount}条记录)`);
});
}
return tableStats;
} catch (error) {
console.error('检查主键失败:', error);
throw error;
} finally {
await sequelize.close();
}
}
// 如果直接运行此脚本
if (require.main === module) {
checkPrimaryKeys()
.then(() => {
console.log('\n检查完成!');
process.exit(0);
})
.catch(error => {
console.error('检查失败:', error);
process.exit(1);
});
}
module.exports = { checkPrimaryKeys };