我正在重写一个旧的API,我正在尝试使用节点模块mssql将多个值立即插入MSSQL-Server(2008)数据库中。现在,我可以以某种方式执行此操作,但是我想遵循最佳做法。我已经完成了研究,并尝试了很多事情来实现自己的目标。但是,我找不到一个可以正常工作的解决方案。
您可能会想:
好吧,您正在重写这个API,所以一定有一种方法可以做到这一点,并且可以正常工作吗?
当然,您是对的,它之前已经工作过,但是...在某种程度上让我不愿意在重写中使用它。让我向您展示它是如何完成的(当然添加了一点抽象):
const request = new sql.Request(connection);
let query = "INSERT INTO tbl (col1, col2, col3, col4) VALUES ";
for (/*basic for loop w/ counter variable i*/) {
query += "(1, @col2" + [i] + ", @col3" + [i] + ", (SELECT x FROM y WHERE z = @someParam" + [i] + "))";
// a check whether to add a comma or not
request.input("col2" + [i], sql.Int(), values[i]);
// ...
}
request.query(query, function(err, recordset) {
// ...
}
虽然这仍然有效,但我不太认为这可以称为“最佳做法” 之类的东西。这也显示了最大的问题:子选择用于插入值。
起初,我尝试了可能最简单的事情:
// simplified
const sQuery = "INSERT INTO tbl (col1, col2, col3, col4) VALUES (1, @col2, @col3, (SELECT x FROM y WHERE z = @col4));";
oPool.request().then(oRequest => {
return oRequest
.input("col2", sql.Int(), aValues.map(oValue => oValue.col2))
.input("col3", sql.Int(), aValues.map(oValue => oValue.col3))
.input("col4", sql.Int(), aValues.map(oValue => oValue.col4))
.query(sQuery);
});
我会说,这是一个很好的猜测,实际上工作得还不错。 除了那一部分,它忽略了第一个项目之后的每个项目……这使它变得毫无用处。所以,我尝试了...
...我想,那样做就可以了。但是-令人惊讶-没有,仍然只插入了第一项。
在这一点上,我真的开始寻找解决方案,因为第二个解决方案只是在模块文档中进行快速搜索。 我偶然发现this answer并立即尝试。 我的终端没多久就吐出一个
RequestError:“?”附近的语法不正确。
那么多。
一些进一步的研究导致了bulk inserting。 很有趣,很酷的功能,并且可以用OP的解决方案很好地更新问题! 我在这里开始时有些挣扎,但最终看起来确实不错:插入了多条记录,值似乎还可以。
直到我添加了子查询。将其用作声明的列的值不会引起任何错误,但是在检查表的值时,它只是显示
0作为该列的值。一点也不令人惊讶,但是每个人都可以做梦,对吧?
我真的不知道该怎么想:
// simplified
Promise.all(aValues.map(oValue => {
return oPool.request().then(oRequest =>
oRequest
.input("col2", sql.Int, oValue.col2)
.input("col3", sql.Int, oValue.col3)
.input("col4", sql.Int, oValue.col4)
.query(sQuery);
});
});
它可以完成工作,但是如果由于某种原因请求失败,则其他非失败插入仍将被执行,即使应该不可能。
即使最后一个方法的主要问题是即使失败也要继续,所以我尝试围绕它建立事务。所有查询是否成功?好的,提交。任何查询都有errpr吗?好吧,只是回滚比。因此,我建立了一个事务,将Promise.all结构移入其中,然后重试。 Aaand下一个错误在我的终端中弹出:
TransactionError: Can't acquire connection for the request. There is another request in progress.
如果您走到了这么远,我不需要告诉您问题出在哪里。
我还没有尝试过的(并且我不认为我会尝试这种方法)是使用事务处理方式并依次调用语句。我不认为这是要走的路。
而且我也不认为应该使用惰性方式,因为它可以对要插入的每条记录使用单个请求,而在某种程度上可以仅使用一个请求来完成。我不知道,只是某种程度上,现在不在我的脑海中。所以请,如果您有什么可以帮助我的,请告诉我。
此外,如果您发现我的代码有任何其他错误,请随时指出。我不认为自己是初学者,但我也不认为学习会永远结束。 :)