2

我正在尝试运行一个脚本,从一个数据库中提取记录,然后将记录插入另一个数据库,但在插入步骤中,我不断遇到此错误 8 或 9 次重复。

我对 node-mssql 库不是很熟悉,如果能对这里发生的事情有任何见解,我将不胜感激!我附上了堆栈跟踪和脚本的副本。

  const sql = require('mssql')
        const humENV = require('../env').humENV
        const rbENV = require('../env').rbENV
        const logger = require('./logger')

        const getReviewHumanatic = async () => {
          try {
            let pool = await sql.connect(humENV.SQL_CONFIG)
            let req = await pool.request()
            .query(`
              WITH cte 
              AS (SELECT DISTINCT TOP 500 htaskid, 
                  ht.frn_leuserid, 
                  ht.frn_callid, 
                  ht.frn_hcatid, 
                  ht.frn_hcat_optionid, 
                  frn_lskinid, 
                  cq.duration_seconds, 
                  add_path, 
                  CASE 
                    WHEN call_queueid IS NULL THEN 3 
                    ELSE 1 
                  END AS status, 
                  CASE 
                    WHEN hcab_reviewid IS NULL THEN 0 
                    ELSE 1 
                  END AS HCAB 
                  FROM   htask ht 
                        LEFT JOIN call_queue cq 
                          ON ht.frn_callid = cq.frn_callid 
                        LEFT JOIN hcab_review hr 
                          ON hr.frn_callid = cq.frn_callid 
                            AND ht.frn_leuserid = hr.frn_leuserid) 
              SELECT Isnull(frn_callid, 0)       AS frn_callid,
                    Isnull(frn_hcatid, 0)        AS frn_hcatid, 
                    Isnull(HCAB, 0)              AS HCAB, 
                    Isnull(frn_hcat_optionid, 0) AS frn_hcat_optionid, 
                    Isnull(frn_lskinid, 0)       AS frn_lskinid, 
                    Isnull(frn_leuserid, 0)      AS frn_leuserid, 
                    Isnull(status, 0)            AS status, 
                    Isnull(duration_seconds, 0)  AS duration_seconds, 
                    Isnull(add_path, '')         AS add_path, 
                    Isnull(htaskid, 0)           AS htaskid 
              FROM   cte 
              ORDER BY frn_callid
              `)
            if (req.recordset.length !== 0) {
              console.log(req.recordset)
              logger.info('returning query records')
              return req.recordset
            }
            pool.close()
          } catch (err) {
            logger.error(err)
          }
        }

        const insertRebase = async (data) => {
          try {
            sql.close()
            let pool = await sql.connect(rbENV.SQL_CONFIG)
            for (let i = 0; i < data.length; i++) {
              console.log(data[i])
              let req = await pool.request()
              .input('frn_callid', sql.BigInt, data[i].frn_callid)
              .input('frn_categoryid', sql.Int, data[i].frn_hcatid)
              .input('HCAB', sql.Int, data[i].HCAB)
              .input('frn_answer_optionid', sql.Int, data[i].frn_hcat_optionid)
              .input('frn_leuserid', sql.Int, data[i].frn_leuserid)
              .input('frn_lskinid', sql.Int, data[i].frn_lskinid)
              .input('frn_statusid', sql.TinyInt, data[i].status)
              .input('reviewid', sql.Int, data[i].htaskid)
              .input('call_duration', sql.Int, data[i].duration_seconds)
              .input('HCAB_trigger', sql.VarChar, data[i].add_path)
              .query('SET IDENTITY_INSERT review ON; INSERT INTO review (frn_callid, frn_categoryid, HCAB, frn_answer_optionid, frn_leuserid, frn_lskinid, frn_statusid, reviewid, call_duration, HCAB_trigger) VALUES (@frn_callid, @frn_categoryid, @HCAB, @frn_answer_optionid, @frn_leuserid, @frn_lskinid, @frn_statusid, @reviewid, @call_duration, @HCAB_trigger)', function (err, recordset) {
                if (err) {
                  logger.error(err)
                  console.log(err)
                }
                pool.close()
              })
            }
          } catch (err) {
            logger.error(err)
          }
        }

        const initializeReview = async () => {
          try {
            const humData = await getReviewHumanatic()
            insertRebase(humData)
          } catch (err) {
            console.log(err)
          }
        }

        initializeReview()

我查看了这个问题NPM MSSQL - error: uncaughtException: Cannot read property 'release' of null但看起来没有确定的解决方案。

错误堆栈跟踪:

堆栈跟踪

编辑:自从我的原始帖子以来,我已将插入查询转换为preparedstatement:

const insertRebase = async (data) => {
  try {
    sql.close()
    let pool = await sql.connect(rbENV.SQL_CONFIG)
    for (let i = 0; i < data.length; i++) {

      let ps = new sql.PreparedStatement(pool)
      ps.input('frn_callid', sql.BigInt)
      ps.input('frn_categoryid', sql.Int)
      ps.input('HCAB', sql.Int)
      ps.input('frn_answer_optionid', sql.Int)
      ps.input('frn_leuserid', sql.Int)
      ps.input('frn_lskinid', sql.Int)
      ps.input('frn_statusid', sql.TinyInt)
      ps.input('reviewid', sql.Int)
      ps.input('call_duration', sql.Int)
      ps.input('HCAB_trigger', sql.VarChar)
      ps.prepare(`SET IDENTITY_INSERT review ON; INSERT INTO review (frn_callid, frn_categoryid, HCAB, frn_answer_optionid, frn_leuserid, frn_lskinid, frn_statusid, reviewid, call_duration, HCAB_trigger) VALUES (@frn_callid, @frn_categoryid, @HCAB, @frn_answer_optionid, @frn_leuserid, @frn_lskinid, @frn_statusid, @reviewid, @call_duration, @HCAB_trigger)`, err => {
        if (err) {
          console.log(err)
          logger.error(err)
        } else {
          ps.execute({frn_callid: data[i].frn_callid, frn_categoryid: data[i].frn_hcatid, HCAB: data[i].HCAB, frn_answer_optionid: data[i].frn_hcat_optionid, frn_leuserid: data[i].frn_leuserid, frn_lskinid: data[i].frn_lskinid, frn_statusid: data[i].status, reviewid: data[i].htaskid, call_duration: data[i].duration_seconds, HCAB_trigger: data[i].add_path}, (err, result) => {
            if (err) {
              console.log(err)
              logger.error(err)
            } else {
              ps.unprepare(err => {
                if (err) {
                  console.log(err)
                  logger.error(err)
                }
              })
            }
          })
        }
      })
    }
  } catch (err) {
    logger.error(err)
  }
}

我不确定为什么preparedstatement 解决方案比以前的解决方案有效,但是preparedstatement 解决方案似乎没有出错并正确插入所有记录。

至于 sql.close() 全局连接问题,做

const getReviewHumanatic = async () => {
  try {
    let pool1 = await sql.connect(SQL_CONFIG1)
    let req = await pool1.request()
}

创建全局连接?我假设它正在创建本地连接,如果我这样做了

let pool2 = await sql.connect(SQL_CONFIG2)

它将创建一个单独的 sql 连接,但似乎并非如此,因为sql.close()在创建 pool2 之前我无法运行该脚本。

我检查了 node-mssql 文档,看起来如果我在没有池规范的情况下执行请求,它将使用全局 sql 连接;也许这就是我的脚本正在发生的事情?https://www.npmjs.com/package/mssql#request

4

0 回答 0