You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:33:25