转义 PostgreSQL 字符串值

Posted

技术标签:

【中文标题】转义 PostgreSQL 字符串值【英文标题】:Escape PostgreSQL string values 【发布时间】:2019-01-21 14:54:21 【问题描述】:

我正在尝试向我的 postgres 数据库中插入超过 70k 的值。但是,每一行都有不同类型的特殊字符。当我插入时,我得到了通常的错误。例如: syntax error at or near ".5"。我正在使用模块 pg-promise。在我正在使用的代码下方:

  function pg_insert(x) 
        var name = x["name"];
        var lastName = x["lasname"];

        var sql = `insert into table(name, lastname)`;
        var values = `values ($name,$lastname)`;

        pg.db
        .none(sql + values)
        .then(data => )
        .catch(err => 
            console.log(err);
        );
    

任何帮助将不胜感激。

谢谢

【问题讨论】:

$name 字符串插值吗?如果是,我建议使用参数化查询来避免引用问题和可能的 SQL 注入。 我该怎么做? Nvm,刚刚找到了方法。谢谢! 【参考方案1】:

正如 Lukasz 所说,使用Parameterized Query:

  function pg_insert(x) 
    const name = x['name'];
    const lastName = x['lasname'];

    const sql = 'insert into table(name, lastname) values ($1, $2)';
    const values = [name, lastname];

    pg.db
    .none(sql, values)
    .then(data => )
    .catch(err => 
      console.log(err);
    );
  

你也可以使用Named Parameters:

  function pg_insert(x) 
    const sql = 'insert into table(name, lasname) values ($name, $lastname)';

    pg.db
    .none(sql, x)
    .then(data => )
    .catch(err => 
      console.log(err);
    );
  

但是,正如pg-promise Named Parameters documentation中提到的:

请记住,虽然属性值 null 和 undefined 都被格式化为 null,但当属性不存在时会引发错误。

如果您传递的对象x 中的任何属性不存在(例如x.namex.lasname "name": "Joe" (注意缺少的lasname 属性)),那么上面的命名参数示例代码将产生错误。

正如vitally-t(库创建者)所提到的,pg-promise 中有helper methods 可以帮助解决缺失的数据。但是,如果您不能保证将传递到查询中的数据的形状,并且对添加清理数据所需的代码不感兴趣,那么参数化查询可能是更简单的防故障选择。

由读者决定哪种方法最适合他们的用例。

【讨论】:

Parameterized Queries 的建议可能放错了地方。库pg-promise 本身提供了几种处理缺失值和默认值的方法,从采用此类选项的基本方法as.format 到也适用于此类默认值的helpers 命名空间。无论如何,Parameterzied Queries 在这里不是一个好的选择。【参考方案2】:

如果你正确使用Named Parameters,那么它会起作用:

function pg_insert(x) 
    pg.db.none('INSERT INTO table(name, lastname) VALUES($name, $lastname)', x)
    .then(data => )
    .catch(err => 
        console.log(err);
    );

更新

我还修改了official documentation 以包括以下内容:

警告:永远不要在 ES6 模板字符串中使用 $ 语法,因为它们不知道如何为 PostgreSQL 格式化值。在 ES6 模板字符串中,您只能使用以下 4 个选项之一 - $()$<>$[]$//

...为了更清楚。

【讨论】:

以上是关于转义 PostgreSQL 字符串值的主要内容,如果未能解决你的问题,请参考以下文章

org.postgresql.util.PSQLException:没有为参数 1 指定值。- Postgres

NodeJS 加密到 Postgres 的连接字符串

postgres 注意事项

为啥 Django 将 postgres JSONField 值作为字符串返回?

错误:Postgresql 中的日期/时间字段值超出范围

我应该在 Django DATABASE ENGINE 中使用哪个 Postgres 值?