使用Node.js将多个条目插入SQL Server

时间:2018-12-10 22:17:43

标签: javascript node.js sql-server-2008 node-modules node-mssql

我正在重写一个旧的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);
});

我会说,这是一个很好的猜测,实际上工作得还不错。 除了那一部分,它忽略了第一个项目之后的每个项目……这使它变得毫无用处。所以,我尝试了...

Request.multiple = true

...我想,那样做就可以了。但是-令人惊讶-没有,仍然只插入了第一项。

使用'?'用于参数

在这一点上,我真的开始寻找解决方案,因为第二个解决方案只是在模块文档中进行快速搜索。 我偶然发现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.

如果您走到了这么远,我不需要告诉您问题出在哪里。

摘要

我还没有尝试过的(并且我不认为我会尝试这种方法)是使用事务处理方式并依次调用语句。我不认为这是要走的路。

而且我也不认为应该使用惰性方式,因为它可以对要插入的每条记录使用单个请求,而在某种程度上可以仅使用一个请求来完成。我不知道,只是某种程度上,现在不在我的脑海中。所以请,如果您有什么可以帮助我的,请告诉我。

此外,如果您发现我的代码有任何其他错误,请随时指出。我不认为自己是初学者,但我也不认为学习会永远结束。 :)

0 个答案:

没有答案