预编译SQL的占位值,参考上一节内容。
值的字符串化。如果使用了JSON类型的字段就经常要对参数值进行字符串化JSON.stringify()
再传给SQL执行。可以在选项设置框中把需要字符串化值写在str
对象中。
比如财务系统中根据指定账套/期间/凭证字【查凭证】:select * from 凭证 where x->'账套' = $1 {where}
,选项设置{ str: { v: [1], where: [1, 2] }, where: ["x->'期间' = ??", "x->'字' = ??"] }
,执行$sql.查凭证(["众触科技"], { where: { 1: "2024-03", 2: "记" })
,将得到SQLselect * from 凭证 where x->'账套' = $1 and x->'期间' = $2 and x->'字' = $3
和参数值['"众触科技"', '"2024-03"', '"记"']
。
类型转换,把查询结果中的字符串类型的字段转换成数值(int或float)。
聚合函数的返回结果是字符串,因为它们的数值有可能太大从而超过可以安全表示的最大整数(9007199254740991),从而引起计算精度问题;Postgres里bigint/numeric类型的字段和MySQL的decimal返回的也是字符串 。
如果前端需要用到数值并确信不超过最大整数就可以用它转换。{ type: { int: ["商品总数"], float: ["成本总额", "销售总额"] } }
。
数据库提供的带参数的预编译SQL难以满足灵活多变的业务需求。比如开发一个多种条件组合的查询工具栏,只有所有条件都填满后再查询,不能任选一个或多个就查询,也不能选一个就自动查询;插入语句也只能同时插入所有字段,不能改一个字段就只保存一个字段。
平台提供多种占位选项让SQL更加动态灵活的同时还能保证安全,因为调用者无法逃离开发者预先定义的选项,并且平台还会把这些动态SQL转换成预编译语句再给数据库执行。
动态占位符用大括号包裹并置于SQL语句的合适位置,并在下方的选项框中用数组罗列所有允许的占位值。执行SQL时在选项参数中指定需要用到的占位名称及占位选项的下标和值。从上一节预编译占位符可以看到Postgres的参数是从1开始的,所以约定所有占位选项的下标也是从1开始的。
选择字段。比如允许全选或只选日期/名称/价格,选项中写{ select: ["*", "名称", "avg(价格) 均价"] }
;如果调用时的选项中传入{ select: [1] }
那么{select}
就会被替换成select *
,如果传入{ select: [2, 4] }
那么{select}
就会被替换成select 名称, avg(价格) 均价
查询条件。选项中可以用??
占位。比如根据给定的日期区间和名称模糊查询,选项框中则写{ where: ["日期 >= ??", "日期 <= ??", "名称 like ??"] }
;调用时传入{ where: { 1: "2024-03-01", 2: "2024-03-31", 3: "%手机%" }
,那么{where}
就会被替换成符合相应数据库语法的预编译语句,如Postgres的where 日期 >= $1 and 日期 <= $2 and 名称 like $3
和对于的占位值["2024-03-01", "2024-03-31", "%手机%"]
。
排序。比如按日期和价格排序,选项中写{ sort: ["日期", "价格"] }
;如果调用时的选项中传入{ sort: [1] }
那么{sort}
就会被替换成order by 日期
,即按日期升序排序;如果传入{ sort: [2, -1] }
那么{sort}
就会被替换成order by 价格, 日期 desc
,即先按价格升序排序再按日期降序排序。
翻页。无需设置选项直接传入数字参数,调用时传入{ limit: 25, skip: 50 }
就是每页25条返回第三页(跳过了两页)。
选项中可以设置maxLimit,当传入的limit大于它时就会被强制替换成它的值。
注意,SQL Server或Oracle需要搭配{sort}
,并把{skip}
放在{limit}
前面。
插入。无需预先设置选项直接传入对象参数,调用时传入{ 日期: "2024-03-01", 价格: 50 }
会把{insert}
替换成符合相应数据库语法的预编译语句,如Postgres的(日期, 价格) values($1, $2)
和占位值["2024-03-01", 50]
。
更新。比如只允许更新日期/名称/价格,选项框中则写{ set: ["日期", "名称", "价格"] }
,调用时传入{ 日期: "2024-03-01", 价格: 50 }
会把{set}
替换成符合相应数据库语法的预编译语句,如Postgres的set 日期 = $1, 价格 = $2
和占位值["2024-03-01", 50]
。
分组。例如{ group: ["省", "市", "rollup(部门, 性别)"] }
。
{select},{set},{where},{group}可以动静混用,如select id {select}
,update 商品 set 更新时间 = $1 {set}
,where 账套 = $1 and 日期 = $2 {where}
,group by 省 {group}
。
要求先在选项设置许可数组,调用时在选项中传入一个数字下标(从1开始)以指定许可数组中的一项。比如想让【从哪个表查数据】动态化,可以定义一个{table}
占位符,写个名为【超级查询】的SQL:select * from {table} limit 50
,允许从三个表中选一个:{ table: ["商品", "价格", "商家"] }
,调用$sql.超级查询([], { table: 2 })
,将获取价格表的前50条数据。