PostgreSQL LIKE 子句

PostgreSQL LIKE 子句完全指南

LIKE 是文本模式匹配的利器,配合 ILIKE~~* 可实现 模糊搜索、忽略大小写、正则匹配 等高级功能。
本文涵盖 语法、元字符、性能优化、索引支持、常见陷阱、JSON/数组应用、替代方案 等全部内容。


一、LIKEILIKE 基本语法

WHERE column LIKE pattern
WHERE column ILIKE pattern
运算符说明
LIKE大小写敏感,支持 %_
ILIKE忽略大小写(PostgreSQL 独有),功能同 LIKE

二、元字符(通配符)

字符含义示例
%匹配 0 或多个字符'A%' → Alice, ABC
_匹配单个字符'A_ce' → Alice
\%转义 %'100\%' → 匹配 100%
\_转义 _'A\_B' → 匹配 A_B

三、准备测试数据

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT,
    code VARCHAR(20),
    tags TEXT[],
    metadata JSONB
);

INSERT INTO products (name, code, tags, metadata) VALUES
('iPhone 15 Pro', 'IPH-15-PRO', '{"mobile","apple"}', '{"color": "black", "storage": "256GB"}'),
('Samsung Galaxy S24', 'SAM-S24-ULT', '{"mobile","android"}', '{"color": "silver", "storage": "512GB"}'),
('MacBook Air M2', 'MAC-AIR-M2', '{"laptop","apple"}', '{"color": "space gray"}'),
('Dell XPS 13', 'DEL-XPS-13', '{"laptop","windows"}', '{"color": "platinum"}'),
('AirPods Pro 2', 'AIR-PRO-2', '{"audio","apple"}', '{"color": "white"}'),
('Sony WH-1000XM5', 'SONY-XM5', '{"audio"}', '{"color": "black"}');

四、基础 LIKE 用法

需求SQL
以 ‘iPhone’ 开头WHERE name LIKE 'iPhone%'
包含 ‘Pro’WHERE name LIKE '%Pro%'
以 ‘2’ 结尾WHERE name LIKE '%2'
第1个字符任意,第2个是 ‘P’,共5个字符WHERE code LIKE '_P___'
包含百分号 %WHERE name LIKE '100\%' ESCAPE '\'
-- 查找所有 Pro 系列
SELECT name FROM products WHERE name LIKE '%Pro%';
-- 结果: iPhone 15 Pro, AirPods Pro 2

五、ILIKE:忽略大小写(PostgreSQL 专属)

-- 查找包含 "mac"(不区分大小写)
SELECT name FROM products WHERE name ILIKE '%mac%';
-- 结果: MacBook Air M2

注意LIKE 是大小写敏感的:

'MacBook' LIKE '%mac%' → false
'MacBook' ILIKE '%mac%' → true

六、转义特殊字符

-- 查找 code 包含下划线 '_'
SELECT code FROM products WHERE code LIKE '%\_%' ESCAPE '\';
-- 结果: 所有 code(因为都含 -)

-- 查找 name 包含百分号
INSERT INTO products (name) VALUES ('Discount 50%');
SELECT name FROM products WHERE name LIKE '%50\%%' ESCAPE '\';

七、性能优化:索引支持

问题:LIKE '%abc%' 无法使用普通 B 树索引

模式是否可用索引
'abc%'Yes(左前缀)
'%abc'No
'%abc%'No
'_abc'No

解决方案

方案 1:前缀匹配建索引

CREATE INDEX idx_prod_name_prefix ON products(name);
-- 加速 'iPhone%'
SELECT * FROM products WHERE name LIKE 'iPhone%';

方案 2:表达式索引 + ILIKE

-- 加速忽略大小写搜索
CREATE INDEX idx_prod_name_lower ON products(LOWER(name));
-- 查询
SELECT * FROM products WHERE LOWER(name) ILIKE '%mac%';

方案 3:全文搜索(推荐复杂搜索)

-- 添加 tsvector 列
ALTER TABLE products ADD COLUMN search_text TSVECTOR;
UPDATE products SET search_text = to_tsvector('english', name || ' ' || array_to_string(tags, ' '));

CREATE INDEX idx_prod_fts ON products USING GIN(search_text);

-- 搜索
SELECT * FROM products 
WHERE search_text @@ plainto_tsquery('macbook OR pro');

方案 4:pg_trgm 扩展(模糊匹配)

CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- 创建 trigram 索引
CREATE INDEX idx_prod_name_trgm ON products USING GIN (name gin_trgm_ops);

-- 加速 %abc%
SELECT * FROM products WHERE name ILIKE '%pro%';

八、LIKE 在 JSON 和数组中的应用

1. JSON 文本搜索

-- 查找 metadata.color 包含 "black"
SELECT name, metadata->>'color' FROM products 
WHERE metadata->>'color' ILIKE '%black%';

2. 数组元素匹配

-- 查找 tags 包含 "apple"
SELECT name, tags FROM products 
WHERE 'apple' = ANY(tags);

-- 错误!不能直接用 LIKE
-- WHERE tags LIKE '%apple%' → 错误

正确方式

-- 转换数组为字符串
SELECT name FROM products 
WHERE array_to_string(tags, ',') ILIKE '%apple%';

九、正则表达式替代(~ 系列)

运算符说明
~正则匹配(区分大小写)
~*正则匹配(忽略大小写)
!~正则不匹配
!~*正则不匹配(忽略大小写)
-- 匹配以数字结尾
SELECT name FROM products WHERE name ~ '\d$';

-- 匹配包含 "Pro" 或 "XM"
SELECT name FROM products WHERE name ~* '(Pro|XM)';

性能:正则比 LIKE 慢,慎用


十、常见陷阱与解决方案

陷阱说明解决方案
LIKE '%abc%' 无索引全表扫描pg_trgm 或全文搜索
LIKE 大小写敏感'Apple' LIKE '%apple%' → falseILIKE
转义字符忘记LIKE '%50%%' → 语法错误ESCAPE
NULL 值不匹配NULL LIKE '%'UNKNOWNIS NOT NULL
-- 安全写法
SELECT * FROM products 
WHERE name IS NOT NULL 
  AND name ILIKE '%pro%';

十一、最佳实践 Checklist

项目建议
优先用 ILIKE忽略大小写
前缀匹配'abc%' + B 树索引
复杂搜索pg_trgm 或全文搜索
避免 %abc%除非建 gin_trgm_ops 索引
NULL 安全col IS NOT NULL AND col ILIKE ...
转义ESCAPE '\'

十二、一键搜索系统(推荐架构)

-- 1. 启用扩展
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- 2. 创建组合搜索字段
ALTER TABLE products ADD COLUMN search_text TEXT 
    GENERATED ALWAYS AS (name || ' ' || array_to_string(tags, ' ')) STORED;

-- 3. 建索引
CREATE INDEX idx_prod_search_trgm ON products USING GIN (search_text gin_trgm_ops);

-- 4. 查询
SELECT name, tags FROM products 
WHERE search_text ILIKE '%pro%';

十三、快速实战:5 分钟掌握 LIKE

-- 1. 基础
SELECT name FROM products WHERE name LIKE 'iPhone%';

-- 2. 忽略大小写
SELECT name FROM products WHERE name ILIKE '%mac%';

-- 3. 包含下划线
SELECT code FROM products WHERE code LIKE '%\_%' ESCAPE '\';

-- 4. 建索引加速
CREATE INDEX idx_prod_name_trgm ON products USING GIN (name gin_trgm_ops);
SELECT * FROM products WHERE name ILIKE '%pro%';

现在就动手
products 表中:

  1. 查找 nameS 开头且包含 24 的产品
  2. 查找 code 包含下划线 _ 的记录
  3. 查找 metadata.color 包含 black 的产品
  4. 启用 pg_trgm,建索引,测试 %pro% 搜索性能

十四、性能对比(EXPLAIN)

-- 慢查询(无索引)
EXPLAIN ANALYZE SELECT * FROM products WHERE name ILIKE '%pro%';

-- 快查询(有 trgm 索引)
CREATE INDEX idx_prod_name_trgm ON products USING GIN (name gin_trgm_ops);
EXPLAIN ANALYZE SELECT * FROM products WHERE name ILIKE '%pro%';

需要我生成:

  • 1000 条测试数据 + 模糊搜索压力测试?回复 测试数据
  • 全文搜索 vs LIKE 性能对比?回复 性能对比
  • Python 动态 LIKE 查询(防注入)?回复 Python LIKE
  • 实时搜索自动补全?回复 自动补全

随时告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注