realm.query(sql, values, options)
Model.query(sql, values)(v2.14+)raw() 函数Raw 类heresql 辅助函数虽然 Leoric 的查询接口覆盖了大部分场景,但有时你需要直接执行原始 SQL。Leoric 提供了几种使用原始 SQL 的方式:realm.query()、Model.query()、raw() 函数以及 heresql 模板辅助函数。
realm.query(sql, values, options)通过 Realm 实例执行原始 SQL 查询:
const result = await realm.query('SELECT * FROM posts WHERE id = ?', [1]);
console.log(result.rows);
// => [{ id: 1, title: 'Hello', content: '...' }]
返回对象包含:
| 属性 | 类型 | 说明 |
|---|---|---|
rows |
Array |
查询结果行 |
fields |
Array |
列元数据(table, name) |
affectedRows |
number |
受影响的行数(INSERT/UPDATE/DELETE) |
insertId |
number |
自动生成的 ID(INSERT) |
始终使用参数化查询来防止 SQL 注入:
// 正确 - 参数化
const result = await realm.query(
'SELECT * FROM posts WHERE title = ? AND author_id = ?',
['Hello', 42]
);
// 错误 - SQL 注入风险!
const result = await realm.query(
`SELECT * FROM posts WHERE title = '${title}'`
);
可以使用 :name 语法进行命名替换:
const result = await realm.query(
'SELECT * FROM posts WHERE title = :title AND author_id = :authorId',
{
replacements: {
title: 'Hello',
authorId: 42,
},
}
);
传入 model 选项可以将结果作为模型实例返回,而非普通对象:
const result = await realm.query(
'SELECT * FROM posts WHERE id = ?',
{ model: Post, replacements: {} }
);
// result.rows 现在是 Post 实例
const post = result.rows[0];
console.log(post instanceof Post); // true
console.log(post.title);
await realm.transaction(async ({ connection }) => {
await realm.query(
'UPDATE posts SET title = ? WHERE id = ?',
['新标题', 1],
{ connection }
);
});
Model.query(sql, values)(v2.14+)从 v2.14 开始,可以直接从模型类执行原始查询:
const result = await Post.query('SELECT * FROM posts WHERE id = ?', [1]);
raw() 函数raw() 函数创建一个不会被转义的 Raw SQL 表达式。适用于在查询中使用 SQL 函数或表达式:
import { raw } from 'leoric';
// 使用 SQL 函数
await Post.update({ id: 1 }, { updatedAt: raw('NOW()') });
// UPDATE posts SET updated_at = NOW() WHERE id = 1
// 在 where 子句中使用
const posts = await Post.find({
createdAt: raw('NOW() - INTERVAL 7 DAY'),
});
也可以通过 Realm 实例访问 raw():
await Post.update({ id: 1 }, { updatedAt: realm.raw('NOW()') });
警告:
raw()会绕过转义。永远不要将用户输入直接传给raw(),否则会导致 SQL 注入漏洞。
Raw 类Raw 是底层实现类。可以直接使用或通过 Raw.build() 创建:
import { Raw } from 'leoric';
const expr = new Raw('COUNT(*)');
const expr2 = Raw.build('COUNT(*)');
heresql 辅助函数heresql 函数将多行 SQL 字符串格式化为单行查询,便于日志输出和提高源码可读性:
import { heresql } from 'leoric';
const sql = heresql(`
SELECT *
FROM posts
WHERE author_id = ?
ORDER BY created_at DESC
LIMIT 10
`);
// => 'SELECT * FROM posts WHERE author_id = ? ORDER BY created_at DESC LIMIT 10'
它会修剪每行的空白并用单个空格连接,使多行 SQL 在源码中更易读,同时生成干净的单行 SQL 用于执行。
始终使用参数化查询处理用户提供的值。永远不要将用户输入拼接到 SQL 字符串中。
谨慎使用 raw()。仅用于 SQL 函数和表达式,绝不用于用户输入。
在确实需要插值时使用 realm.escape(),但参数化查询始终是首选。
// 推荐:参数化
await realm.query('SELECT * FROM posts WHERE title = ?', [userInput]);
// 如果必须手动转义
const escaped = realm.escape(userInput);