MySQL 中查詢 VARCHAR 類型 JSON 數據的

在數據庫設計中,有時我們會將 JSON 數據存儲在 VARCHAR 或 TEXT 類型字段中。這種方式雖然靈活,但在查詢時需要特別注意。本文將詳細介紹如何在 MySQL 中有效查詢存儲為 VARCHAR 類型的 JSON 數據。

一、問題背景

當 JSON 數據存儲在 VARCHAR 列中時,常見的數據格式如下:

[{"id":"1905555466980773889","hasPermission":true},{"id":"1905547884060835841","hasPermission":false}
]

我們需要查詢這個 JSON 數組中是否包含特定 ID 的對象。

二、MySQL JSON 函數

MySQL 5.7+ 版本提供了豐富的 JSON 處理函數,即使數據類型是 VARCHAR,只要內容是有效的 JSON,我們仍然可以使用這些函數:

2.1 常用 JSON 函數

  • JSON_CONTAINS(target, candidate[, path]): 檢查 JSON 文檔是否包含特定值
  • JSON_EXTRACT(json_doc, path): 從 JSON 文檔中提取值
  • JSON_OBJECT(key, val[, key, val]...): 創建 JSON 對象
  • JSON_ARRAY(val[, val]...): 創建 JSON 數組
  • JSON_VALID(json_doc): 驗證字符串是否為有效的 JSON

三、查詢示例

3.1 基本查詢

查詢 JSON 數組中包含特定 ID 的記錄:

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

3.2 查詢多個 ID

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND (JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'))OR JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905547884060835841')));

3.3 使用 JSON_OVERLAPS (MySQL 8.0+)

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_OVERLAPS(app_ids, JSON_ARRAY(JSON_OBJECT('id', '1905555466980773889'),JSON_OBJECT('id', '1905547884060835841')));

3.4 查詢特定權限的記錄

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889', 'hasPermission', true));

四、避免常見錯誤

4.1 空值處理

JSON_CONTAINS 函數在處理 NULL 或空字符串時會報錯,所以需要先排除這些情況:

-- 錯誤做法
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, JSON_OBJECT('id', '123'));-- 正確做法
SELECT * FROM sys_user 
WHERE app_ids IS NOT NULL AND app_ids != '' AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '123'));

4.2 JSON 格式匹配

確保 JSON_CONTAINS 的第二個參數結構與目標 JSON 中的結構匹配:

-- 錯誤做法 (直接傳入 ID 字符串)
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, '"1905555466980773889"');-- 正確做法 (創建與數組元素匹配的對象)
SELECT * FROM sys_user WHERE JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

4.3 確保 JSON 有效性

添加 JSON_VALID 檢查確保字段內容是有效的 JSON:

SELECT * FROM sys_user
WHERE app_ids IS NOT NULLAND app_ids != ''AND JSON_VALID(app_ids) = 1AND JSON_CONTAINS(app_ids, JSON_OBJECT('id', '1905555466980773889'));

五、在 MyBatis Plus 中的應用

5.1 基本查詢

LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.isNotNull(SysUser::getAppIds).ne(SysUser::getAppIds, "").apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889");List<SysUser> userList = sysUserMapper.selectList(queryWrapper);

5.2 多條件查詢

QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("app_ids").ne("app_ids", "").apply("JSON_VALID(app_ids) = 1").apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889");// 如果還要根據權限過濾
queryWrapper.apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}, 'hasPermission', {1}))", "1905555466980773889", true);

5.3 查詢多個 ID

LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.isNotNull(SysUser::getAppIds).ne(SysUser::getAppIds, "").and(w -> w.apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905555466980773889").or().apply("JSON_CONTAINS(app_ids, JSON_OBJECT('id', {0}))", "1905547884060835841"));List<SysUser> userList = sysUserMapper.selectList(queryWrapper);

六、性能優化建議

  1. 考慮使用 JSON 類型:如果您的 MySQL 版本是 5.7+,考慮使用原生 JSON 類型代替 VARCHAR,這樣可以獲得更好的性能和功能支持。

  2. 添加索引:雖然無法直接為 JSON 內容創建索引,但可以使用生成的列和函數索引:

    ALTER TABLE sys_user ADD COLUMN app_id_extracted JSON GENERATED ALWAYS AS (JSON_EXTRACT(app_ids, '$[*].id')) VIRTUAL;ALTER TABLE sys_user ADD INDEX idx_app_id_extracted (app_id_extracted);
    
  3. 定期維護:對于大表,定期 OPTIMIZE TABLE 有助于維護性能。

七、總結

在 MySQL 中查詢 VARCHAR 類型的 JSON 數據時,關鍵是:

  1. 使用 JSON_CONTAINS 函數并構造正確的 JSON 結構進行匹配
  2. 處理好 NULL 和空字符串
  3. 驗證 JSON 有效性
  4. 在 MyBatis Plus 中使用 apply 方法添加原生 SQL 條件

正確使用這些技術可以有效地查詢和處理 VARCHAR 中存儲的 JSON 數據。

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

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

相關文章

路由器開啟QOS和UPNP的作用

QOS 的作用 保障關鍵業務帶寬&#xff1a;可根據網絡應用的重要性分配帶寬。比如在家庭網絡中&#xff0c;當多人同時使用網絡時&#xff0c;將視頻會議等實時性要求高的關鍵業務設置為高優先級&#xff0c;確保其能獲得足夠帶寬&#xff0c;避免卡頓&#xff0c;而文件下載等…

5G網絡下客戶端數據業務掉線頻繁

MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;客戶端的日志&#xff0c;和界面在待機狀態下&#xff08;即沒有做通話等業務操作&#xff09;&#xff0c;會頻繁提示“離線”。 主要先看有沒有丟網&#xff0c;UL BLER有沒有問題。確認沒有問題。看到業務信道釋…

使用Python和Matplotlib可視化字體輪廓:從路徑數據到矢量圖形

引言 字體設計和矢量圖形處理是編程中一個有趣且實用的領域。通過Python的matplotlib庫&#xff0c;我們可以輕松將字體輪廓的路徑數據轉換為直觀的矢量圖形。本文將帶你一步步實現這一過程&#xff0c;并解析代碼細節&#xff0c;幫助你理解如何將復雜的路徑指令轉化為可視化…

4.13日總結

javafx中實現發送qq郵箱驗證碼: 手動導入jar包方法&#xff1a; 第一步&#xff1a;開啟QQ郵箱的 POP3/IMAP 或者 SMTP/IMAP 服務 打開qq郵箱&#xff08;電腦端&#xff09;&#xff0c;找到設置里的賬號與安全的安全設置&#xff0c;往下滑就可以找到 POP3/IMAP 或者 SMTP…

智慧鄉村數字化農業全產業鏈服務平臺建設方案PPT(99頁)

1. 農業全產業鏈概念 農業全產業鏈是依托數字化、電子商務、云計算等技術&#xff0c;整合規劃咨詢、應用軟件設計與開發等服務&#xff0c;推動農業產業升級和價值重塑&#xff0c;構建IT產業融合新生態。 2. 產業鏈技術支撐 利用云計算、大數據、區塊鏈等技術&#xff0c;為…

k8s的配置文件總結

在 Kubernetes 中&#xff0c;配置文件 是定義集群資源的核心&#xff0c;通常以 YAML 或 JSON 格式編寫。以下是 Kubernetes 中關鍵的配置文件類型及其作用&#xff1a; 1. 核心工作負載配置 (1) Deployment ? 用途&#xff1a;定義無狀態應用的 Pod 副本管理策略&#xff…

STM32(基于標準庫)

參考博客&#xff1a;江科大STM32筆記 Stm32外設 一、GPIO 基礎 GPIO位結構 I/O引腳的保護二極管是對輸入電壓進行限幅的上面的二極管接VDD, 3.3V,下面接VSS, 0V&#xff0c;當輸入電壓 >3.3V 那上方這個二極管就會導通&#xff0c;輸入電壓產生的電流就會大部分充入VD…

為什么我們需要if __name__ == __main__:

[目錄] 0.前言 1.什么是 __name__&#xff1f; 2.if __name__ __main__: 的作用 3.為何Windows更需if __name__ &#xff1f;前言 if __name__ __main__: 是 Python 中一個非常重要的慣用法&#xff0c;尤其在使用 multiprocessing 模塊或編寫可導入的模塊時。它的作用是區分…

速盾:高防CDN的原理和高防IP一樣嗎?

隨著互聯網的發展&#xff0c;網絡安全威脅日益嚴重&#xff0c;尤其是DDoS攻擊、CC攻擊等惡意行為&#xff0c;給企業帶來了巨大的風險。為了應對這些挑戰&#xff0c;許多企業開始采用高防CDN&#xff08;內容分發網絡&#xff09;和高防IP作為防御措施。盡管兩者都能提供一定…

《算法筆記》3.6小節——入門模擬->字符串處理

1009 說反話 #include <cstdio>int main() {char sen[80][80];int num0;while(scanf("%s",sen[num])!EOF){num;}for (int i num-1; i > 0; --i) {printf("%s ",sen[i]);}printf("%s\n",sen[0]);return 0; }字符串連接 #include <io…

供應鏈業務-供應鏈全局觀(三)- 供應鏈三流的集成

概述 供應鏈的全局觀的全兩篇文章主要描述了供應鏈的基礎概念和供應鏈的協作和集成問題。 供應鏈業務-供應鏈全局觀&#xff08;一&#xff09;定義了什么是供應鏈和供應鏈管理。 所謂供應鏈就是把采購進來的東西&#xff0c;通過自身的生成加工&#xff0c;進行增值服務&am…

鏈表-算法小結

鏈表 單鏈表 雙鏈表 循環鏈表 鏈表_stl-CSDN博客 虛擬頭結點 反轉鏈表 刪除鏈表元素 方法一: 直接使用原來的鏈表來進行刪除操作。 頭節點是否為空頭鏈表的值是否為要刪除的值頭結點刪除后,新的頭節點是否依舊要刪除 ,刪除后的,新頭節點可能是空結點 方法二: 設置一個虛擬…

C語言中常用的調試宏和函數總結(__LINE__、__FUNCTION__)

表格&#xff1a;C語言調試工具 類別工具描述示例代碼預定義宏__LINE__表示當前源代碼的行號。printf("Error occurred at line %d\n", __LINE__);__FILE__表示當前源代碼文件的名稱。printf("Error occurred in file %s\n", __FILE__);__func__表示當前函…

DotnetCore開源庫SampleAdmin源碼編譯

1.報錯: System.Net.Sockets.SocketException HResult0x80004005 Message由于目標計算機積極拒絕&#xff0c;無法連接。 SourceSystem.Net.Sockets StackTrace: 在 System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, C…

如何使用切片操作來處理序列數據

1 問題 本文主要探究 Python 中切片操作的原理和應用。具體來說&#xff0c;我們將分析切片的基本語法、切片的步長和切片的邊界&#xff0c;并通過示例代碼展示如何使用切片操作來處理序列數據。 2 方法 為了更好地理解切片操作&#xff0c;我們采用如下的思路學習python中的切…

java(二):java的運算和流程控制

java中單引號和雙引號區別和用法 區別1&#xff1a;java中的單引號表示字符&#xff0c;雙引號表示字符串。 區別2&#xff1a;單引號引的數據一般是char類型的&#xff1b;雙引號引的數據 是String類型的。 區別3&#xff1a;java中單引號里面只能放一個字母或數字或符號&…

Android envsetup與Python venv使用指南

Android envsetup 和 Python venv 是兩種完全不同的環境配置工具&#xff0c;分別服務于不同的開發場景。以下是對它們的詳細解釋及使用方法&#xff1a; 1. Android envsetup 用途&#xff1a; Android envsetup 是 Android 源碼開發中的環境配置腳本&#xff08;envsetup.sh…

游戲引擎學習第222天

回顧昨天的過場動畫工作 我們正在制作一個游戲&#xff0c;目標是通過直播的方式完成整個游戲的開發。在昨天的工作中&#xff0c;我享受了制作過場動畫的過程&#xff0c;所以今天我決定繼續制作多個層次的過場動畫。 昨天我們已經開始了多層次過場動畫的基本制作&#xff0…

Leedcode刷題 | Day31_貪心算法05

一、學習任務 56. 合并區間代碼隨想錄738. 單調遞增的數字968. 監控二叉樹 二、具體題目 1.56合并區間56. 合并區間 - 力扣&#xff08;LeetCode&#xff09; 給出一個區間的集合&#xff0c;請合并所有重疊的區間。 示例 1: 輸入: intervals [[1,3],[2,6],[8,10],[15,1…

app逆向專題五:新快報app數據采集

app逆向專題五:新快報app數據采集 一、抓包尋找數據接口二、編寫代碼三、完整代碼一、抓包尋找數據接口 打開charles,并在手機端打開新快報app,點擊“廣州”或者“經濟”等選項卡,抓包,尋找數據接口,如圖所示: 二、編寫代碼 這里介紹一種簡便的代碼編寫方法,在數據…