WeHelp
MySQL/ MariaDB 之 JSON 欄位值查詢
2024-09-22 17:59:13
如果資料表某個欄位儲存的資料格式是 JSON,想要透過這個 JSON 的某個屬性去過濾資料,要怎麼做呢? 舉例來說,我有一張表用來儲存使用者資訊如下圖。 ``` | name | detail | | ----- | ------------------------------- | | Kevin | {"gender": "male", "age": 23} | | Amy | {"gender": "female", "age": 25} | | Alice | {"gender": "female", "age": 20} | ``` 目標 : 找出整張表裡面性別是女性的使用者資料。 --- 首先,先建立一張測試用的表格。 ```sql create table user( name varchar(50), detail json ); ``` 加一些測試用資料進去。 ```sql insert into user values ('Kevin', '{"gender": "male", "age": 23}'), ('Amy', '{"gender": "female", "age": 25}'), ('Alice', '{"gender": "female", "age": 20}'); ``` 運用不帶 where 條件的搜尋語句,把全部資料都列出來。 ```sql select * from user; ``` ``` | name | detail | | ----- | ------------------------------- | | Kevin | {"gender": "male", "age": 23} | | Amy | {"gender": "female", "age": 25} | | Alice | {"gender": "female", "age": 20} | ``` 我們的目標是想要用 detail 欄位裡面 JSON 格式的 gender 屬性來過濾資料,這個時候可以使用內建的 JSON_CONTAINS() 函數,有找到指定資料時會返回 1 ,沒找到時會返回 0。 `JSON_CONTAINS(欄位名稱, 值, 用來過濾資料的屬性)` 因此,要過濾出 gender 是 female 的資料, sql 指令可以這樣下 : ```sql -- 方法一 select * from user where JSON_CONTAINS(detail, '"female"', '$.gender'); -- 方法二 select * from user where JSON_CONTAINS(detail, '{"gender": "female"}'); ``` 注意! 因為 JSON_CONTAINS 的第二個參數需要放字串形式的資料,但如果資料本來就是以字串形態存在,如上圖的 female,則除了原本字串的引號外,需要另外再多加一層引號才能正常運作。 ```sql select * from user where JSON_CONTAINS(detail, '23', '$.age'); ``` 如果改成用 age 去搜尋,因為原本是數字格式,就只需要加單層引號即可。 --- 補充資訊一 JSON_CONTAINS 的第一個參數,其實只要是 JSON 格式的資料都可以放。 ```sql SET @json = '{"A": 0, "B": {"C": 1}, "D": 2}'; SELECT JSON_CONTAINS(@json, '2', '$.A'); ``` 也就是說,除了針對資料表的欄位值,其實也可以針對一個定義好的變數進行搜尋,上述的指令會得到以下結果。 ``` | JSON_CONTAINS(@json, '2', '$.A') | | -------------------------------- | | 0 | ``` --- 補充資訊二 我把 user 這張資料表改成用來記錄學生有選修哪些課堂,detail 裡面變成陣列裡面裝多個 JSON 格式的資料。 ``` | name | detail | | ----- | ----------------------------------------------------------------------------- | | Jack | [{"classNo": 1, "className": "Math"}, {"classNo": 2, "className": "Art"}] | | Grace | [{"classNo": 1, "className": "Math"}, {"classNo": 3, "className": "Sport"}] | | Marry | [{"classNo": 3, "className": "Sport"}, {"classNo": 4, "className": "Nature"}] | ``` 我想找出有選修體育課的使用者,指令可以這樣下 : ```sql select * from user where JSON_CONTAINS(detail, '{"className": "Sport"}'); -- 注意!這邊用以下寫法是無效的,因為最上層的陣列本身並不包含 className 屬性 select * from user where JSON_CONTAINS(detail, '"Sport"', '$.className'); ``` --- 以上就是這次的分享,MySQL/ MariaDB 裡面還有很多內建的函數可以使用,有機會大家也可以自己操作看看~ 最後偷偷放個 [Medium](https://medium.com/@HeronCheng/mysql-mariadb-%E4%B9%8B-json-%E6%AC%84%E4%BD%8D%E5%80%BC%E6%9F%A5%E8%A9%A2-f098b9768490) 連結。