< ! DOCTYPE html>
< html lang = "zh-CN" >
< head> < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title> SQL审核工具 - 专业数据库审核解决方案< /title> < link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" > < style> * { margin: 0 ; padding: 0 ; box-sizing: border-box; font-family: 'Segoe UI' , Tahoma, Geneva, Verdana, sans-serif; } :root { --primary: --secondary: --success: --warning: --danger: --info: --vault: --light-bg: --dark-text: --light-text: --border-radius: 10px; } body { background: linear-gradient( 135deg, background-size: 400 % 400 %; animation: gradientBG 15s ease infinite; color: var( --dark-text) ; line-height: 1.6 ; min-height: 100vh; padding: 20px; } @keyframes gradientBG { 0 % { background-position: 0 % 50 %; } 50 % { background-position: 100 % 50 %; } 100 % { background-position: 0 % 50 %; } } .container { max-width: 1400px; margin: 0 auto; background-color: rgba( 255 , 255 , 255 , 0.97 ) ; border-radius: 15px; box-shadow: 0 15px 40px rgba( 0 , 0 , 0 , 0.25 ) ; overflow: hidden; } header { background: linear-gradient( to right, color: white; padding: 35px 50px; text-align: center; position: relative; border-bottom: 5px solid var( --secondary) ; } h1 { font-size: 3rem; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; gap: 25px; letter-spacing: 1px; } .logo { font-size: 3 .5rem; color: animation: pulse 2s infinite; } @keyframes pulse { 0 % { transform: scale( 1 ) ; } 50 % { transform: scale( 1.05 ) ; } 100 % { transform: scale( 1 ) ; } } .subtitle { font-size: 1 .3rem; opacity: 0.9 ; max-width: 900px; margin: 0 auto; line-height: 1.7 ; font-weight: 300 ; } .controls { display: flex; flex-wrap: wrap; gap: 25px; padding: 30px; background-color: var( --light-bg) ; border-bottom: 1px solid } .control-group { flex: 1 ; min-width: 320px; } label { display: block; margin-bottom: 12px; font-weight: 600 ; color: var( --dark-text) ; display: flex; align-items: center; gap: 12px; font-size: 1 .1rem; } select, button { width: 100 %; padding: 16px 20px; border: 2px solid border-radius: var( --border-radius) ; font-size: 1 .1rem; background-color: white; transition: all 0 .3s ease; } select:focus { border-color: var( --secondary) ; outline: none; box-shadow: 0 0 0 4px rgba( 52 , 152 , 219 , 0.2 ) ; } button { background: linear-gradient( to right, var( --secondary) , color: white; font-weight: 700 ; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 15px; transition: all 0 .3s ease; margin-top: 36px; font-size: 1 .2rem; border-radius: 50px; box-shadow: 0 5px 15px rgba( 52 , 152 , 219 , 0.3 ) ; } button:hover { transform: translateY( -5px) ; box-shadow: 0 10px 25px rgba( 0 , 0 , 0 , 0.2 ) ; background: linear-gradient( to right, } .main-content { display: flex; flex-wrap: wrap; padding: 0 30px 30px; gap: 30px; } .panel { flex: 1 ; min-width: 320px; background: white; border-radius: var( --border-radius) ; box-shadow: 0 10px 25px rgba( 0 , 0 , 0 , 0.08 ) ; overflow: hidden; border: 1px solid transition: transform 0 .3s ease; } .panel:hover { transform: translateY( -5px) ; box-shadow: 0 15px 30px rgba( 0 , 0 , 0 , 0.12 ) ; } .panel-header { background: linear-gradient( to right, padding: 20px 30px; font-weight: 700 ; color: var( --dark-text) ; display: flex; align-items: center; gap: 15px; border-bottom: 1px solid font-size: 1 .4rem; } .panel-content { padding: 25px; height: 500px; } textarea { width: 100 %; height: 100 %; padding: 25px; border: 1px solid border-radius: var( --border-radius) ; font-family: 'Consolas' , 'Courier New' , monospace; font-size: 1 .1rem; resize: none; background-color: transition: all 0 .3s; line-height: 1.8 ; box-shadow: inset 0 2px 5px rgba( 0,0 ,0,0.05) ; } textarea:focus { border-color: var( --secondary) ; outline: none; box-shadow: 0 0 0 4px rgba( 52 , 152 , 219 , 0.1 ) , inset 0 2px 5px rgba( 0,0 ,0,0.05) ; background-color: white; } .results-container { overflow-y: auto; height: 100 %; padding: 5px; } .result-item { padding: 25px; margin-bottom: 20px; border-radius: var( --border-radius) ; background-color: border-left: 6px solid var( --secondary) ; display: flex; gap: 20px; transition: all 0 .3s ease; animation: fadeIn 0 .5s ease; position: relative; overflow: hidden; } .result-item::before { content: '' ; position: absolute; top: 0 ; left: 0 ; width: 100 %; height: 100 %; background: linear-gradient( to right, rgba( 255,255 ,255,0.1) , transparent) ; pointer-events: none; } @keyframes fadeIn { from { opacity: 0 ; transform: translateY( 15px) ; } to { opacity: 1 ; transform: translateY( 0 ) ; } } .result-item:hover { transform: translateX( 8px) ; } .result-item.error { border-left-color: var( --danger) ; background-color: rgba( 231 , 76 , 60 , 0.08 ) ; } .result-item.warning { border-left-color: var( --warning) ; background-color: rgba( 243 , 156 , 18 , 0.08 ) ; } .result-item.success { border-left-color: var( --success) ; background-color: rgba( 46 , 204 , 113 , 0.08 ) ; } .result-item.info { border-left-color: var( --info) ; background-color: rgba( 155 , 89 , 182 , 0.08 ) ; } .result-item.suggestion { border-left-color: var( --secondary) ; background-color: rgba( 52 , 152 , 219 , 0.08 ) ; } .result-item.vault { border-left-color: var( --vault) ; background-color: rgba( 211 , 84 , 0 , 0.08 ) ; } .result-icon { font-size: 30px; flex-shrink: 0 ; margin-top: 5px; min-width: 40px; text-align: center; } .result-content { flex: 1 ; } .result-content h3 { margin-bottom: 15px; font-size: 1 .4rem; display: flex; align-items: center; gap: 10px; } .result-content p { color: line-height: 1.8 ; font-size: 1 .1rem; margin-bottom: 15px; } .result-content .db-hint { margin-top: 10px; font-style: italic; color: font-size: 0 .95rem; display: flex; align-items: center; gap: 8px; padding: 10px 15px; background: rgba( 0,0 ,0,0.03) ; border-radius: 6px; border-left: 3px solid var( --warning) ; } .result-content .recommendation { background: rgba( 46 , 204 , 113 , 0.1 ) ; padding: 12px 15px; border-radius: 6px; border-left: 3px solid var( --success) ; margin-top: 10px; } .result-content .vault-recommendation { background: rgba( 211 , 84 , 0 , 0.1 ) ; padding: 12px 15px; border-radius: 6px; border-left: 3px solid var( --vault) ; margin-top: 10px; } .db-badges { display: flex; gap: 25px; justify-content: center; margin-top: 25px; flex-wrap: wrap; } .db-badge { background: linear-gradient( to right, color: white; padding: 12px 30px; border-radius: 50px; font-weight: 600 ; display: flex; align-items: center; gap: 15px; font-size: 1 .2rem; box-shadow: 0 5px 15px rgba( 0,0 ,0,0.15) ; transition: transform 0 .3s ease; } .db-badge:hover { transform: translateY( -3px) ; } .db-badge.oracle { background: linear-gradient( to right, } .db-badge.mysql { background: linear-gradient( to right, } .db-badge.postgres { background: linear-gradient( to right, } .stats { display: flex; justify-content: space-around; padding: 30px; background-color: var( --light-bg) ; border-top: 1px solid flex-wrap: wrap; gap: 25px; } .stat-item { text-align: center; min-width: 180px; padding: 20px; background: white; border-radius: var( --border-radius) ; box-shadow: 0 8px 20px rgba( 0,0 ,0,0.08) ; transition: transform 0 .3s ease; } .stat-item:hover { transform: translateY( -5px) ; } .stat-value { font-size: 3rem; font-weight: 800 ; margin-bottom: 10px; } .stat-label { font-size: 1 .1rem; color: var( --light-text) ; text-transform: uppercase; letter-spacing: 1px; font-weight: 700 ; } .success-value { color: var( --success) ; } .warning-value { color: var( --warning) ; } .error-value { color: var( --danger) ; } .suggestion-value { color: var( --secondary) ; } .vault-value { color: var( --vault) ; } footer { text-align: center; padding: 30px; color: var( --light-text) ; font-size: 1 .1rem; background-color: var( --light-bg) ; border-top: 1px solid } .progress-container { height: 8px; background: border-radius: 4px; overflow: hidden; margin-top: 20px; display: none; } .progress-bar { height: 100 %; background: var( --secondary) ; width: 0 %; transition: width 0 .4s ease; } .rule-tag { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0 .85rem; font-weight: 600 ; margin-right: 8px; } .tag-security { background: rgba( 231 , 76 , 60 , 0.15 ) ; color: var( --danger) ; } .tag-performance { background: rgba( 243 , 156 , 18 , 0.15 ) ; color: var( --warning) ; } .tag-design { background: rgba( 52 , 152 , 219 , 0.15 ) ; color: var( --secondary) ; } .tag-maintain { background: rgba( 155 , 89 , 182 , 0.15 ) ; color: var( --info) ; } .tag-best { background: rgba( 46 , 204 , 113 , 0.15 ) ; color: var( --success) ; } .tag-vault { background: rgba( 211 , 84 , 0 , 0.15 ) ; color: var( --vault) ; } @media ( max-width: 992px) { .controls { flex-direction: column ; } .main-content { flex-direction: column ; } h1 { font-size: 2 .4rem; } .panel-content { height: 400px; } } @media ( max-width: 576px) { header { padding: 25px 20px; } h1 { font-size: 2rem; } .subtitle { font-size: 1 .1rem; } .panel-content { height: 350px; } .stat-item { min-width: 140px; padding: 15px; } .stat-value { font-size: 2 .5rem; } } .vault-commands { background: rgba( 211 , 84 , 0 , 0.05 ) ; border: 1px dashed var( --vault) ; border-radius: 10px; padding: 15px; margin-top: 20px; } .vault-commands h4 { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; color: var( --vault) ; } .vault-command-list { display: flex; flex-wrap: wrap; gap: 8px; } .vault-command { background: rgba( 211 , 84 , 0 , 0.1 ) ; color: var( --vault) ; padding: 4px 10px; border-radius: 4px; font-family: monospace; font-size: 0 .9rem; } < /style>
< /head>
< body> < div class = "container" > < header> < h1 >< i class = "fas fa-database logo" > < /i> SQL审核专家系统< /h1 >< p class = "subtitle" > 专业审核Oracle、MySQL和PostgreSQL数据库SQL语句,提供语法验证、性能优化、安全审计与金库命令检测< /p> < div class = "db-badges" > < div class = "db-badge oracle" > < i class = "fas fa-database" > < /i> Oracle< /div> < div class = "db-badge mysql" > < i class = "fas fa-database" > < /i> MySQL< /div> < div class = "db-badge postgres" > < i class = "fas fa-database" > < /i> PostgreSQL< /div> < /div> < /header> < div class = "controls" > < div class = "control-group" > < label for = "db-type" > < i class = "fas fa-server" > < /i> 选择数据库类型< /label> < select id = "db-type" > < option value = "oracle" > Oracle Database< /option> < option value = "mysql" selected> MySQL< /option> < option value = "postgres" > PostgreSQL< /option> < /select> < /div> < div class = "control-group" > < label for = "audit-level" > < i class = "fas fa-shield-alt" > < /i> 审核严格级别< /label> < select id = "audit-level" > < option value = "low" > 低 - 仅关键问题< /option> < option value = "medium" selected> 中 - 推荐级别< /option> < option value = "high" > 高 - 全面检查< /option> < option value = "strict" > 严格 - 生产环境标准< /option> < /select> < /div> < div class = "control-group" > < button id = "analyze-btn" > < i class = "fas fa-search" > < /i> 分析SQL语句< /button> < div class = "progress-container" id = "progress-container" > < div class = "progress-bar" id = "progress-bar" > < /div> < /div> < /div> < /div> < div class = "stats" > < div class = "stat-item" > < div class = "stat-value error-value" id = "error-count" > 0 < /div> < div class = "stat-label" > 严重错误< /div> < /div> < div class = "stat-item" > < div class = "stat-value warning-value" id = "warning-count" > 0 < /div> < div class = "stat-label" > 性能警告< /div> < /div> < div class = "stat-item" > < div class = "stat-value vault-value" id = "vault-count" > 0 < /div> < div class = "stat-label" > 金库命令< /div> < /div> < div class = "stat-item" > < div class = "stat-value success-value" id = "success-count" > 0 < /div> < div class = "stat-label" > 通过检查< /div> < /div> < div class = "stat-item" > < div class = "stat-value suggestion-value" id = "suggestion-count" > 0 < /div> < div class = "stat-label" > 优化建议< /div> < /div> < /div> < div class = "main-content" > < div class = "panel" > < div class = "panel-header" > < i class = "fas fa-code" > < /i> SQL输入< /div> < div class = "panel-content" > < textarea id = "sql-input" placeholder = "在此输入SQL语句..." > SELECT e.employee_id, e.first_name, e.last_name, d.department_name, ( SELECT COUNT( *) FROM projects p WHERE p.manager_id = e.employee_id) AS project_count
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE e.hire_date > '2020-01-01'
ORDER BY e.last_name, e.first_name; UPDATE employees
SET salary = salary * 1.05
WHERE department_id = 10 ; DELETE FROM order_details
WHERE order_id IN ( SELECT order_id FROM orders WHERE order_date < '2019-01-01' ) ; CREATE INDEX idx_employee_name ON employees( last_name, first_name) ; GRANT SELECT ON employees TO public; -- 金库命令示例
DROP TABLE temp_data;
TRUNCATE TABLE audit_log;
ALTER TABLE employees ADD COLUMN salary_history TEXT;
REVOKE ALL ON employees FROM public;
FLUSH PRIVILEGES;
COMMIT; < /textarea> < /div> < /div> < div class = "panel" > < div class = "panel-header" > < i class = "fas fa-clipboard-check" > < /i> 专业审核结果< /div> < div class = "panel-content" > < div class = "results-container" id = "results-container" > < div class = "result-item info" > < div class = "result-icon" > < i class = "fas fa-info-circle" > < /i> < /div> < div class = "result-content" > < h3 > SQL审核专家系统< /h3 >< p> 输入SQL语句并点击"分析SQL语句" 按钮开始专业审核< /p> < p> 系统将检测语法错误、性能问题、安全隐患和金库命令< /p> < div class = "vault-commands" > < h4 >< i class = "fas fa-vault" > < /i> 金库命令监控< /h4 >< div class = "vault-command-list" > < span class = "vault-command" > INSERT< /span> < span class = "vault-command" > DELETE< /span> < span class = "vault-command" > UPDATE< /span> < span class = "vault-command" > ALTER< /span> < span class = "vault-command" > TRUNCATE< /span> < span class = "vault-command" > DROP< /span> < span class = "vault-command" > GRANT< /span> < span class = "vault-command" > REVOKE< /span> < span class = "vault-command" > FLUSH< /span> < span class = "vault-command" > COMMIT< /span> < span class = "vault-command" > ROLLBACK< /span> < /div> < p style = "margin-top: 10px; font-size: 0.9rem;" > 这些命令需要额外授权,系统将进行特殊标记< /p> < /div> < /div> < /div> < /div> < /div> < /div> < /div> < footer> < p> SQL审核专家系统 v3.2 & copy; 2025 | 新增智能SQL分析引擎 | 专业数据库管理解决方案< /p> < /footer> < /div> < script> document.addEventListener( 'DOMContentLoaded' , function ( ) { const analyzeBtn = document.getElementById( 'analyze-btn' ) ; const sqlInput = document.getElementById( 'sql-input' ) ; const resultsContainer = document.getElementById( 'results-container' ) ; const progressContainer = document.getElementById( 'progress-container' ) ; const progressBar = document.getElementById( 'progress-bar' ) ; const successCount = document.getElementById( 'success-count' ) ; const warningCount = document.getElementById( 'warning-count' ) ; const errorCount = document.getElementById( 'error-count' ) ; const suggestionCount = document.getElementById( 'suggestion-count' ) ; const vaultCount = document.getElementById( 'vault-count' ) ; // 定义金库命令(敏感命令)const vaultCommands = [ 'insert' , 'delete' , 'update' , 'alter' , 'truncate' , 'drop' ,'mysqladmin' , 'mysqldump' , 'mysqld' , 'grant' , 'create' , 'set' ,'rename' , 'source' , 'revoke' , 'flush' , 'load' , 'import' ,'shutdown' , 'startup' , 'flushall' , 'flushdb' , 'bgrewriteaof' ,'push' , 'pull' , 'pop' , 'inc' , 'remove' , 'call' , 'replace' ,'commit' , 'rollback' , 'lock' , 'unlock' ] ; analyzeBtn.addEventListener( 'click' , function ( ) { const sql = sqlInput.value.trim( ) ; const dbType = document.getElementById( 'db-type' ) .value; const auditLevel = document.getElementById( 'audit-level' ) .value; if ( ! sql) { alert( '请输入SQL语句!' ) ; return ; } // 显示进度条progressContainer.style.display = 'block' ; progressBar.style.width = '0%' ; // 更新按钮状态analyzeBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 分析中...' ; analyzeBtn.disabled = true ; // 清空结果容器resultsContainer.innerHTML = '' ; // 模拟进度let progress = 0 ; const progressInterval = setInterval(( ) = > {progress + = 5 ; progressBar.style.width = `${progress}% `; if ( progress >= 100 ) {clearInterval( progressInterval) ; }}, 100 ) ; / / 开始计时const startTime = new Date( ) .getTime( ) ; / / 模拟分析过程setTimeout(( ) = > {/ / 清空进度条clearInterval( progressInterval) ; progressBar.style.width = '100 % '; / / 统计结果let success = 0 , warning = 0 , error = 0 , suggestion = 0 , vault = 0 ; / / SQL语句解析(简化处理)const sqlLower = sql.toLowerCase( ) ; const statements = sql.split( '; ') .filter( s = > s.trim( ) != = '') ; / / 检测金库命令for ( const cmd of vaultCommands) {if ( sqlLower.includes( cmd)) { vault++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item vault' ; let content = '' ; let recommendation = '' ; // 根据具体命令生成内容switch( cmd) { case 'drop' : content = '检测到DROP命令:此操作将永久删除数据库对象' ; recommendation = 'DROP操作不可逆,执行前需进行备份并确保有回滚计划' ; break ; case 'truncate' : content = '检测到TRUNCATE命令:此操作将立即清空表数据' ; recommendation = 'TRUNCATE操作不可回滚,建议改用DELETE并添加WHERE条件' ; break ; case 'grant' : content = '检测到GRANT命令:此操作将修改数据库权限' ; recommendation = '权限变更需经过安全团队审批,确保符合最小权限原则' ; break ; case 'revoke' : content = '检测到REVOKE命令:此操作将收回数据库权限' ; recommendation = '权限变更需经过安全团队审批,确保不影响关键业务流程' ; break ; case 'alter' : content = '检测到ALTER命令:此操作将修改数据库结构' ; recommendation = '表结构变更需在维护窗口执行,确保不影响在线业务' ; break ; case 'commit' : content = '检测到COMMIT命令:此操作将提交事务' ; recommendation = '确保事务操作已正确测试,避免提交错误数据' ; break ; case 'delete' : content = '检测到DELETE命令:此操作将删除数据' ; recommendation = 'DELETE操作需添加WHERE条件,避免全表删除' ; break ; default:content = ` 检测到${ cmd.toUpperCase( ) } 命令:此操作需要额外授权` ; recommendation = '此类命令需要DBA审批和双重确认,确保操作已获得授权并记录审计日志' ; } resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-shield-alt" > < /i> < /div> < div class = "result-content" > < h3 > 金库命令检测 < span class = "rule-tag tag-vault" > 金库命令< /span> < /h3 >< p> ${ content} < /p> < div class = "vault-recommendation" > < strong> 安全建议:< /strong> ${ recommendation} < /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 关键< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } } // 检测常见SQL问题if ( sqlLower.includes( "select *" )) { warning++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item warning' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-asterisk" > < /i> < /div> < div class = "result-content" > < h3 > SELECT * 警告 < span class = "rule-tag tag-performance" > 性能< /span> < /h3 >< p> 避免使用SELECT *,明确指定所需列< /p> < div class = "recommendation" > < strong> 推荐方案:< /strong> 明确指定所需列,例如: SELECT id, name, title FROM employees< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 重要< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } if ( sqlLower.includes( "delete" ) && ! sqlLower.includes( "where" )) { error++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item error' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-ban" > < /i> < /div> < div class = "result-content" > < h3 > DELETE无WHERE条件 < span class = "rule-tag tag-security" > 安全< /span> < /h3 >< p> DELETE语句缺少WHERE条件,将删除全表数据< /p> < div class = "recommendation" > < strong> 安全建议:< /strong> 添加WHERE条件限制删除范围< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 关键< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } if ( sqlLower.includes( "join" ) && ! sqlLower.includes( "on" )) { error++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item error' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-link" > < /i> < /div> < div class = "result-content" > < h3 > JOIN条件缺失 < span class = "rule-tag tag-design" > 设计< /span> < /h3 >< p> JOIN语句缺少ON条件,可能导致笛卡尔积< /p> < div class = "recommendation" > < strong> 推荐方案:< /strong> 为JOIN添加ON条件,指定关联字段< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 关键< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } if ( sqlLower.includes( "grant" ) && sqlLower.includes( "public" )) { warning++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item warning' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-lock" > < /i> < /div> < div class = "result-content" > < h3 > 权限过大 < span class = "rule-tag tag-security" > 安全< /span> < /h3 >< p> GRANT语句将敏感数据表授权给PUBLIC角色< /p> < div class = "recommendation" > < strong> 安全建议:< /strong> 使用最小权限原则,仅授权给必要用户< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 重要< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 检测子查询性能问题if ( sqlLower.match( /select\ s+.*?\ s+from.*?\ s+where\ s+.*?\ ( \ s*select\ s+.*?\ s+from/)) { suggestion++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item suggestion' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-tachometer-alt" > < /i> < /div> < div class = "result-content" > < h3 > 子查询性能问题 < span class = "rule-tag tag-performance" > 性能< /span> < /h3 >< p> 相关子查询可能导致性能问题,特别是在大表上< /p> < div class = "recommendation" > < strong> 推荐方案:< /strong> 考虑使用JOIN重写或使用临时表优化< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 推荐< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 检测索引创建if ( sqlLower.includes( "create index" )) { success++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item success' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-check-circle" > < /i> < /div> < div class = "result-content" > < h3 > 索引创建合理 < span class = "rule-tag tag-best" > 最佳实践< /span> < /h3 >< p> 索引设计合理,有助于提高查询性能< /p> < div class = "recommendation" > < strong> 建议:< /strong> 监控索引使用情况,避免创建过多索引< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 推荐< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 检测隐式类型转换if ( sqlLower.match( /where\ s+\ w+\ s*= \ s*[ '"]\d+[' "] /)) { warning++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item warning' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-columns" > < /i> < /div> < div class = "result-content" > < h3 > 隐式类型转换 < span class = "rule-tag tag-performance" > 性能< /span> < /h3 >< p> WHERE条件中存在隐式类型转换,可能导致索引失效< /p> < div class = "recommendation" > < strong> 推荐方案:< /strong> 确保WHERE条件中的列和值数据类型一致< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 重要< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 检测大表操作if ( sqlLower.includes( "delete" ) || sqlLower.includes( "update" )) { const tableMatch = sqlLower.match( /( ?:from| update) \ s+( \ w+) /) ; if ( tableMatch) { const tableName = tableMatch[ 1 ] ; warning++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item warning' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-server" > < /i> < /div> < div class = "result-content" > < h3 > 大表操作风险 < span class = "rule-tag tag-performance" > 性能< /span> < /h3 >< p> 在表 ${ tableName} 上执行数据修改操作,可能影响性能< /p> < div class = "recommendation" > < strong> 推荐方案:< /strong> 分批操作,每批处理1000条记录< /div> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 重要< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } } // 检测日期格式if ( sqlLower.match( /\ d{ 4 } -\ d{ 2 } -\ d{ 2 } /)) { suggestion++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item suggestion' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-calendar" > < /i> < /div> < div class = "result-content" > < h3 > 日期格式建议 < span class = "rule-tag tag-design" > 设计< /span> < /h3 >< p> 日期字面值使用ISO格式(YYYY-MM-DD),确保跨数据库兼容性< /p> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } | 规则级别: 推荐< /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 如果没有检测到任何问题if ( resultsContainer.children.length == = 0 ) { success++; const resultElement = document.createElement( 'div' ) ; resultElement.className = 'result-item success' ; resultElement.innerHTML = ` < div class = "result-icon" > < i class = "fas fa-check-circle" > < /i> < /div> < div class = "result-content" > < h3 > 审核完成< /h3 >< p> 未发现任何问题,SQL语句符合最佳实践< /p> < p class = "db-hint" > < i class = "fas fa-database" > < /i> 数据库: ${ dbType.toUpperCase( ) } < /p> < /div> ` ; resultsContainer.appendChild( resultElement) ; } // 更新统计信息errorCount.textContent = error; warningCount.textContent = warning; successCount.textContent = success; suggestionCount.textContent = suggestion; vaultCount.textContent = vault; // 计算分析时间const endTime = new Date( ) .getTime( ) ; const timeTaken = ( endTime - startTime) / 1000 ; // 恢复按钮状态setTimeout(( ) = > { analyzeBtn.innerHTML = '<i class="fas fa-search"></i> 分析SQL语句' ; analyzeBtn.disabled = false ; progressContainer.style.display = 'none' ; } , 500 ) ; } , 1800 ) ; } ) ; } ) ; < /script>
< /body>
< /html>