不止like和in:cj2sql扩展SQL关键字全清单,between、exists、caseWhen一次讲透
2026/9/24 17:24:44 网站建设 项目流程

不止like和in:cj2sql扩展SQL关键字全清单,between、exists、caseWhen一次讲透

【免费下载链接】cj2sql将仓颉代码转换成 SQL项目地址: https://gitcode.com/Cangjie-SIG/cj2sql

cj2sql 是一个将仓颉代码转换成 SQL 的开源工具,而它的扩展 SQL 关键字是最让新手上头的功能:用仓颉函数调用的方式写出betweenexistscaseWhenlikein等 SQL 条件,编译期自动展开成标准 SQL,免去手工拼接字符串的痛苦。🚀

一、cj2sql 扩展 SQL 关键字全清单

cj2sql 通过枚举ExtSql声明所有扩展 SQL 关键字(定义见 src/sql/use.cj),完整清单如下:

关键字作用生成的 SQL
like/notLike原生模糊匹配col LIKE 'abc'
likeLeft/likeRight/likeAll左/右/全模糊col LIKE 'abc%'
notLikeLeft/notLikeRight/notLikeAll反向模糊col NOT LIKE ...
inn/notIn列表包含col IN (1, 2, 3)
between/notBetween区间判断col BETWEEN 1 AND 5
exists/notExists子查询存在性EXISTS (SELECT ...)
caseWhen条件表达式CASE WHEN ... END
null/notNull判空(配合iscol IS NULL
asc/desc排序方向(配合iscol ASC / DESC
not逻辑非NOT (expr)

二、两步上手:导入 + 声明

使用规则非常简单:ExtSql.关键字(参数列表),前缀ExtSql.可以省略。

import cj2sql.macros.cjSql // 宏 import cj2sql.sql.ExtSql // 扩展 SQL 关键字 import cj2sql.sql.select

只需给函数标注@cjSql宏,函数体内的 DML 代码就会在编译期被解析、展开成 SQL。整个解析流程可以这样理解:

其中「扩展关键字」就是由CallExprParser分发给BaseCallExtKeyParser系列解析器完成的(参见 src/macros/parser/call_ext_keyword_parser.cj)。

三、between:区间条件怎么写

规则:between(列, 开始值, 结束值),反向用notBetween

let five = 5 between(user.id, 1, five) // ==> user.id BETWEEN 1 AND ?

参数支持字面量或变量,变量会被生成为绑定参数?,天然防止 SQL 注入。解析逻辑见 call_ext_key_between_parser.cj,参数个数不对时会在编译期直接报错,非常省心。

四、exists:子查询存在性判断

规则:exists(子查询),反向用notExists

exists(user.subQuery<RoleTest> { r => r.select { r.id }.filter { r.id == 2 } }) // ==> EXISTS (SELECT r.id FROM role_test r WHERE r.id = 2)

「查主表 + 判断关联表里是否存在记录」这类常见需求,一行exists就搞定,不用手写嵌套查询字符串。解析器在 call_ext_key_exists_parser.cj。

五、caseWhen:把 if/match 直接变 CASE WHEN

规则:caseWhen(if或match表达式),可用作 select 列(需配合as)。

caseWhen(if (user.id > 1) { user.id } else { user.roleId }) == 1 // ==> (CASE WHEN user.id > 1 THEN user.id ELSE user.role_id END) = 1

写法很巧妙:仓颉里的if/elsematch表达式会一一映射成 SQL 的WHEN/THEN/ELSE,多级else if也支持,解析实现见 call_ext_key_case_parser.cj。

六、like 与 in:不只是简单匹配

除了原生like,cj2sql 还提供了likeLeft/likeRight/likeAll三种模糊匹配,无需手动拼%

likeRight(user.name, 'cang') // ==> user.name LIKE 'cang%' likeAll(user.name, 'jie') // ==> user.name LIKE '%jie%' inn(user.id, 1, 2, 3) // ==> user.id IN (1, 2, 3)

inn还支持传入数组变量,甚至直接传入子查询:

let list = [10, 20, 30] inn(user.id, list) // ==> user.id IN (?, ?, ?)

七、null / notNull / asc / desc:用 is 关键字

这四个关键字配合仓颉的is语法使用,读起来和原生 SQL 几乎一致:

user.id is null // ==> user.id IS NULL user.id is notNull // ==> user.id IS NOT NULL user.roleId is desc // ==> user.role_id DESC

八、底层原理:一切皆语法树节点

每个扩展关键字最终都会转成 SQL 语法树中的表达式节点(如SqlBetweenExprSqlExistsSqlCaseExpr),再经方言层渲染成 MySQL / Oracle / PostgreSQL / SQLServer 的具体 SQL,结构可参考官方设计文档 doc/design.md:

表达式节点源码集中在 src/sql/expr/,工具方法见 ExprUtil。

九、总结

cj2sql 的扩展 SQL 关键字让「写 SQL」变成了「写仓颉」:

  • 清单全覆盖:like 家族、in、between、exists、caseWhen、判空与排序一次配齐
  • 编译期展开:参数错误在编译阶段就报错,运行零风险
  • 多数据库方言:同一份代码可渲染多种数据库 SQL

更多实战示例(增删改查全流程)可直接阅读 doc/use.md,跟着文档走一遍即可上手。

【免费下载链接】cj2sql将仓颉代码转换成 SQL项目地址: https://gitcode.com/Cangjie-SIG/cj2sql

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询