如何DRY优化UNION ALL连接两个相似跨Schema SELECT的SQL代码?
可实现的两种方案
方案1:数据库端动态SQL拼接(无需额外工具,单脚本完成)
核心逻辑是把公共查询逻辑定义为字符串模板,批量替换schema占位符后拼接为完整SQL执行,所有主流数据库都支持该逻辑,以下是MySQL语法示例:
-- 定义公共查询模板,? 作为schema占位符 SET @query_template = ' SELECT a.column_a, b.column_b, c.column_c FROM ?.table_a AS a INNER JOIN ?.table_b AS b ON a.id_b = b.id INNER JOIN ?.table_c AS c ON b.id_c = c.id WHERE a.column_a LIKE ''something%'' '; -- 替换占位符并拼接UNION ALL逻辑 SET @final_sql = CONCAT( REPLACE(@query_template, '?', 'schema_A'), ' UNION ALL ', REPLACE(@query_template, '?', 'schema_B') ); -- 执行最终SQL PREPARE exec_stmt FROM @final_sql; EXECUTE exec_stmt; DEALLOCATE PREPARE exec_stmt;
不同数据库的动态SQL执行语法略有差异:
- PostgreSQL 可使用
EXECUTE语句执行拼接后的SQL - SQL Server 可使用
sp_executesql存储过程执行
该方案只需要修改@query_template里的公共逻辑,所有schema的查询逻辑会自动同步。
方案2:本地编辑器/脚本替换(无数据库语法依赖)
如果不想使用动态SQL,可只维护一份公共查询模板,用本地工具批量替换占位符生成最终执行的SQL,适合跨数据库场景使用。
- 先创建模板文件
query_template.sql,用自定义标记作为schema占位符:
SELECT a.column_a, b.column_b, c.column_c FROM {{schema}}.table_a AS a INNER JOIN {{schema}}.table_b AS b ON a.id_b = b.id INNER JOIN {{schema}}.table_c AS c ON b.id_c = c.id WHERE a.column_a LIKE 'something%'
- 用本地工具批量替换生成最终SQL,比如用shell命令可以直接生成可运行的脚本:
(sed 's/{{schema}}/schema_A/g' query_template.sql && echo "UNION ALL" && sed 's/{{schema}}/schema_B/g' query_template.sql) > final_exec.sql
VS Code、Notepad++等编辑器的批量替换功能也可以实现同样效果。
注意:如果后续需要新增更多schema查询,只需要在拼接处新增一次占位符替换逻辑即可,无需重复编写查询主体。
内容的提问来源于stack exchange,提问作者Pahbloo Marks
相关产品推荐
相关产品推荐

