SQL查询中字符串重复两次,如何遵循DRY原则提升可维护性?
符合DRY原则的SQL代码优化方案(避免重复字符串列表)
针对你这段重复使用字符串列表的SQL,以下几种方法能提升可维护性,完全符合DRY(Don't Repeat Yourself)原则:
1. 使用CTE(公共表表达式)
这是最通用且易读的方案,几乎所有现代数据库(PostgreSQL、MySQL 8+、SQL Server等)都支持。只需要在查询开头定义一次目标列表,后续查询直接引用即可,修改时只需改动CTE部分。
简洁版(支持VALUES子句的数据库)
WITH target_gizmos(name) AS ( VALUES ('foo'), ('bar'), ('baz'), ('bletch') ) SELECT * FROM gizmo_details WHERE _gizmo_name IN (SELECT name FROM target_gizmos) OR gizmo_id IN ( SELECT id FROM gizmos WHERE gizmo_name IN (SELECT name FROM target_gizmos) );
兼容版(适合所有支持CTE的数据库)
如果你的数据库不支持在CTE中直接用VALUES,可以用UNION ALL拼接:
WITH target_gizmos AS ( SELECT 'foo' AS name UNION ALL SELECT 'bar' UNION ALL SELECT 'baz' UNION ALL SELECT 'bletch' ) SELECT * FROM gizmo_details WHERE _gizmo_name IN (SELECT name FROM target_gizmos) OR gizmo_id IN ( SELECT id FROM gizmos WHERE gizmo_name IN (SELECT name FROM target_gizmos) );
2. 使用表变量(特定数据库支持)
对于SQL Server、MySQL这类支持会话变量的数据库,可以把列表存入表变量,后续查询复用。
SQL Server示例
DECLARE @targetNames TABLE (name VARCHAR(50)); INSERT INTO @targetNames VALUES ('foo'), ('bar'), ('baz'), ('bletch'); SELECT * FROM gizmo_details WHERE _gizmo_name IN (SELECT name FROM @targetNames) OR gizmo_id IN ( SELECT id FROM gizmos WHERE gizmo_name IN (SELECT name FROM @targetNames) );
MySQL示例
SET @targetNames = 'foo,bar,baz,bletch'; SELECT * FROM gizmo_details WHERE FIND_IN_SET(_gizmo_name, @targetNames) OR gizmo_id IN ( SELECT id FROM gizmos WHERE FIND_IN_SET(gizmo_name, @targetNames) );
注意:FIND_IN_SET会有一定性能损耗,但你不关注性能,仅从可维护性角度看,这种方式只需修改一次变量值即可。
3. 创建临时表(适合跨查询复用)
如果这个字符串列表需要在多个查询中使用,可以创建临时表存储,所有查询直接引用临时表即可。
CREATE TEMPORARY TABLE target_gizmos ( name VARCHAR(50) PRIMARY KEY ); INSERT INTO target_gizmos VALUES ('foo'), ('bar'), ('baz'), ('bletch'); SELECT * FROM gizmo_details WHERE _gizmo_name IN (SELECT name FROM target_gizmos) OR gizmo_id IN ( SELECT id FROM gizmos WHERE gizmo_name IN (SELECT name FROM target_gizmos) ); -- 临时表在会话结束后会自动清理,也可以手动删除 DROP TEMPORARY TABLE IF EXISTS target_gizmos;
优先推荐方案
优先选择CTE方案,它不需要额外创建数据库对象,代码结构清晰,可读性高,修改时仅需调整CTE中的列表内容,完全满足可维护性要求,适配绝大多数数据库环境。
内容的提问来源于stack exchange,提问作者Timur Shtatland
相关产品推荐
相关产品推荐

