MySQL 中 `${}` 和 `#{}` 占位符詳解及面試高頻考點

文章目錄

    • 一、概述
    • 二、`#{}` 和 `${}` 的核心區別
      • 1. 底層機制
        • 代碼示例
      • 2. 核心區別總結
    • 三、為什么表名只能用 `${}`?
      • 1. 預編譯機制的限制
      • 2. 動態表名的實現
    • 四、安全性注意事項
      • 1. `${}` 的風險場景
      • 2. 安全實踐
    • 五、面試高頻考點
      • 1. 基礎原理類問題
        • **問題 1**:
        • **問題 2**:
      • 2. 安全與設計類問題
        • **問題 3**:
        • **問題 4**:
      • 3. 擴展實戰類問題
        • **問題 5**:
    • 六、總結與最佳實踐
      • 1. 使用場景對比
      • 2. 最佳實踐
    • 七、附錄:MyBatis 預編譯原理圖示

一、概述

在 MySQL 和 MyBatis 等框架中,${}#{} 是動態 SQL 中常用的占位符。它們的核心差異在于 預編譯機制安全性,正確使用二者是后端開發的基本功,也是面試中的高頻考點。本文將從原理、場景、安全性及面試題四方面深入解析。


二、#{}${} 的核心區別

1. 底層機制

占位符預編譯替換方式安全性
#{}?參數化綁定 (?)
${}?字符串直接拼接
代碼示例
-- #{}
SELECT * FROM users WHERE name = #{name};
-- 預編譯后:SELECT * FROM users WHERE name = ?;-- ${}
SELECT * FROM ${table} WHERE id = 1;
-- 替換后:SELECT * FROM users_2023 WHERE id = 1;

2. 核心區別總結

  • #{}
    用于替換 值類型(如 WHERE 條件值、INSERT 字段值),通過 PreparedStatement 預編譯,防止 SQL 注入。
  • ${}
    用于替換 標識符(如表名、列名、ORDER BY 子句),直接拼接字符串,需手動校驗安全性。

三、為什么表名只能用 ${}

1. 預編譯機制的限制

  • 數據庫協議限制:預編譯占位符 ? 僅支持替換值類型(字符串、數字等),不能替換表名、列名等標識符。
  • 語法合法性:以下寫法直接報錯:
    -- 錯誤!表名無法預編譯
    SELECT * FROM ? WHERE id = 1;
    

2. 動態表名的實現

若需根據業務邏輯動態切換表(如分表場景),只能通過字符串拼接:

<!-- MyBatis 示例 -->
<select id="selectLogs" resultType="Log">SELECT * FROM logs_${month}
</select>

四、安全性注意事項

1. ${} 的風險場景

// 惡意輸入導致 SQL 注入
String userInput = "users; DROP TABLE users; --";
String sql = "SELECT * FROM " + userInput; 
// 執行結果:SELECT * FROM users; DROP TABLE users; --

2. 安全實踐

  1. 禁止用戶控制表名:表名應在代碼層生成(如根據時間分表),而非直接傳遞用戶輸入。
  2. 白名單校驗:若必須動態傳參,需校驗參數格式(如正則匹配 ^[a-zA-Z0-9_]+$)。
  3. SQL 審計:攔截非常規表名操作(如 information_schema)。

五、面試高頻考點

1. 基礎原理類問題

問題 1

“MyBatis 中 #{}${} 的底層實現有什么區別?”

  • #{} 使用 PreparedStatement 預編譯,參數替換為 ?,防止 SQL 注入。
  • ${} 直接拼接字符串,無預編譯,需手動處理安全性。

場景
面試官考察候選人對 MyBatis 執行過程的理解,是否清楚預編譯機制。


問題 2

“為什么表名必須用 ${}?能否用 #{}?”

數據庫協議規定預編譯占位符 ? 只能替換值類型,不能替換表名、列名等標識符。若強行使用 #{},最終生成的 SQL 會因語法錯誤無法執行。

場景
面試中常見于考察 SQL 預編譯機制的底層知識。


2. 安全與設計類問題

問題 3

“如何安全地使用 ${} 動態指定表名?”

  • 代碼層控制:表名由系統生成(如 user_2023),而非用戶傳入。
  • 白名單校驗:若需外部傳入,校驗參數是否符合命名規范(如正則匹配)。
  • 日志監控:記錄所有動態表名操作,便于審計。

場景
考察安全意識和實際工程經驗,常見于金融、數據安全相關崗位。


問題 4

“除了表名,還有哪些場景必須用 ${}?”

  • 動態列名:SELECT ${column} FROM table
  • 排序字段:ORDER BY ${sortField}
  • 動態 SQL 片段:<if test="condition">${sqlSegment}</if>

場景
面試官可能延伸考察動態 SQL 的靈活應用能力。


3. 擴展實戰類問題

問題 5

“如果必須讓用戶傳入表名,如何設計安全方案?”

  1. 前端傳遞表名編碼(如 1=users, 2=products),后端映射為真實表名。
  2. 參數加密:用戶傳入加密參數,后端解密后匹配預定義表名。
  3. 數據庫權限隔離:動態表操作使用只讀低權限賬號。

場景
高級崗位考察系統設計能力,尤其是安全與靈活性平衡的方案。


六、總結與最佳實踐

1. 使用場景對比

場景占位符示例
WHERE 條件值#{}WHERE id = #{id}
動態表名/列名${}SELECT * FROM ${table}
排序字段${}ORDER BY ${sort}

2. 最佳實踐

  • 默認使用 #{}:除非必須使用 ${}
  • 最小化 ${} 暴露:禁止用戶傳入未經驗證的參數。
  • 日志 + 監控:記錄所有動態 SQL 操作,及時預警異常行為。

七、附錄:MyBatis 預編譯原理圖示

MyBatis 執行流程:
1. 解析 XML SQL → 2. 替換 `#{}` 為 `?` → 3. 預編譯 SQL → 4. 綁定參數值 → 5. 執行

文檔說明:本文適用于初中級后端開發者鞏固知識點,以及資深開發者面試復習。建議結合 MyBatis 源碼和 MySQL 協議文檔深入理解。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76097.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76097.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76097.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言編譯預處理2

#include <XXXX.h>和#include <XXXX.c> #include "XXXX.h" 是 C 語言中一條預處理指令 #include <XXXX.h>&#xff1a;這種形式用于包含系統標準庫的頭文件。預處理器會在系統默認的頭文件搜索路徑中查找XXXX.h 文件。例如在 Linux 系統中&#…

Elasticvue-輕量級Elasticsearch可視化管理工具

Elasticvue一個免費且開源的 Elasticsearch 在線可視化客戶端&#xff0c;用于管理 Elasticsearch 集群中的數據&#xff0c;完全支持 Elasticsearch 版本 8.x 和 7.x. 功能特色&#xff1a; 集群概覽索引和別名管理分片管理搜索和編輯文檔REST 查詢快照和存儲庫管理支持國際…

Git提交規范及最佳實踐

Git 提交規范通常是為了提高代碼提交的可讀性、可維護性和自動化效率&#xff08;如生成 ChangeLog&#xff09;。以下是常見的 Conventional Commits 規范&#xff0c;結合社區最佳實踐總結而成&#xff1a; 1. 提交格式 每次提交的 commit message 應包含三部分&#xff1a;…

Ubuntu中snap

通過Snap可以安裝眾多的軟件包。需要注意的是&#xff0c;snap是一種全新的軟件包管理方式&#xff0c;它類似一個容器擁有一個應用程序所有的文件和庫&#xff0c;各個應用程序之間完全獨立。所以使用snap包的好處就是它解決了應用程序之間的依賴問題&#xff0c;使應用程序之…

android studio 運行java main報錯

運行某個帶main函數的java文件報錯 Could not create task :app:Test.main(). > SourceSet with name main not found. 解決辦法&#xff1a;在工程的.idea/gradle.xml 文件下添加&#xff1a; <option name"delegatedBuild" value"false" /&g…

openssh離線一鍵升級腳本分享(含安裝包)

查看當前的版本 [rootmyoracle ~]#ssh -V相關安裝包下載地址 openssh下載地址&#xff1a;http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssl下載地址&#xff1a;https://www.openssl.org/source/zlib下載地址&#xff1a;http://www.zlib.net/今天演示從7.4升級…

Mac M1管理多個Node.js版本

目錄 1. 使用 nvm (Node Version Manager) 1.1.安裝 nvm 1.2.安裝Node.js版本 1.3.查看已安裝的node版本列表 1.4.使用特定版本的Node.js 1.5.查看當前使用的版本 2. 使用 fnm (Fast Node Manager) 2.1.安裝 fnm 2.2.安裝Node.js版本 2.3.查看已安裝的版本 2.4.使用…

Unity中國戰略調整簡訊:Unity6下架 團結引擎接棒

Unity中國戰略調整簡訊&#xff1a;Unity6下架 團結引擎接棒 免費版 2025年4月9日 —— Unity中國宣布自即日起&#xff0c;中國大陸及港澳地區停止提供Unity 6及后續版本下載與服務&#xff0c;相關功能由國產引擎“團結引擎”承接。國際版2022 LTS及更早版本仍由Unity中國維護…

TestNG 單元測試詳解

1、測試環境 jdk1.8.0 121 myeclipse-10.0-offline-installer-windows.exe TestNG 插件 org.testng.eclipse 6.8.6.20130607 0745 2、介紹 套件(suite):由一個 XML 文件表示,通過<suite>標簽定義,包含一個或更多測試(test)。測試(test):由<test>定義&#xf…

C復習(主要復習)

指針和數組 指針數組是一個數組&#xff0c;數組的每個元素都是指針。它適用于需要存儲多個指針的場景&#xff0c;如字符串數組。數組指針是一個指針&#xff0c;指向一個數組。它適用于需要傳遞整個數組給函數或處理多維數組的場景。 函數指針&#xff1a;函數指針的定義需要…

探索大語言模型(LLM):定義、發展、構建與應用

文章目錄 引言大規模語言模型的基本概念大規模語言模型的發展歷程1. 基礎模型階段&#xff08;2018年至2021年&#xff09;2. 能力探索階段&#xff08;2019年至2022年&#xff09;3. 突破發展階段&#xff08;以2022年11月ChatGPT的發布為起點&#xff09; 大規模語言模型的構…

5. k8s 之 pod原理與使用

Kubernetes Pod 原理詳解 1. Pod 的部署方式 Pod 是 Kubernetes 的最小調度單元&#xff0c;其部署方式分為 聲明式&#xff08;YAML&#xff09; 和 命令式&#xff08;kubectl&#xff09; 兩種&#xff1a; (1) 聲明式部署&#xff08;推薦&#xff09; 通過 YAML 文件定…

使用PyTorch實現目標檢測邊界框轉換與可視化

一、引言 在目標檢測任務中&#xff0c;邊界框&#xff08;Bounding Box&#xff09;的坐標表示與轉換是核心基礎操作。本文將演示如何&#xff1a; 實現邊界框的兩種表示形式&#xff08;角點坐標 vs 中心坐標&#xff09;之間的轉換 使用Matplotlib在圖像上可視化邊界框 驗…

電影推薦及數據分析可視化系統(Python+Echarts+Mysql+Flask框架)

提升自己&#xff0c;掌握數據分析的能力&#xff0c;最快的方式就是實踐&#xff01; 下面是對本項目的一些功能展示、介紹以及部分核心代碼的展示,附項目系統展示的視頻,制作不易如需完整代碼后臺私信我有償獲取! 一 、系統分析及功能介紹 1.系統分析 系統采用Python作為開發…

Android Jetpack Compose 高級開發核心技術

Android Compose 高級技術總結 1. 性能優化 1.1 狀態管理優化 狀態提升原則&#xff1a;將狀態提升到共享的最近共同父組件derivedStateOf&#xff1a;當需要基于多個狀態計算派生狀態時使用 val scrollState rememberScrollState() val showButton by remember {derivedS…

Java堆結構深度解析:原理、實現與應用全指南

一、堆的核心概念體系 1. 堆的定義與性質 graph TBROOT((最大堆)) --> A[父節點 ≥ 子節點]ROOT --> B[完全二叉樹結構]ROOT --> C[數組存儲]ROOT --> D[快速獲取極值] 2. 堆類型對比 類型特性典型應用場景最大堆父節點值 ≥ 子節點值獲取前K大元素最小堆父節點…

SpringMVC學習(請求與響應。常見參數類型接收與響應。@RequestParam、@RequestBody的使用)(詳細示例)

目錄 一、請求與響應。(RequestMapping) &#xff08;1&#xff09;使用注解RequestMapping對業務模塊區分。 StudentController。 TeacherController。 &#xff08;2&#xff09;Apifox請求與響應。 "/student/login"。 "/teacher/login"。 二、常見參數…

回溯算法+對稱剪枝——從八皇后問題到數獨問題(二)

引入&#xff1a; 本節我們進一步完善八皇后問題&#xff0c;學習剪枝、八皇后殘局問題 進一步領會邏輯編程的概念&#xff0c;深入體會回溯算法&#xff0c;回顧上一節提到的啟發搜索策略。 回顧&#xff1a; 八皇后問題&#xff1a;我們需要在一個空棋盤上放置 n 個皇后&a…

【玩泰山派】MISC(雜項)- 使用vscode遠程連接泰山派進行開發

文章目錄 前言流程1、安裝、啟動sshd2、配置一下允許root登錄3、vscode中配置1、安裝remote插件2、登錄 **注意** 前言 有時候要在開發板中寫一寫代碼&#xff0c;直接在終端中使用vim這種工具有時候也不是很方便。這里準備使用vscode去通過ssh遠程連接泰山派去操作&#xff0…

【VsCode】設置文件自動保存

目錄 一、前言 二、操作步驟 一、前言 VSCode中開啟自動保存功能可以通過訪問設置、修改settings.json文件、使用自動保存延遲功能來實現。這些方法能有效提升編程效率、避免數據丟失、實時同步更改。 二、操作步驟 在 Visual Studio Code (VS Code) 中設置自動保存功能非…