# SQL 模板(`xlyEntry/templesql/`) 框架在 `xlyEntry/src/main/resources/templates/templesql/` 下保存了一小组 **SQL 脚手架**。运行时不会用它们即时生成 SQL;它们是工程师编写新存储过程时复制并填充的模板,最终由框架通过[通用存储过程分发](proc-dispatch.md)调用。 ## 已提供的脚手架 实时树中有 8 个文件: | 文件 | 脚手架内容 | |---|---| | `sSaveProName.sql` | 标准保存过程,带约定参数列表和 OUT code | | `sSaveProNameBefore.sql` | 保存前校验过程 | | `sDeleteProName.sql` | 标准删除过程 | | `sProcName.sql` | 通用逻辑过程(审计 / 计算 / 检查) | | `sButtonParam.sql` | 按钮触发的过程,通过 `gdsconfigformslave.sButtonParam` 参数化 | | `sp_btn_calc.sql` | 按钮驱动计算过程 | | `sProTempleByDb.sql` | 按数据库 / 租户切换行为的过程 | | `sSqlStr.sql` | `gdsconfigformmaster.sSqlStr` 的 SELECT 形状脚手架 | ## 占位符约定 每个脚手架使用 `{placeholderName}` 语法(单花括号,不转义)。来自 `sSaveProName.sql` 的示例: ```sql DROP PROCEDURE IF EXISTS {sProName}; CREATE PROCEDURE {sProName}( IN sGuid VARCHAR(100), IN sFormGuid VARCHAR(100), IN sLoginId VARCHAR(100), IN sBrId VARCHAR(100), IN sSuId VARCHAR(100), OUT sCode INT(1), OUT sReturn LONGTEXT ) BEGIN -- ... placeholder logic ... Update {sMasterTableName} AS A JOIN {sSlaveTableName} AS B ON A.sId = B.sProductId SET A.dProductQty = B.dProductQty WHERE B.sId = sGuid AND B.sBrandsId = sBrId AND B.sSubsidiaryId = sSuId; END ``` 工程师复制该文件,填入 `{sProName}`、`{sMasterTableName}`、`{sSlaveTableName}`,把占位逻辑替换成真实业务规则,并将生成的 SQL 应用到目标 schema。 ## 占位符用途 - `{sProName}`:过程名,例如 `Sp_Sales_Save`。 - `{sMasterTableName}`、`{sSlaveTableName}`、`{sAllTableName}`:该过程操作的单据表族。 - 其他占位符取决于具体脚手架。 ## 为什么这是模板库,不是代码生成器 框架**不会**基于元数据从这些模板自动生成过程。脚手架存在是因为 xly 的过程遵循共同形状;复制脚手架能保证新过程: - 接受 [通用分发](proc-dispatch.md) 可调用的标准参数列表 `(sGuid, sFormGuid, sLoginId, sBrId, sSuId)`。 - 通过标准 `OUT sCode INT, OUT sReturn LONGTEXT` 返回成功 / 错误。 - 遵守多租户过滤 `sBrandsId = sBrId AND sSubsidiaryId = sSuId`。 不遵守这些约定的过程无法通过通用分发调用,只能从自定义 Java 代码调用。 ## 另见 - [通用存储过程分发](proc-dispatch.md):过程写好后框架如何调用。 - [切片 5(每客户 SQL 覆盖)](../../slices/05-customer-sql-override.md):客户需要替换标准过程时,复用相同模板结构,但在目标 schema 上 `DROP` 并 `CREATE` 一个覆盖版本。