Postgres Javascript(pg.js)动态列名

时间:2018-06-22 23:05:14

标签: javascript postgresql

我已经搜索了很多,只是没有找到答案。

我正在使用pg.js从我的Node.js服务器运行查询到Postgres数据库。我想使用1函数在两个不同的表上运行查询。所以我想这样做:

database.query("SELECT * FROM $1 WHERE $2 = $3;",
  [type, idName, parseInt(id, 10)],
  (error, result) => {});

这会导致语法错误。

error: syntax error at or near "$1"

我发现一些SO文章使用:name~将变量转换为“名称”。像这样:

database.query("SELECT * FROM $1~ WHERE $2~ = $3;",
  [type, idName, parseInt(id, 10)],
  (error, result) => {});

这将导致相同的错误。

如果我对表名进行了硬编码,并尝试仅在列名上使用〜。我收到错误消息:

error: operator does not exist: unknown ~

唯一可行的方法就是这个非常糟糕的解决方案:

database.query("SELECT * FROM "+type+" WHERE "+idName+" = $1;",
  [parseInt(id, 10)],
  (error, result) => {});

任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

您面临的问题是由于插值。动态列名和表名与注入动态值不同。

您可能想尝试一下:

npm install pg-format

var format = require('pg-format');
var sql = format('SELECT * FROM %I WHERE my_col = %L %s', 'my_table', 34, 'LIMIT 10');
console.log(sql); // SELECT * FROM my_table WHERE my_col = '34' LIMIT 10

此处有更多详细信息-https://github.com/datalanche/node-pg-format

肮脏的ES6修复程序可能是:

database.query(`SELECT * FROM ${type} WHERE ${idName} = $3;`,
      [parseInt(id, 10)],
      (error, result) => {});

如果您打算构建大量动态查询,请考虑尝试一下-https://knexjs.org/

答案 1 :(得分:1)

您不能创建准备好的语句,也不能在查询中注入动态表或列名,因为这将不允许完全准备语句。如果一定要执行预处理语句,则需要知道在PreparedStatements中必须定义输入数据类型(动态变量)和返回数据类型(返回列)。由于*将为不同的表格返回不同的net返回类型,因此上述方法将永远无法使用。例如,如果您知道始终返回一个id和一个名称,则可以在PostgreSQL中创建一个函数,如下所示:

CREATE TYPE idname AS (id int4, name text);

CREATE OR REPLACE FUNCTION dynamicidnamequery(tablename text,field text,content text)  RETURNS SETOF idname AS 
$$
DECLARE 
    r idname;
BEGIN
    FOR r IN EXECUTE 'SELECT id,name FROM '||tablename||' WHERE '||field||'='''||content||''''
    LOOP
        return next r;
    END LOOP;
END$$ language 'plpgsql';

select * from dynamicidnamequery('company','name','Amazon');

现在可以动态查询最后一个选择。

答案 2 :(得分:0)

我确实找到了部分解决方案。虽然我在PostGres网站上找不到有关此文档的任何文档,但我发现了一些在线文章,其中显示了使用CAST速记符号将字符串转换为列名的示例。

正如问题中提到的,我发现了几篇关于stackoverflow的文章,其中提到了:name作为解决方案,但对我来说有效的是::name,这是CAST的简写。 Postgres并未将name记录为数据类型,但这确实对我有用。

database.query("SELECT * FROM "+ type +" WHERE $1::name = $2;",
  [idName, parseInt(id, 10)],
  (error, result) => {});

对于表名,同一件事不起作用。