SET類型是MySQL獨有的集合類型,底層以位圖存儲,單欄位最多64成員,極適合「標籤、屬性、權限位」等多值單選場景。本文深度解析位運算增刪查核心技巧。
`mark` SET('index','best','hot')
-- 成員對應位值:
-- index → 第0位 → 2^0 = 1
-- best → 第1位 → 2^1 = 2
-- hot → 第2位 → 2^2 = 4
-- 組合 'index,best' → 1|2 = 3
-- 組合 'index,hot' → 1|4 = 5
MySQL自動處理字符串↔數字轉換,SET mark=1與SET mark='index'等效。
| 操作 | SQL模板 | 位運算原理 | 範例 |
|---|---|---|---|
| 新增標籤 | UPDATE t SET mark = mark | 值 | 按位或 |:置1保留原有 | mark = mark | 1 | 2 加 index+best |
| 刪除標籤 | UPDATE t SET mark = mark & ~值 | 按位與取反 & ~:目標位清0,其它保留 | mark = mark & ~4 & ~1 刪 hot+index |
| 查詢包含 | SELECT * FROM t WHERE FIND_IN_SET('標籤', mark) | 內建函數,自動解析集合 | WHERE FIND_IN_SET('hot', mark) |
| 查詢包含(位運算) | SELECT * FROM t WHERE mark & 值 | 按位與 &:結果非0即包含 | WHERE mark & 1 含 index |
-- 表結構
CREATE TABLE article (
id INT PRIMARY KEY,
title VARCHAR(100),
tags SET('tech','life','travel','food','sport') -- 5標籤,值1,2,4,8,16
);
-- 發文帶標籤
INSERT INTO article (id, title, tags) VALUES (1, 'MySQL SET深度解析', 'tech,life');
-- 後台添加 'travel' 標籤(不影響原有)
UPDATE article SET tags = tags | 4 WHERE id = 1; -- 4 = travel
-- 移除 'life' 標籤
UPDATE article SET tags = tags & ~2 WHERE id = 1; -- 2 = life
-- 查詢含 'tech' 的文章
SELECT * FROM article WHERE FIND_IN_SET('tech', tags);
-- 或
SELECT * FROM article WHERE tags & 1;
SELECT
SUM(tags & 1) AS tech_cnt,
SUM(tags & 2) AS life_cnt,
SUM(tags & 4) AS travel_cnt
FROM article;
WHERE (tags & 1) AND (tags & 4)WHERE tags & (1|4) 或 WHERE FIND_IN_SET('tech',tags) OR FIND_IN_SET('travel',tags)SELECT CAST(tags AS CHAR) FROM article WHERE id=1 → 'tech,travel'| 坑點 | 說明 | 規避 |
|---|---|---|
| 成員超過64個 | SET最大64成員 | 改用JSON或關聯表 |
| 成員名含逗號/空格 | 解析錯誤 | 成員名用下劃線,不含特殊字符 |
| NOT NULL預設值 | 預設為空字符串'' | 顯式DEFAULT '' |
| 索引效能 | SET欄位索引效果一般 | 高頻查詢建冗余標籤表或JSON索引 |
SET類型配合位運算,以「極小空間、極快運算」實現多值屬性管理,是標籤系統的輕量級首選。