Files
nxxmdata/backend/check-primary-keys.js

128 lines
4.0 KiB
JavaScript
Raw Normal View History

/**
* 检查数据库中所有表的主键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 };