javascript - 节点:使用变量替换管理 SQL 文件
问题描述
我有大型 SQL 语句,我想将它们存储为单独的文件(带有语法突出显示等)。我喜欢这里提出的公认解决方案。
在我的用例中,我用 Javascript Template Literal 语法编写 SQL 来进行变量替换。所以我的文件看起来像
-- some_file.sql
select col1, col2, col3
from my_table
where col1 = '${val1}'
and col2 between ${val2} and ${val3}
事实上,这种编写查询的方式最初是在查询增长并需要自己的文件之前使用模板文字开始的。
问题是如何实现模板文字,例如对使用读取的查询字符串进行评估,fs.readFileSync
而不必执行可怕的操作eval
?我查看了es6-template-render,但是该实现不适合执行上下文中的变量;即不指定单独的context
参数,而是在运行时隐式使用环境中可用的变量(全局/局部)。
任何指针?
解决方案
如果我的假设不正确,我们深表歉意,但周围的引号'${val1}'
表明您打算使用字符串替换而不是参数化查询。不要那样做。:-) 永远不要使用字符串替换将值放入 SQL 查询中。让我把你介绍给我的朋友鲍比:
请改用参数化查询。
例如,您可能会使用与您非常相似的格式,只是没有任何引号${val1}
:
select col1, col2, col3
from my_table
where col1 = ${val1}
and col2 between ${val2} and ${val3}
然后您的代码可以将其转换为适合您的 DB API 的查询。他们中的许多人使用?
占位符,例如(这里我node-mysql2
用作 DB API,但特定的 API 不是重点):
const rexParam = /(?<!\$)\$\{([^}]+)\}/g;
function doQuery(sql, params) {
return new Promise((resolve, reject) => {
const values = [];
const preppedSql = sql.replace(rexParam, (_, paramName) => {
const value = params[paramName];
if (value === undefined) { // Or do an `in` check if you want to allow `undefined`
throw new Error(`Missing parameter ${paramName}`);
}
values.push(value);
return "?";
});
return connection.execute(
preppedSql,
values,
function(err, results, fields) {
if (err) {
reject(err);
} else {
resolve({results, fields});
}
}
);
});
}
这会在字符串中旋转,将${val1}
和 等标记替换为并?
同时填充要传递给参数化查询函数的值数组。
(请注意负面的lookbehind,因此它$${...}
不会被扩展,就像在模板文字中一样。正则表达式有点原始,但我认为应该足以满足SQL......)
现场示例只是转储字符串和值:
const sql =
"select col1, col2, col3\n" +
"from my_table\n" +
"where col1 = ${val1}\n" +
"and col2 between ${val2} and ${val3}";
const rexParam = /(?<!\$)\$\{([^}]+)\}/g;
function doQuery(sql, params) {
const values = [];
const preppedSql = sql.replace(rexParam, (_, paramName) => {
const value = params[paramName];
if (value === undefined) { // Or do an `in` check if you want to allow `undefined`
throw new Error(`Missing parameter '${paramName}'`);
}
values.push(value);
return "?";
});
console.log(preppedSql);
console.log(values);
}
doQuery(sql, {val1: "one", val2: 2, val3: 20});
推荐阅读
- google-sheets - 当行被移动并且上面的行发生变化时在上面添加列
- r - 如何在r中为回归线上方和下方的ggplot点着色?
- python - 尽管 Big-O 相同,为什么这两个函数的性能差异如此之大?
- arrays - How to sort list by sub list value in flutter?
- kubernetes-ingress - haproxy-ingress 多个后端规则
- google-apps-script - Google Apps 脚本“脚本属性”实际上是“项目属性”吗?正确的范围是多少?
- java - Web 应用程序监听服务器事件的最佳方式
- android - 了解android中的隐藏过程
- javascript - 反应导航 - 无法读取未定义的属性“推送”
- python - 为什么“超级”的论点很重要?