LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

使用 HTML + JavaScript 实现 SQL 智能补全功能(附源码地址)

admin
2026年1月24日 10:5 本文热度 80
现代数据库管理工具中,SQL 智能补全功能已成为提升开发效率的重要特性。它能够根据上下文环境自动提示关键词、表名、字段名等信息,大大减少了手动输入错误和查询文档的时间。这种智能化的代码辅助功能不仅提高了编写 SQL 的准确性,还能帮助开发者快速回忆表结构和语法规范。本文将介绍如何使用 HTML、CSS 和 JavaScript 实现 SQL 智能补全功能。

效果演示

这个 SQL 智能补全功能提供了一个直观的编辑环境,当用户在文本框中输入 SQL 语句时,系统会根据上下文智能推荐关键词、表名和字段名。例如,当用户在 SELECT 关键词后输入时,系统会推荐可用的字段名;在 FROM 后面则会推荐数据库中的表名。补全建议会以下拉菜单的形式显示,用户可以通过键盘方向键导航,按 Enter 或 Tab 键确认选择,也可以点击鼠标直接选择。

页面结构

页面主要包括以下几个区域:

SQL 编辑器区域

这是主要的输入区域,用户在这里编写 SQL 语句。
<div class="sql-editor-wrapper">    <textarea id="sqlEditor" placeholder="输入SQL语句,体验智能补全功能..."></textarea>    <div class="autocomplete-dropdown" id="autocompleteDropdown"></div></div>

信息面板区域

底部的信息面板提供了使用说明和快捷键提示。
<div class="info-panel">    支持:关键词、表名、字段名智能补全 | 快捷键:↑↓选择,Enter/Tab确认,Esc取消 | 表:user, order</div>

核心功能实现

SQL 词汇表构建

智能补全功能的基础是完整的词汇表,包括 SQL 关键词和预定义的表结构。代码首先定义了常用 SQL 关键词数组 SQL_KEYWORDS,包含 SELECT、FROM、WHERE 等标准 SQL 语句关键词。同时,通过 TABLES 对象定义了两个示例表(user 和 order)及其字段,这些数据构成了智能补全的数据基础。为了提高查询效率,代码创建了缓存数据结构:TABLE_NAMES 存储所有表名,ALL_COLUMNS 是所有字段的集合,而 COLUMNS_BY_TABLE 则建立了表到其字段的映射关系。
// SQL关键词const SQL_KEYWORDS = [  'SELECT''FROM''WHERE''INSERT''UPDATE''DELETE''SET',  'JOIN''LEFT JOIN''RIGHT JOIN''INNER JOIN''OUTER JOIN',  // ... 其他关键词];
// 表结构定义const TABLES = {  user: { columns: ['id''username''email''password''created_at''updated_at''status''nickname''avatar'] },  order: { columns: ['id''user_id''order_no''amount''status''created_at''pay_time''remark''payment_method'] }};
// 缓存数据const TABLE_NAMES = Object.keys(TABLES);const ALL_COLUMNS = new Set();const COLUMNS_BY_TABLE = {};TABLE_NAMES.forEach(table => {  COLUMNS_BY_TABLE[table] = new Set(TABLES[table].columns);  TABLES[table].columns.forEach(col => ALL_COLUMNS.add(col));});

令牌提取与上下文分析

智能补全的关键在于准确识别用户当前正在输入的内容。
getTokenContext 函数负责从编辑器中提取光标前的文本,并使用正则表达式匹配当前正在输入的令牌(token)。这个函数返回令牌本身、令牌起始位置和光标位置等信息,为后续的上下文分析提供基础。
getContext 函数进一步分析当前的 SQL 上下文,确定用户可能需要的补全类型。它通过检查光标前的文本模式来判断当前处于什么 SQL 语句部分:如果前面是 FROM、JOIN 或 INTO,则认为是表名上下文;如果是 ON,则可能是列名且涉及表别名;如果是 WHERE、ORDER BY 等,则是列名上下文;如果检测到表别名(如 "t." 形式),则提供该表的字段建议。
function getTokenContext() {  const cursorPos = editor.selectionStart;  const text = editor.value;  const beforeCursor = text.substring(0, cursorPos);  const tokenMatch = beforeCursor.match(/[\w.]*$/);  const token = tokenMatch ? tokenMatch[0] : '';  const tokenStart = cursorPos - token.length;  return { token, tokenStart, cursorPos, text };}
function getContext(text, cursorPos, tokenStart) {  const beforeToken = text.substring(0, tokenStart).toUpperCase().trim();
  if (/FROM\s*$/.test(beforeToken) || /JOIN\s*$/.test(beforeToken) || /INTO\s*$/.test(beforeToken)) {    return { type'table', prefix: '' };  }
  if (/ON\s*$/.test(beforeToken)) {    return { type'column', prefix: '', tableContext: true };  }
  if (/(WHERE|ORDER BY|GROUP BY|HAVING|SELECT|SET)\s*$/.test(beforeToken)) {    return { type'column', prefix: '' };  }
  const aliasMatch = text.substring(Math.max(0, tokenStart - 50), tokenStart).match(/(\w+)\.$/);  if (aliasMatch) {    const alias = aliasMatch[1].toLowerCase();    if (COLUMNS_BY_TABLE[alias]) {      return { type'column', prefix: '', table: alias };    }  }
  return { type'mixed', prefix: '' };}

智能建议算法

getSuggestions 函数实现了建议算法,它根据上下文类型返回相应的补全选项。算法首先定义了 calculateScore 函数来计算匹配度分数,该函数考虑了多种因素:完全匹配得分最高,前缀匹配次之,包含匹配再次,最后根据字符串长度进行微调。基于上下文类型,算法分别处理表名、字段名和混合类型的建议。对于表名上下文,只返回匹配的表名;对于字段名上下文,如果没有指定表则返回所有字段,如果有指定表则只返回该表的字段;对于混合上下文,则同时考虑关键词、表名和字段名。所有建议按分数排序并限制数量。
function getSuggestions(token, context) {  const suggestions = [];  const tokenLower = token.toLowerCase();  const cleanToken = token.replace(/[`"]/g'');  const cleanTokenLower = cleanToken.toLowerCase();
  function calculateScore(text, search, typePriority) {    let score = typePriority * 100;    const textLower = text.toLowerCase();    const searchLower = search.toLowerCase();
    if (textLower === searchLower) {      score += 1000;    } else if (textLower.startsWith(searchLower)) {      score += 500;    } else if (textLower.includes(searchLower)) {      score += 200;    }
    score -= text.length * 0.1;    return score;  }
  if (context.type === 'table') {    TABLE_NAMES.forEach(table => {      if (table.toLowerCase().includes(cleanTokenLower)) {        const score = calculateScore(table, cleanToken, 10);        suggestions.push({ text: table, type'table', score });      }    });  } else if (context.type === 'column') {    // ... 字段上下文,搜索字段名  } else {    // ... 混合上下文,搜索关键词、表名和字段名  }
  return suggestions.sort((a, b) => b.score - a.score).slice(012);}

下拉框定位与渲染

为了提供良好的用户体验,下拉框需要精确地出现在光标附近。

calculateDropdownPosition 函数计算下拉框的绝对位置,它首先通过 textMeasurer 元素测量当前行的文本宽度,然后计算光标所在的行列位置,从而确定下拉框的左上角坐标。

renderDropdown 函数负责创建和显示下拉框。它首先清空现有内容,然后为每个建议创建 autocomplete-item 元素,包含建议文本和类型标识。每个项目都绑定点击事件和鼠标悬停事件,使用户可以通过鼠标或键盘选择建议。

function calculateDropdownPosition(tokenStart{  const text = editor.value;  const beforeToken = text.substring(0, tokenStart);  const lines = beforeToken.split('\n');  const currentLineText = lines[lines.length - 1];
  const editorRect = editor.getBoundingClientRect();  const editorStyle = window.getComputedStyle(editor);
  const paddingLeft = parseFloat(editorStyle.paddingLeft);  const paddingTop = parseFloat(editorStyle.paddingTop);  const paddingRight = parseFloat(editorStyle.paddingRight);  const lineHeight = parseFloat(editorStyle.lineHeight) || 21;
  textMeasurer.textContent = currentLineText;  const textWidth = textMeasurer.offsetWidth;
  const left = paddingLeft + textWidth;  const top = paddingTop + (lines.length - 1) * lineHeight;
  const dropdownHeight = Math.min(200, dropdown.scrollHeight || 150);  const dropdownWidth = 220;
  const spaceBelow = editorRect.height - top;  const displayAbove = spaceBelow < dropdownHeight + 10;
  const adjustedLeft = Math.min(left, editorRect.width - dropdownWidth - paddingRight - 5);
  return {    left: adjustedLeft,    top: displayAbove ? top - dropdownHeight - 5 : top + lineHeight,    displayAbove  };}
function renderDropdown(suggestions, tokenStart) {  if (suggestions.length === 0) {    hideDropdown();    return;  }
  currentSuggestions = suggestions;  selectedIndex = -1;
  dropdown.innerHTML = '';  suggestions.forEach((suggestion, index) => {    const item = document.createElement('div');    item.className = 'autocomplete-item';    item.setAttribute('data-index', index);
    const text = suggestion.displayText || suggestion.text;    item.innerHTML = `${text}</span><span class="autocomplete-type">${suggestion.type}</span>`;
    item.addEventListener('click'() => selectSuggestion(index));    item.addEventListener('mouseenter'() => setSelectedIndex(index));
    dropdown.appendChild(item);  });
  const position = calculateDropdownPosition(tokenStart);  dropdown.style.left = position.left + 'px';  dropdown.style.top = position.top + 'px';  dropdown.style.display = 'block';}

交互控制与事件处理

智能补全功能的交互体验依赖于完善的事件处理机制。本项目中实现了多种事件监听器来处理用户输入、键盘导航等。
input 事件在用户输入时触发建议生成。为了避免频繁更新影响性能,代码使用防抖技术,延迟 80 毫秒执行建议生成逻辑。如果输入的令牌长度大于等于 1,则根据上下文获取建议并渲染下拉框;否则隐藏下拉框。
keydown 事件处理键盘导航:方向键用于在建议项间移动选择,Enter 和 Tab 键确认选择,Esc 键取消建议。
editor.addEventListener('input'() => {  if (compositionInProgress) return;
  clearTimeout(inputDebounceTimer);  inputDebounceTimer = setTimeout(() => {    const { token, tokenStart, cursorPos } = getTokenContext();
    if (token.length >= 1) {      const context = getContext(editor.value, cursorPos, tokenStart);      const suggestions = getSuggestions(token, context);      renderDropdown(suggestions, tokenStart);    } else {      hideDropdown();    }  }, 80);});
editor.addEventListener('keydown'(e) => {  if (compositionInProgress) return;
  if (dropdown.style.display === 'block') {    if (e.key === 'ArrowDown') {      e.preventDefault();      setSelectedIndex(Math.min(selectedIndex + 1, currentSuggestions.length - 1));      return;    } else if (e.key === 'ArrowUp') {      e.preventDefault();      setSelectedIndex(Math.max(selectedIndex - 1, -1));      return;    } else if (e.key === 'Enter' || e.key === 'Tab') {      if (currentSuggestions.length > 0) {        e.preventDefault();        selectSuggestion(Math.max(selectedIndex, 0));        return;      }    } else if (e.key === 'Escape') {      e.preventDefault();      hideDropdown();      return;    }  }
  if ([' ''('')'','';''.''['']'].includes(e.key)) {    setTimeout(() => {      const { token } = getTokenContext();      if (token.length < 1) {        hideDropdown();      }    }, 0);  }});

扩展建议

  • 添加数据库连接功能,动态获取真实表结构信息

  • 实现语法高亮,提升代码可读性和编辑体验

  • 增加一键美化功能,自动调整缩进、换行使代码结构清晰

  • 增加历史记录功能,方便用户查看之前的查询语句

  • 支持更多数据库方言,适应不同的数据库系统

源码地址

git地址:https://gitee.com/ironpro/hjdemo/blob/master/sql-complete/index.html


阅读原文:https://mp.weixin.qq.com/s/bNmB2OXq88lJq_BAYzhsog


该文章在 2026/1/24 10:05:34 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved