【问题标题】:Parameterized/Prepared Statements usage pg-promise参数化/准备好的语句使用 pg-promise
【发布时间】:2017-04-17 15:46:35
【问题描述】:

我正在使用 koa v2pg-promise。我尝试在参数化/准备语句中做一个简单的SELECT 2 + 2; 来测试我的设置:

// http://127.0.0.1:3000/sql/2
router.get('/sql/:id', async (ctx) => {
  await db.any({
    name: 'addition',
    text: 'SELECT 2 + 2;',
  })
    .then((data) => {
      console.log('DATA:', data);
      ctx.state = { title: data }; // => I want to return num 4 instead of [Object Object]
    })
    .catch((error) => {
      console.log('ERROR:', error);
      ctx.body = '::DATABASE CONNECTION ERROR::';
    })
    .finally(pgp.end);

  await ctx.render('index');
});

在模板中呈现[Object Object] 并将其从pg-monitor 返回到控制台:

17:30:54 connect(postgres@postgres)
17:30:54 name="addition", text="SELECT 2 + 2;"
17:30:54 disconnect(postgres@postgres)
DATA: [ anonymous { '?column?': 4 } ]

我的问题:

我想将结果4 存储在ctx.state 中。不知道如何在[ anonymous { '?column?': 4 } ]内访问?

感谢您的帮助!

编辑:

我在官方 wiki 中找到了另一个 recommended(1) ways(2) 来处理命名参数。

// http://127.0.0.1:3000/sql/2
router.get('/sql/:id', async (ctx) => {
  const obj = {
    id: parseInt(ctx.params.id, 10),
  };
  await db.result('SELECT ${id} + ${id}', obj)
    .then((data) => {
      console.log('DATA:', data.rows[0]['?column?']);
      ctx.state = { title: data.rows[0]['?column?'] }; // => 4
    })
    .catch((error) => {
      console.log('ERROR:', error);
      ctx.body = '::DATABASE CONNECTION ERROR::';
    })
    .finally(pgp.end);

  await ctx.render('index');
});

我将any 对象更改为result,它返回原始文本。比我访问号码4 像一个javascript 对象。难道我做错了什么?还有其他方法可以访问此值吗?

推荐的、更快速、更安全的使用方法是什么?

【问题讨论】:

    标签: javascript sql node.js koa pg-promise


    【解决方案1】:

    由于你只请求一个值,你应该使用方法one

    const {value} = await db.one({
        name: 'addition',
        text: 'SELECT 2 + 2 as value',
    }); // value = 4
    

    对于这样的例子,你不能使用类型 PreparedStatementParameterizedQuery,因为它们在服务器端格式化查询,而 PostgreSQL 不支持像 $1 + $1 这样的语法。

    真正的问题是——你真的需要这些类型吗?

    【讨论】:

    • 我想使用一种不受sql注入的查询方法。 API 文档和 reddit 答案中的最佳实践部分表明这是这样做的方法(所以我不知道我是否真的需要它)。我的应用程序一开始不会做任何发布请求(数据库将像 json 文件或 API 一样工作)。路由将决定从数据库(URL 参数)中查询什么。我的第二个例子在我看来有一个简单的语法。为什么只推荐第一个,你有什么反对意见吗?
    • pg-promise 提供自己的 SQL 注入保护。例如,请参阅SQL Names,您应该将其用于任何动态列;)第二个示例中没有具体内容。并且您应该始终命名计算列,以便能够直接解决它们。
    • 我最终得到了这个实现:db.one('SELECT ${id} + ${id} as VALUE;', { id: parseInt(ctx.params.id, 10) }, v => v.value),它的工作原理。我在v.value 之前省略了[]+。数组[]+ 在这里做了什么?
    • + = parseInt, [] 是一个空的参数列表。
    猜你喜欢
    • 2021-07-24
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 2020-04-18
    相关资源
    最近更新 更多