pg-promise upsert on postgresql 9.4.11

时间:2017-10-30 22:25:00

标签: node.js postgresql postgresql-9.4 upsert pg-promise

我进行了广泛的搜索,但我无法解决这个简单的问题。 我在nodejs中编程,并使用pg-promise将我的JSON文件动态存储到postgres 9.4.11数据库中(我不允许升级数据库)。 我的JSON每个包含大约一百列,我已经将它正确解析为三个对象。 田野 2.列 3.表 当我这样做时,Pg-promise完美地工作:

//-- connection details would be up here  const db = pgp (conn);--
//Insert statement is below


 for (var i=0; i<Object.keys(fields).length; i++){

    const data = [fields[i]];
    const cs = new pgp.helpers.ColumnSet(columns[i]);
    const table = new pgp.helpers.TableName(tables[i],"public");
    const insert = pgp.helpers.insert(data,cs,table);

       db.none(insert)
        .then(data => {
            console.log("Success! Record inserted for " + table);
        })
        .catch(error => {
            //error
            console.log("ALERT!!! Something went wrong with Record in table " + table);
        });
    }

但是,当然,我在postgresql 9.4.11上,我不能使用简单的:

const insert = pgp.helpers.insert(data,cs,table) + " ON CONFLICT (id1, uid2, xid3) DO NOTHING";

仅执行新项目的插入,因为UPSERTS仅从9.5开始提供。

我的查询每次运行大约需要2000行插入,我对此很满意。

我对此很陌生,我希望也许在我的谷歌搜索时间里,我忽略了直接的解决方案。

我见过的最接近的解决方案是存储过程,但我不确定如何实现它。

拜托,stackoverflow,你可能是我唯一的希望!

我只是想确保在id1,uid2和xid3上匹配的每一行都没有插入到我的postgres db中。

1 个答案:

答案 0 :(得分:0)

所以我学到了关于postgres的一些事情。但首先,这是最终为我工作的代码:

 for (var i=0; i<Object.keys(fields).length; i++){

    const data = [fields[i]];
    const cs = new pgp.helpers.ColumnSet(columns[i]);
    const table = new pgp.helpers.TableName(tables[i],"public");
    const insert = pgp.helpers.insert(data,cs,table);
         db.none( 'BEGIN WORK; LOCK TABLE public.'
        + tables[i] + ' IN SHARE ROW EXCLUSIVE MODE; ' 
        + 'INSERT INTO public.'+tables[i]+ ' ('+ columns[i]+')' 
        + 'SELECT 'google.com','another value', 'etc...' WHERE NOT EXISTS(SELECT 1 FROM public.'
        +tables[i] +' WHERE id1 ='+fields[i].id1 
        +' AND uid2 ='+fields[i].uid2 
        +' AND xid3 ='+fields[i].xid3 +');' 
        + 'COMMIT WORK;' ) 
    }

所以我学到的是postgres没有看到双引号内的项目作为值,而是作为列。 所以我不得不取出我的values数组并删除双引号并用单引号替换,这允许postgres接受查询。

使用pg-promise将postgres查询拼接在一起可能看起来很麻烦,但这是我发现使用for循环加载数百行宽数百列的数据的最佳方式

注意,我有一个数值数组,但我把它们写成&#39; google.com&#39;,&#39;另一个值&#39;,&#39;等...&#39;这样你就可以看到双引号和单引号。