我进行了广泛的搜索,但我无法解决这个简单的问题。 我在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中。
答案 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;这样你就可以看到双引号和单引号。